Skip to content

Commit fb7fa38

Browse files
committed
[Kernel] Rework and improve serial driver
1 parent 754043b commit fb7fa38

File tree

2 files changed

+69
-13
lines changed

2 files changed

+69
-13
lines changed

kernel/kernel/drivers/ps2/ps2.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ void ps2_controller_init(void) {
118118
for (uint32_t i = 0; i < 2; i++) {
119119
ps2_write_device(i, PS2_DEV_RESET);
120120
uint8_t ret = ps2_read(PS2_DATA);
121-
assert(ret == PS2_DEV_ACK && ps2_read(PS2_DATA) == PS2_DEV_RESET_ACK, "Failed to reset device");
121+
printf("Reset %d expect %d\n", ret, PS2_DEV_ACK);
122+
//assert(ret == PS2_DEV_ACK && ps2_read(PS2_DATA) == PS2_DEV_RESET_ACK, "Failed to reset device");
122123

123124
// For some reason, mice send an additional 0x00 byte
124125
/*

kernel/kernel/drivers/serial/serial.c

+67-12
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,25 @@
33
#include "kernel/util/spinlock/spinlock.h"
44
#include <kernel/smp.h>
55

6+
// Ref: https://www.lookrs232.com/rs232/fcr.htm
7+
68
//COM 1
79
#define PORT 0x3F8
810

9-
#define BUF_SIZE 1028*8
10-
static char buffer[BUF_SIZE];
11+
// Only valid when DLAB is unset
12+
#define DATA_REGISTER (PORT + 0)
13+
#define INTERRUPT_ENABLE_REGISTER (PORT + 1)
14+
15+
// Only valid when DLAB is set
16+
#define DLAB_DATA_BYTE_LOW_REGISTER (PORT + 0)
17+
#define DLAB_DATA_BYTE_HIGH_REGISTER (PORT + 1)
18+
19+
#define INTERRUPT_AND_FIFO_CONTROL_REGISTER (PORT + 2)
20+
#define LINE_CONTROL_REGISTER (PORT + 3)
21+
#define MODEM_CONTROL_REGISTER (PORT + 4)
22+
23+
#define BUF_SIZE (1028*8)
24+
static char buffer[BUF_SIZE] = {0};
1125
static int idx = 0;
1226

1327
int serial_waiting() {
@@ -25,7 +39,10 @@ bool is_transmitting() {
2539

2640
void __serial_putchar(char c) {
2741
while (is_transmitting() == 0);
28-
if (c == '\n') outb(PORT, '\r');
42+
if (c == '\n') {
43+
// Add an extra carriage return
44+
outb(PORT, '\r');
45+
}
2946
outb(PORT, c);
3047
}
3148

@@ -38,7 +55,8 @@ void __serial_writestring(char* str) {
3855

3956
static void serial_flush() {
4057
__serial_writestring(buffer);
41-
memset(buffer, 0, BUF_SIZE);
58+
// It's only necessary to memset up to where we last wrote
59+
memset(buffer, 0, idx);
4260
idx = 0;
4361
}
4462

@@ -49,7 +67,7 @@ void serial_putchar(char c) {
4967
}
5068
//append c to buffer
5169
buffer[idx+0] = c;
52-
buffer[idx+1] = '\0';
70+
//buffer[idx+1] = '\0';
5371
idx++;
5472
//also flush on newline
5573
if (c == '\n') {
@@ -95,11 +113,48 @@ void serial_init() {
95113

96114
memset(buffer, 0, BUF_SIZE);
97115

98-
outb(PORT + 1, 0x00); //interrupts off
99-
outb(PORT + 3, 0x80); //baud rate
100-
outb(PORT + 0, 0x03); //divisor to 3
101-
outb(PORT + 1, 0x00);
102-
outb(PORT + 3, 0x03); //1 byte, no parity, 1 stop bit
103-
outb(PORT + 2, 0xC7); //FIFO, 14-byte threshold
104-
outb(PORT + 4, 0x0B); //irq on, RTS/DSR set
116+
// Disable interrupts
117+
outb(INTERRUPT_ENABLE_REGISTER, 0x00);
118+
119+
// Enable DLAB bit, as we'll set the frequency divisor next
120+
outb(LINE_CONTROL_REGISTER, 0x80);
121+
// Set divisor to 1, so we transmit at the serial clock speed
122+
// Low divisor byte
123+
outb(DLAB_DATA_BYTE_LOW_REGISTER, 0x01);
124+
// High divisor byte
125+
outb(DLAB_DATA_BYTE_HIGH_REGISTER, 0x00);
126+
127+
// Bit pattern:
128+
// [0, 1]: Set 7 data bits (we're just sending ASCII so this should work out cleanly)
129+
// 2: Set 1 stop bit
130+
// 3: No parity bit
131+
outb(LINE_CONTROL_REGISTER, 0b0010);
132+
133+
// Bit pattern:
134+
// 0: Enable FIFO's
135+
// 1: Clear receive FIFO
136+
// 2: Clear transmit FIFO
137+
// 3: DMA mode-select
138+
// 4: Reserved
139+
// 5: Disable model-specific 64-byte FIFO
140+
// [6-7]: Set interrupt trigger level to 14 bytes
141+
outb(INTERRUPT_AND_FIFO_CONTROL_REGISTER, 0b11000111);
142+
143+
// Bit pattern:
144+
// 0: Data Terminal Ready
145+
// 1: Request to Send
146+
// 2: OUT1, unused in PC implementations
147+
// 3: Set the OUT2 hardware pin which is used to enable the IRQ in PC implementations
148+
// 4: Disable loopback
149+
// [5-7]: Unused
150+
outb(MODEM_CONTROL_REGISTER, 0b00001011);
151+
152+
// TODO(PT): Switch to an interrupt-based model for this controller, instead of polling
153+
/*
154+
// Enable interrupts.
155+
// Bit pattern:
156+
// : Interrupt when the transmitter is empty (so we know when we can send more)
157+
interrupt_setup_callback(INT_VECTOR_APIC_4, (int_callback_t)_handle_irq);
158+
outb(INTERRUPT_ENABLE_REGISTER, 0b10);
159+
*/
105160
}

0 commit comments

Comments
 (0)