| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 | 
							- #include <errno.h>
 
- #include <stdio.h>
 
- #include <kernel/hw/port.hpp>
 
- #include <kernel/irq.hpp>
 
- #include <kernel/log.hpp>
 
- #include <kernel/module.hpp>
 
- #include <kernel/tty.hpp>
 
- using namespace kernel::tty;
 
- using namespace kernel::hw;
 
- constexpr int PORT0 = 0x3f8;
 
- constexpr int PORT1 = 0x2f8;
 
- using port_group = const p8[6];
 
- constexpr p8 port0[] = {
 
-     p8{PORT0 + 0}, p8{PORT0 + 1}, p8{PORT0 + 2},
 
-     p8{PORT0 + 3}, p8{PORT0 + 4}, p8{PORT0 + 5},
 
- };
 
- constexpr p8 port1[] = {
 
-     p8{PORT1 + 0}, p8{PORT1 + 1}, p8{PORT1 + 2},
 
-     p8{PORT1 + 3}, p8{PORT1 + 4}, p8{PORT1 + 5},
 
- };
 
- static void _serial0_receive_data_interrupt() {
 
-     while (*port0[5] & 1)
 
-         console->commit_char(*port0[0]);
 
- }
 
- static void _serial1_receive_data_interrupt() {
 
-     while (*port1[5] & 1)
 
-         console->commit_char(*port1[0]);
 
- }
 
- static inline int _init_port(port_group ports) {
 
-     // taken from osdev.org
 
-     ports[1] = 0x00; // Disable all interrupts
 
-     ports[3] = 0x80; // Enable DLAB (set baud rate divisor)
 
-     // TODO: set baud rate
 
-     ports[0] = 0x00; // Set divisor to 0 -3- (lo byte) 115200 -38400- baud
 
-     ports[1] = 0x00; //                  (hi byte)
 
-     ports[3] = 0x03; // 8 bits, no parity, one stop bit
 
-     ports[2] = 0xC7; // Enable FIFO, clear them, with 14-byte threshold
 
-     // TODO: IRQ disabled
 
-     ports[4] = 0x0B; // IRQs enabled, RTS/DSR set
 
-     ports[4] = 0x1E; // Set in loopback mode, test the serial chip
 
-     ports[0] = 0xAE; // Test serial chip (send byte 0xAE and check if serial
 
-                      // returns same byte)
 
-     // Check if serial is faulty (i.e: not same byte as sent)
 
-     if (*ports[0] != 0xAE)
 
-         return -EIO;
 
-     // If serial is not faulty set it in normal operation mode
 
-     // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
 
-     ports[4] = 0x0F;
 
-     ports[1] = 0x01; // Enable interrupts #0: Received Data Available
 
-     return 0;
 
- }
 
- class serial_tty : public virtual tty {
 
-     const p8* ports;
 
-    public:
 
-     serial_tty(port_group ports, int id) : tty{"ttyS"}, ports(ports) {
 
-         name += '0' + id;
 
-     }
 
-     virtual void putchar(char c) override {
 
-         while (!(*ports[5] & 0x20))
 
-             ; // nop
 
-         ports[0] = c;
 
-     }
 
- };
 
- class serial_module : public virtual kernel::module::module {
 
-    public:
 
-     serial_module() : module("serial-tty") {}
 
-     virtual int init() override {
 
-         if (int ret = _init_port(port0); ret == 0) {
 
-             auto* dev = new serial_tty(port0, 0);
 
-             kernel::irq::register_handler(4, _serial0_receive_data_interrupt);
 
-             if (int ret = register_tty(dev); ret != 0)
 
-                 kmsg("[serial] cannot register ttyS0");
 
-         }
 
-         if (int ret = _init_port(port1); ret == 0) {
 
-             auto* dev = new serial_tty(port1, 0);
 
-             kernel::irq::register_handler(3, _serial1_receive_data_interrupt);
 
-             if (int ret = register_tty(dev); ret != 0)
 
-                 kmsg("[serial] cannot register ttyS1");
 
-         }
 
-         return kernel::module::MODULE_SUCCESS;
 
-     }
 
- };
 
- kernel::module::module* serial_module_init() {
 
-     return new serial_module();
 
- }
 
- INTERNAL_MODULE(serial_module_loader, serial_module_init);
 
 
  |