diff --git a/kernel/Makefile b/kernel/Makefile index 0991c56..b4b4a76 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -63,6 +63,7 @@ SRCFILES += $(call GRABSRC, \ rbuf \ ipc/pipe \ drivers/ps2kb \ + drivers/serial \ dev \ ) diff --git a/kernel/dev/dev.c b/kernel/dev/dev.c index c1351f5..9a5fedb 100644 --- a/kernel/dev/dev.c +++ b/kernel/dev/dev.c @@ -6,6 +6,7 @@ #include "hal/hal.h" #include "termdev.h" #include "ps2kbdev.h" +#include "serialdev.h" DevTable DEVTABLE; @@ -15,4 +16,5 @@ void dev_init(void) { termdev_init(); ps2kbdev_init(); + serialdev_init(); } diff --git a/kernel/dev/dev.h b/kernel/dev/dev.h index 00410fb..3cfeefe 100644 --- a/kernel/dev/dev.h +++ b/kernel/dev/dev.h @@ -12,6 +12,7 @@ typedef struct { int _hshtbstate; char ident[0x100]; DevFn fns[DEV_FNS_MAX]; + SpinLock spinlock; } Dev; diff --git a/kernel/dev/ps2kbdev.c b/kernel/dev/ps2kbdev.c index 5f0b029..b5b7e95 100644 --- a/kernel/dev/ps2kbdev.c +++ b/kernel/dev/ps2kbdev.c @@ -33,5 +33,6 @@ void ps2kbdev_init(void) { Dev *ps2kbdev; HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev); + spinlock_init(&ps2kbdev->spinlock); ps2kbdev->fns[0] = &ps2kbdev_readch; } diff --git a/kernel/dev/serialdev.c b/kernel/dev/serialdev.c new file mode 100644 index 0000000..ed0dd91 --- /dev/null +++ b/kernel/dev/serialdev.c @@ -0,0 +1,42 @@ +#include +#include +#include "dev.h" +#include "serialdev.h" +#include "errors.h" +#include "util/util.h" +#include "hshtb.h" +#include "sysdefs/devctl.h" +#include "drivers/serial/serial.h" +#include "kprintf.h" + +int32_t serialdev_sendb(uint8_t *buffer, size_t len, void *extra) { + (void)len; (void)extra; + serial_sendb(buffer[0]); + return E_OK; +} + +int32_t serialdev_sendready(uint8_t *buffer, size_t len, void *extra) { + (void)buffer; (void)len; (void) extra; + return serial_sendready(); +} + +int32_t serialdev_recvb(uint8_t *buffer, size_t len, void *extra) { + (void)buffer; (void)len; (void)extra; + return serial_recvb(); +} + +int32_t serialdev_recvready(uint8_t *buffer, size_t len, void *extra) { + (void)buffer; (void)len; (void)extra; + return serial_recvready(); +} + +void serialdev_init(void) { + Dev *serialdev = NULL; + HSHTB_ALLOC(DEVTABLE.devs, ident, "serialdev", serialdev); + serialdev->fns[DEV_SERIALDEV_SENDB] = &serialdev_sendb; + serialdev->fns[DEV_SERIALDEV_SENDREADY] = &serialdev_sendready; + serialdev->fns[DEV_SERIALDEV_RECVB] = &serialdev_recvb; + serialdev->fns[DEV_SERIALDEV_RECVREADY] = &serialdev_recvready; + spinlock_init(&serialdev->spinlock); + serial_init(); +} diff --git a/kernel/dev/serialdev.h b/kernel/dev/serialdev.h new file mode 100644 index 0000000..43ee298 --- /dev/null +++ b/kernel/dev/serialdev.h @@ -0,0 +1,10 @@ +#ifndef DEV_SERIALDEV_H_ +#define DEV_SERIALDEV_H_ + +int32_t serialdev_sendb(uint8_t *buffer, size_t len, void *extra); +int32_t serialdev_sendready(uint8_t *buffer, size_t len, void *extra); +int32_t serialdev_recvb(uint8_t *buffer, size_t len, void *extra); +int32_t serialdev_recvready(uint8_t *buffer, size_t len, void *extra); +void serialdev_init(void); + +#endif // DEV_SERIALDEV_H_ diff --git a/kernel/dev/termdev.c b/kernel/dev/termdev.c index 2723a5d..7e3c489 100644 --- a/kernel/dev/termdev.c +++ b/kernel/dev/termdev.c @@ -17,4 +17,5 @@ void termdev_init(void) { Dev *termdev = NULL; HSHTB_ALLOC(DEVTABLE.devs, ident, "termdev", termdev); termdev->fns[0] = &termdev_putch; + spinlock_init(&termdev->spinlock); } diff --git a/kernel/drivers/serial/serial.c b/kernel/drivers/serial/serial.c new file mode 100644 index 0000000..811ae80 --- /dev/null +++ b/kernel/drivers/serial/serial.c @@ -0,0 +1,42 @@ +#include +#include "hal/hal.h" +#include "kprintf.h" + +// https://wiki.osdev.org/Serial_Ports + +#define PORT 0x3f8 + +void serial_init(void) { + io_out8(PORT+1, 0x00); + io_out8(PORT+3, 0x80); + io_out8(PORT+0, 0x03); + io_out8(PORT+1, 0x00); + io_out8(PORT+3, 0x03); + io_out8(PORT+2, 0xC7); + io_out8(PORT+4, 0x0B); + io_out8(PORT+4, 0x1E); + io_out8(PORT+0, 0xAE); + + if (io_in8(PORT+0) != 0xAE) { + ERR("serial", "serial is faulty!\n"); + return; + } + + io_out8(PORT+4, 0x0F); +} + +int serial_recvready(void) { + return io_in8(PORT+5) & 1; +} + +uint8_t serial_recvb(void) { + return io_in8(PORT); +} + +int serial_sendready(void) { + return io_in8(PORT+5) & 0x20; +} + +void serial_sendb(uint8_t b) { + io_out8(PORT, b); +} diff --git a/kernel/drivers/serial/serial.h b/kernel/drivers/serial/serial.h new file mode 100644 index 0000000..c2538e2 --- /dev/null +++ b/kernel/drivers/serial/serial.h @@ -0,0 +1,12 @@ +#ifndef DRIVERS_SERIAL_SERIAL_H_ +#define DRIVERS_SERIAL_SERIAL_H_ + +#include + +void serial_init(void); +int serial_recvready(void); +uint8_t serial_recvb(void); +int serial_sendready(void); +void serial_sendb(uint8_t b); + +#endif // DRIVERS_SERIAL_SERIAL_H_ diff --git a/kernel/hshtb.h b/kernel/hshtb.h index 307805e..cbcca3b 100644 --- a/kernel/hshtb.h +++ b/kernel/hshtb.h @@ -26,13 +26,17 @@ enum { HSHTB_TOMB = 2, }; +#define __HSHTB_ARRAY_LEN(tb) \ + ((void)sizeof(struct { int _[!!(sizeof(tb) % sizeof((tb)[0]) == 0)]; }) , (sizeof(tb) / sizeof((tb)[0]))) + #define HSHTB_ALLOC(tb, keyfield, k, out) \ do { \ - size_t __len = sizeof((tb)) / sizeof((tb)[0]); \ + size_t __len = __HSHTB_ARRAY_LEN(tb); \ uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \ size_t __idx = __h % __len; \ size_t __start = __idx; \ typeof(&(tb)[0]) __tomb = NULL; \ + (out) = NULL; \ do { \ if ((tb)[__idx]._hshtbstate == HSHTB_EMPTY) { \ typeof(&(tb)[0]) __slot = __tomb ? __tomb : &(tb)[__idx]; \ @@ -55,7 +59,7 @@ enum { #define HSHTB_GET(tb, keyfield, k, out) \ do { \ - size_t __len = sizeof((tb)) / sizeof((tb)[0]); \ + size_t __len = __HSHTB_ARRAY_LEN(tb); \ uint32_t __h = hshtb_fnv32((k), hal_strlen((k))); \ size_t __idx = __h % __len; \ size_t __start = __idx; \ @@ -77,7 +81,7 @@ enum { typeof(&(tb)[0]) __e; \ HSHTB_GET((tb), (keyfield), (k), __e); \ if (__e) { \ - __e->state = HSHTB_TOMB; \ + __e->_hshtbstate = HSHTB_TOMB; \ } \ } while(0) diff --git a/kernel/kmain.c b/kernel/kmain.c index fc077a6..cc75f77 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -11,8 +11,7 @@ #include "storedev/storedev.h" #include "util/util.h" #include "proc/proc.h" -#include "dev/termdev.h" -#include "dev/ps2kbdev.h" +#include "dev/dev.h" const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; @@ -66,8 +65,7 @@ void kmain(void) { storedev_init(); baseimg_init(); vfs_init(); - termdev_init(); - ps2kbdev_init(); + dev_init(); proc_init(); for(;;); diff --git a/kernel/syscall/devctl.c b/kernel/syscall/devctl.c index c8aae23..11763e4 100644 --- a/kernel/syscall/devctl.c +++ b/kernel/syscall/devctl.c @@ -27,8 +27,10 @@ int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) { goto done; } + spinlock_acquire(&DEVTABLE.spinlock); Dev *founddev; HSHTB_GET(DEVTABLE.devs, ident, ident, founddev); + spinlock_release(&DEVTABLE.spinlock); if (founddev == NULL) { ret = E_NOENTRY; @@ -66,7 +68,9 @@ int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) { ret = E_NOENTRY; goto done; } + spinlock_acquire(&dev->spinlock); ret = dev->fns[cmd]((uint8_t *)buffer1, (size_t)len1, (void *)extra1); + spinlock_release(&dev->spinlock); } break; } diff --git a/share/sysdefs/devctl.h b/share/sysdefs/devctl.h index 658ce0e..f5ce38b 100644 --- a/share/sysdefs/devctl.h +++ b/share/sysdefs/devctl.h @@ -3,6 +3,15 @@ #define DEVCTL_GET_HANDLE 100 +#define DEV_TERMDEV_PUTCH 0 + +#define DEV_PS2KBDEV_READCH 0 + +#define DEV_SERIALDEV_SENDB 0 +#define DEV_SERIALDEV_SENDREADY 1 +#define DEV_SERIALDEV_RECVB 2 +#define DEV_SERIALDEV_RECVREADY 3 + #if !defined(__ASSEMBLER__) typedef uint64_t Dev_t; diff --git a/ulib/dev.h b/ulib/dev.h deleted file mode 100644 index 26346fd..0000000 --- a/ulib/dev.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef ULIB_DEV_H_ -#define ULIB_DEV_H_ - -#define DEV_TERMDEV_PUTCH 0 - -#define DEV_PS2KBDEV_READCH 0 - -#endif // ULIB_DEV_H_ diff --git a/ulib/ulib.h b/ulib/ulib.h index f759138..0d66b84 100644 --- a/ulib/ulib.h +++ b/ulib/ulib.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/user/init/main.c b/user/init/main.c index 0d99c0b..95f0176 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -35,6 +35,11 @@ void main(void) { PID = (uint64_t)processctl(-1, PCTL_GETPID, 0, 0, 0); devctl(&ps2kbdev, DEVCTL_GET_HANDLE, (uint8_t *)"ps2kbdev", 0, 0); + Dev_t serialdev; + int32_t err = devctl(&serialdev, DEVCTL_GET_HANDLE, (uint8_t *)"serialdev", 0, 0); + uint8_t a = 'A'; + devctl(&serialdev, DEV_SERIALDEV_SENDB, &a, 1, 0); + tb_runinitscript(); uprintf("Shell exited! Please reboot the system.\n");