diff --git a/driver/irq/pic/serial/serial.c b/driver/irq/pic/serial/serial.c index fec1847..89385ee 100644 --- a/driver/irq/pic/serial/serial.c +++ b/driver/irq/pic/serial/serial.c @@ -2,9 +2,19 @@ #include "serial.h" #include "../internal.h" #include "../../../../interrupt/interrupt.h" +#include "../../../../memory/memory.h" +#include "../pic.h" -pic_serial_Port pic_serial_COM1 = {0x3f8, false}, pic_serial_COM2 = {0x2f8, false}; +pic_serial_Port pic_serial_COM1 = {0x3f8, 4, false}, pic_serial_COM2 = {0x2f8, 3, false}; + +SYSV_ABI void __pic_serial_IRQHandler(pic_serial_Port *port) { + while ((inb(port->port + 5) & 1)) { + uint8_t b = inb(port->port); + queue_PushByte(&port->buffer, b); + smp_Condition_NotifyAll(port->cond, 0); + } +} bool pic_serial_Init(pic_serial_Port *port, int baudrate, int lineFlags) { if (115200 % baudrate != 0) @@ -37,6 +47,22 @@ bool pic_serial_Init(pic_serial_Port *port, int baudrate, int lineFlags) { return true; } +bool pic_serial_InitInput(pic_serial_Port *port) { + // Set IRQ handler for serial input + if (port->irq) { + queue_InitBuffered(&port->buffer, kMalloc(PIC_SERIAL_DEFAULT_BUFFERSIZE), PIC_SERIAL_DEFAULT_BUFFERSIZE); + port->cond = smp_Condition_Create(); + + irq_pic_IRQHandler[port->irq] = __pic_serial_IRQHandler; + irq_pic_IRQHandler_Data[port->irq] = (uintptr_t)port; + irq_pic_Mask(port->irq, false); + outb(port->port + 1, 1); + + return true; + } else + return false; +} + void pic_serial_Write(pic_serial_Port *port, const char *str, int n) { if (port && port->ok) { INTERRUPT_DISABLE; diff --git a/driver/irq/pic/serial/serial.h b/driver/irq/pic/serial/serial.h index 612bb7a..895616c 100644 --- a/driver/irq/pic/serial/serial.h +++ b/driver/irq/pic/serial/serial.h @@ -1,5 +1,7 @@ #pragma once +#include "../../../../util/queue.h" +#include "../../../../smp/condiction.h" #include "stdbool.h" #ifdef __cplusplus @@ -7,12 +9,21 @@ extern "C" { #endif +// Default buffer size for serial input +#ifndef PIC_SERIAL_DEFAULT_BUFFERSIZE +#define PIC_SERIAL_DEFAULT_BUFFERSIZE 16 +#endif + // Serial port state. // // Line protocol defaults to 8N1 (8 bits, no parity, one stop bit) typedef struct { int port; // IO Port + int irq; // IRQ, 0 for disable bool ok; // Is the port usable? + + queue_Queue buffer; // input byte buffer + smp_Condition *cond; // input wait condiction } pic_serial_Port; extern pic_serial_Port pic_serial_COM1, pic_serial_COM2; @@ -22,6 +33,9 @@ extern pic_serial_Port pic_serial_COM1, pic_serial_COM2; // TODO lineFlags is ignored by now, always 8N1 bool pic_serial_Init(pic_serial_Port *port, int baudrate, int lineFlags); +// InitInput initializes input for a serial port. Returns true if success. +bool pic_serial_InitInput(pic_serial_Port *port); + // Write writes a string to a serial port, if the port is usable. // // Writes n chars. If n is 0, writes until it reaches NUL.