Import a crude CMOS clock driver

This still does not work though.
This commit is contained in:
Pierre Pronchery 2018-06-25 02:23:40 +02:00
parent 2e9b282606
commit e5bc6ea415
16 changed files with 494 additions and 9 deletions

View File

@ -15,6 +15,7 @@
# define ENODEV 19
# define EINVAL 22
# define ERANGE 34
# define EAGAIN 35
# define ENOSYS 78
# define ENOTSUP 86

View File

@ -1,2 +1,2 @@
subdirs=kernel,sys
dist=Makefile,elf.h,errno.h,fcntl.h,limits.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,unistd.h
dist=Makefile,elf.h,errno.h,fcntl.h,limits.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,time.h,unistd.h

21
include/time.h Normal file
View File

@ -0,0 +1,21 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#ifndef UKERNEL_TIME_H
# define UKERNEL_TIME_H
/* types */
# ifndef time_t
# define time_t time_t
typedef long long time_t;
# endif
/* functions */
time_t time(time_t * t);
#endif /* !UKERNEL_TIME_H */

72
src/drivers/clock.c Normal file
View File

@ -0,0 +1,72 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "clock.h"
/* private */
/* variables */
static ukClock * _clock = NULL;
/* public */
/* variables */
#if defined(__amd64__) || defined(__i386__)
extern ukClock cmos_clock;
#endif
/* functions */
/* clock_init */
ukClock * clock_init(ukBus * bus, char const * name)
{
ukClock * clock = NULL;
const ukClock * drivers[] = {
#if defined(__amd64__) || defined(__i386__)
&cmos_clock
#endif
};
size_t i;
for(i = 0; i < sizeof(drivers) / sizeof(*drivers); i++)
if(strncmp(drivers[i]->name, name,
strlen(drivers[i]->name)) == 0
&& drivers[i]->init != NULL)
{
fprintf(stderr, "%s clock%s%s\n", name, (bus != NULL)
? " at " : "",
(bus != NULL) ? bus->name : "");
clock = drivers[i]->init(bus);
}
if(clock == NULL)
errno = ENODEV;
else if(_clock == NULL)
_clock = clock;
return clock;
}
/* accessors */
/* clock_get_default */
ukClock * clock_get_default(void)
{
if(_clock == NULL)
errno = ENODEV;
return _clock;
}
/* clock_get_time */
int clock_get_time(ukClock * clock, time_t * time)
{
if(clock == NULL
&& (clock = clock_get_default()) == NULL)
return -1;
return clock->get_time(clock, time);
}

42
src/drivers/clock.h Normal file
View File

@ -0,0 +1,42 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#ifndef UKERNEL_DRIVERS_CLOCK_H
# define UKERNEL_DRIVERS_CLOCK_H
# include <time.h>
# include "bus.h"
/* public */
/* types */
typedef struct _ukClock ukClock;
typedef struct _ukClockData ukClockData;
struct _ukClock
{
char name[16];
ukClock * (*init)(ukBus * bus);
void (*destroy)(ukClock * clock);
int (*get_time)(ukClock * clock, time_t * time);
ukClockData * data;
};
/* prototypes */
ukClock * clock_init(ukBus * bus, char const * name);
void clock_destroy(ukClock * clock);
/* accessors */
ukClock * clock_get_default(void);
int clock_get_time(ukClock * clock, time_t * time);
#endif /* !UKERNEL_DRIVERS_CLOCK_H */

140
src/drivers/clock/cmos.c Normal file
View File

@ -0,0 +1,140 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#include <stdlib.h>
#include <errno.h>
#include "drivers/clock.h"
/* private */
/* types */
typedef struct _ukClock CMOSClock;
typedef struct _ukClockData
{
ukBus * bus;
} CMOSClockData;
/* constants */
#define CMOS_REGISTER_SECONDS 0x00
#define CMOS_REGISTER_MINUTES 0x02
#define CMOS_REGISTER_HOURS 0x04
#define CMOS_REGISTER_WEEKDAY 0x06
#define CMOS_REGISTER_DAY 0x07
#define CMOS_REGISTER_MONTH 0x08
#define CMOS_REGISTER_YEAR 0x09
/* prototypes */
/* console */
static CMOSClock * _cmos_clock_init(ukBus * bus);
static void _cmos_clock_destroy(CMOSClock * clock);
static int _cmos_clock_get_time(CMOSClock * console, time_t * time);
/* public */
/* variables */
/* console */
CMOSClock cmos_clock =
{
"cmos",
_cmos_clock_init,
_cmos_clock_destroy,
_cmos_clock_get_time,
NULL
};
/* functions */
/* console */
/* cmos_clock_init */
static CMOSClock * _cmos_clock_init(ukBus * bus)
{
CMOSClock * clock = &cmos_clock;
CMOSClockData * data;
if(bus == NULL)
{
errno = ENODEV;
return NULL;
}
if((data = malloc(sizeof(*data))) == NULL)
return NULL;
data->bus = bus;
clock->data = data;
return clock;
}
/* cmos_clock_destroy */
static void _cmos_clock_destroy(CMOSClock * clock)
{
free(clock->data);
}
/* cmos_clock_get_time */
static int _get_time_do(ukBus * bus, unsigned char * seconds,
unsigned char * minutes, unsigned char * hours,
unsigned char * day, unsigned char * month,
unsigned char * year);
static int _cmos_clock_get_time(CMOSClock * clock, time_t * time)
{
CMOSClockData * data = clock->data;
unsigned char seconds, s;
unsigned char minutes, m;
unsigned char hours, h;
unsigned char day, d;
unsigned char month, M;
unsigned char year, y;
size_t i;
if(time == NULL)
{
errno = EINVAL;
return -1;
}
for(i = 0; i < 3; i++)
{
if(_get_time_do(data->bus, &seconds, &minutes, &hours, &day,
&month, &year) != 0
|| _get_time_do(data->bus, &s, &m, &h, &d, &M,
&y) != 0)
return -1;
if(seconds == s && minutes == m && hours == h
&& day == d && month == M && year == y)
break;
}
if(i == 3)
{
errno = EAGAIN;
return -1;
}
/* FIXME this is not correct */
*time = seconds + (minutes * 60) + (hours * 60 * 24)
+ (day * 60 * 24 * 30) + (month * 60 * 24 * 12)
+ (((year >= 70) ? (year - 1970) : (year + 30))
* 60 * 24 * 365);
return 0;
}
static int _get_time_do(ukBus * bus, unsigned char * seconds,
unsigned char * minutes, unsigned char * hours,
unsigned char * day, unsigned char * month,
unsigned char * year)
{
/* FIXME check first if the data is available */
if(bus->read8(bus, CMOS_REGISTER_SECONDS, seconds) != 0
|| bus->read8(bus, CMOS_REGISTER_MINUTES, minutes) != 0
|| bus->read8(bus, CMOS_REGISTER_HOURS, hours) != 0
|| bus->read8(bus, CMOS_REGISTER_DAY, day) != 0
|| bus->read8(bus, CMOS_REGISTER_MONTH, month) != 0
|| bus->read8(bus, CMOS_REGISTER_YEAR, year) != 0)
return -1;
return 0;
}

View File

@ -0,0 +1,15 @@
targets=cmos.o,sys.o
cppflags_force=-nostdinc -isystem ../../../include -I../..
cflags_force=`../../../tools/platform.sh -V UKERNEL_CFLAGS -C "$$ARCH"`
cflags=-W -Wall -g -O2
ldflags_force=`../../../tools/platform.sh -V UKERNEL_LDFLAGS -C "$$ARCH"`
dist=Makefile
#targets
[cmos.o]
type=object
sources=cmos.c
[sys.o]
type=object
sources=sys.c

59
src/drivers/clock/sys.c Normal file
View File

@ -0,0 +1,59 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#include <stddef.h>
#include "drivers/clock.h"
/* private */
/* types */
typedef struct _ukClock SysClock;
/* prototypes */
/* console */
static SysClock * _sys_clock_init(ukBus * bus);
static int _sys_clock_get_time(SysClock * console, time_t * time);
extern time_t _time(time_t * t);
/* public */
/* variables */
/* console */
SysClock sys_clock =
{
"sys",
_sys_clock_init,
NULL,
_sys_clock_get_time,
NULL
};
/* functions */
/* console */
/* sys_clock_init */
static SysClock * _sys_clock_init(ukBus * bus)
{
(void) bus;
return &sys_clock;
}
/* sys_clock_get_time */
static int _sys_clock_get_time(SysClock * clock, time_t * time)
{
time_t t;
if(_time(&t) == -1)
return -1;
if(time != NULL)
*time = t;
return 0;
}

View File

@ -1,5 +1,5 @@
subdirs=boot,bus,console
targets=bus.o,console.o
subdirs=boot,bus,clock,console
targets=bus.o,clock.o,console.o
cppflags_force=-nostdinc -isystem ../../include -I..
as=$(CC)
asflags_force=$(CFLAGSF) $(CFLAGS) -c
@ -13,6 +13,10 @@ dist=Makefile,bus.h,console.h
type=object
sources=bus.c
[clock.o]
type=object
sources=clock.c
[console.o]
type=object
sources=console.c
@ -21,5 +25,8 @@ sources=console.c
[bus.c]
depends=bus.h,bus/ioport.c
[clock.c]
depends=bus.h,clock.h
[console.c]
depends=bus.h,console/vga.h,console/vga.c

View File

@ -27,8 +27,8 @@ sources=../common/crtn.S
[uKernel.bin]
type=binary
sources=arch.S,gdt.c,main.c,multiboot.c,start.S
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)../drivers/boot/multiboot.o $(OBJDIR)../drivers/bus.o $(OBJDIR)../drivers/bus/cmos.o $(OBJDIR)../drivers/bus/ioport.o $(OBJDIR)../drivers/console.o $(OBJDIR)../drivers/console/uart.o $(OBJDIR)../drivers/console/vesa.o $(OBJDIR)../drivers/console/vga.o $(OBJDIR)../lib/libuKernel.a $(OBJDIR)crtend.o $(OBJDIR)crtn.o `$(CC) -print-libgcc-file-name`
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)../drivers/boot/multiboot.o,$(OBJDIR)../drivers/bus.o,$(OBJDIR)../drivers/bus/cmos.o,$(OBJDIR)../drivers/bus/ioport.o,$(OBJDIR)../drivers/console.o,$(OBJDIR)../drivers/console/uart.o,$(OBJDIR)../drivers/console/vesa.o,$(OBJDIR)../drivers/console/vga.o,$(OBJDIR)../lib/libuKernel.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
ldflags=$(OBJDIR)crti.o $(OBJDIR)crtbegin.o $(OBJDIR)../drivers/boot/multiboot.o $(OBJDIR)../drivers/bus.o $(OBJDIR)../drivers/bus/cmos.o $(OBJDIR)../drivers/bus/ioport.o $(OBJDIR)../drivers/clock.o $(OBJDIR)../drivers/clock/cmos.o $(OBJDIR)../drivers/console.o $(OBJDIR)../drivers/console/uart.o $(OBJDIR)../drivers/console/vesa.o $(OBJDIR)../drivers/console/vga.o $(OBJDIR)../lib/libuKernel.a $(OBJDIR)crtend.o $(OBJDIR)crtn.o `$(CC) -print-libgcc-file-name`
depends=$(OBJDIR)crtbegin.o,$(OBJDIR)crtend.o,$(OBJDIR)crti.o,$(OBJDIR)crtn.o,$(OBJDIR)../drivers/boot/multiboot.o,$(OBJDIR)../drivers/bus.o,$(OBJDIR)../drivers/bus/cmos.o,$(OBJDIR)../drivers/bus/ioport.o,$(OBJDIR)../drivers/clock.o,$(OBJDIR)../drivers/clock/cmos.o,$(OBJDIR)../drivers/console.o,$(OBJDIR)../drivers/console/uart.o,$(OBJDIR)../drivers/console/vesa.o,$(OBJDIR)../drivers/console/vga.o,$(OBJDIR)../lib/libuKernel.a,../arch/amd64/uKernel.ld,../arch/i386/uKernel.ld
#sources
[arch.S]

View File

@ -7,7 +7,7 @@ dist=Makefile,ssp.h
[libuKernel]
type=library
sources=ctype.c,errno.c,ssp.c,stdio.c,stdlib.c,string.c,sys/mman.c,unistd.c
sources=ctype.c,errno.c,ssp.c,stdio.c,stdlib.c,string.c,sys/mman.c,time.c,unistd.c
[ctype.c]
depends=../../include/ctype.h
@ -29,3 +29,6 @@ depends=../../include/string.h
[sys/mman.c]
depends=../../include/sys/mman.h
[time.c]
depends=../../include/time.h,../drivers/clock.h

23
src/lib/time.c Normal file
View File

@ -0,0 +1,23 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#include <stddef.h>
#include <time.h>
#include "drivers/clock.h"
/* functions */
/* time */
time_t time(time_t * time)
{
time_t t;
if(clock_get_time(NULL, &t) != 0)
return -1;
if(time != NULL)
*time = t;
return t;
}

View File

@ -35,6 +35,14 @@ _exit:
jmp _syscall
/* gettimeofday */
.global _gettimeofday
.type _gettimeofday, @function
_gettimeofday:
mov $0x1a2, %eax
jmp _syscall
/* read */
.global _read
.type _read, @function
@ -99,6 +107,23 @@ _start:
hlt
/* time */
.global _time
.type _time, @function
_time:
push $0x0
sub $0xc, %esp
push %esp
call _gettimeofday
cmp $-1, %eax
je 1f
mov 0xc(%esp), %eax
mov 0x8(%esp), %edx
1:
add $0x14, %esp
ret
/* write */
.global _write
.type _write, @function

74
tools/clock.c Normal file
View File

@ -0,0 +1,74 @@
/* $Id$ */
/* Copyright (c) 2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS uKernel */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "drivers/clock.h"
/* private */
/* variables */
static ukClock * _clock = NULL;
/* public */
/* variables */
extern ukClock sys_clock;
/* functions */
/* clock_init */
ukClock * clock_init(ukBus * bus, char const * name)
{
const ukClock * drivers[] = {
&sys_clock
};
size_t i;
ukClock * clock = NULL;
for(i = 0; i < sizeof(drivers) / sizeof(*drivers); i++)
if(strncmp(drivers[i]->name, name,
strlen(drivers[i]->name)) == 0
&& drivers[i]->init != NULL)
{
printf("%s%s%s\n", name, (bus != NULL) ? " at " : "",
(bus != NULL) ? bus->name : "");
clock = drivers[i]->init(bus);
}
if(clock == NULL)
{
errno = ENODEV;
return NULL;
}
else if(_clock == NULL)
_clock = clock;
return clock;
}
/* FIXME code duplication with src/drivers/clock.c */
/* accessors */
/* clock_get_default */
ukClock * clock_get_default(void)
{
if(_clock == NULL)
errno = ENODEV;
return _clock;
}
/* clock_get_time */
int clock_get_time(ukClock * clock, time_t * time)
{
if(clock == NULL
&& (clock = clock_get_default()) == NULL)
{
errno = ENODEV;
return -1;
}
return clock->get_time(clock, time);
}

View File

@ -6,9 +6,11 @@
#include <stddef.h>
#include "drivers/bus.h"
#include "drivers/clock.h"
#include "drivers/console.h"
#define TOOLS_BUS "tty"
#define TOOLS_CLOCK "sys"
#define TOOLS_CONSOLE "stdio"
@ -18,5 +20,6 @@ int _init(void)
bus = bus_init(NULL, TOOLS_BUS);
console_init(bus, TOOLS_CONSOLE);
clock_init(NULL, TOOLS_CLOCK);
return 0;
}

View File

@ -14,9 +14,9 @@ sources=start.S
[uKernel]
type=binary
sources=bus.c,console.c,init.c,main.c
ldflags=$(OBJDIR)start.o $(OBJDIR)../src/lib/libuKernel.a $(OBJDIR)../src/drivers/console/stdio.o `$(CC) -print-libgcc-file-name`
depends=$(OBJDIR)start.o,$(OBJDIR)../src/lib/libuKernel.a,$(OBJDIR)../src/drivers/console/stdio.o
sources=bus.c,clock.c,console.c,init.c,main.c
ldflags=$(OBJDIR)start.o $(OBJDIR)../src/lib/libuKernel.a $(OBJDIR)../src/drivers/clock/sys.o $(OBJDIR)../src/drivers/console/stdio.o `$(CC) -print-libgcc-file-name`
depends=$(OBJDIR)start.o,$(OBJDIR)../src/lib/libuKernel.a,$(OBJDIR)../src/drivers/clock/sys.o,$(OBJDIR)../src/drivers/console/stdio.o
#sources
[bus.c]