summaryrefslogtreecommitdiff
path: root/kernel/serial.c
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-08-26 13:29:33 +1000
committerJake Mannens <jake72360@gmail.com>2018-08-26 13:29:33 +1000
commit307eaac66d378c1f6150519123ec1204277464d9 (patch)
tree8c6dc79c5c16bf776bd57ca78a439701cc10412e /kernel/serial.c
parentdafb5464fe8b9a3f8ff41de233f9ff6cd21162ea (diff)
Updated the style of the code in lib/string.c to conform to the rest of
the project. Added the system call 'sys_panic' as well as the corresponding library function panic() whose prototype is defined in unistd.h. This is to allow userspace programs to deliberately crash the kernel for the purpose of debugging. Added the element 'write' as a function pointer in the tty_struct structure. The purpose of this function pointer is to provide a means for the TTY subsystem to notify the device driver of any newly added data to the write queue. Added the tty_write() function to the TTY subsystem. This function will copy data provided by the user into the specified TTY device's write queue, blocking if the queue's buffer is full. tty_write() will then call the driver's write() function to notify it of new data. Added the rsint_tx() function to the serial driver to handle transmit interrupts by re-supplying the UART's transmit FIFO.
Diffstat (limited to 'kernel/serial.c')
-rw-r--r--kernel/serial.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/kernel/serial.c b/kernel/serial.c
index 39c5ee0..a133865 100644
--- a/kernel/serial.c
+++ b/kernel/serial.c
@@ -16,6 +16,7 @@
#define RSDATA RSBASE
#define RSINTEN (RSBASE + 1)
#define RSFIFOC (RSBASE + 2)
+#define RSINTID (RSBASE + 2)
#define RSLINEC (RSBASE + 3)
#define RSMODEMC (RSBASE + 4)
#define RSLINES (RSBASE + 5)
@@ -27,8 +28,12 @@
extern void rs_isr(void);
+/* internal function prototypes */
+void rsint_tx(void);
+
struct tty_struct tty_rs = {
- .init = &serial_init
+ .init = &serial_init,
+ .write = &rsint_tx
};
static char present;
@@ -70,11 +75,18 @@ void serial_init(void) {
/* restore access to the divisor */
outb(RSLINEC, inb(RSLINEC) & 0x7F);
/* configure port parameters */
- outb(RSFIFOC, 0x06);
+ outb(RSFIFOC, 0x07);
outb(RSLINEC, 0x03);
outb(RSMODEMC, 0x0B);
- outb(RSINTEN, 0x01);
+ outb(RSINTEN, 0x03);
inb(RSDATA);
+
+ /* test FIFO functionality */
+ if(inb(RSINTID) & 0xC0 != 0xC0) {
+ printk("[rs] Failed to enable FIFO on COM0!\n");
+ return;
+ }
+
/* register the interrupt handler */
register_isr(0x24, 0, &rs_isr);
irq_enable(0x10);
@@ -85,7 +97,7 @@ void serial_init(void) {
present = 1;
}
-void rs_handler(void) {
+void rsint_rx(void) {
struct tty_queue *q = &tty_rs.rqueue;
if((inb(RSLINES) & 1) == 0)
@@ -98,3 +110,22 @@ void rs_handler(void) {
wake_up(&q->waiting);
}
+
+void rsint_tx(void) {
+ int copied = 0;
+ struct tty_queue *q = &tty_rs.wqueue;
+
+ while(q->pread != q->pwrite) {
+ /* we're done if the TX FIFO is full */
+ if((inb(RSLINES) & 0x20) == 0)
+ break;
+
+ outb(RSDATA, q->buf[q->pread]);
+ q->pread = (q->pread + 1) % TTY_BUF_SIZE;
+
+ copied = 1;
+ }
+
+ if(copied)
+ wake_up(&q->waiting);
+}