-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserial.c
More file actions
141 lines (126 loc) · 4.46 KB
/
Copy pathserial.c
File metadata and controls
141 lines (126 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* serial.c - Serial port driver
*
* This file implements basic initialization and output functions for the standard PC serial ports (COM1-COM4).
* It allows the kernel to output debug information over a serial connection, which is invaluable for early
* boot debugging and for use in virtual machines where serial output can be easily captured.
*
* Author: u/ApparentlyPlus
*/
#include <kernel/drivers/serial.h>
/*
* get_port_base - Get port base address for each serial port
*/
uint16_t get_port_base(serial_port_t port) {
switch(port) {
case SERIAL_COM1: return COM1_PORT;
case SERIAL_COM2: return COM2_PORT;
case SERIAL_COM3: return COM3_PORT;
case SERIAL_COM4: return COM4_PORT;
default: return COM1_PORT;
}
}
/*
* serial_init_port - Initializes specific serial port at 38400 baud
*/
void serial_init_port(serial_port_t port) {
uint16_t port_base = get_port_base(port);
outb(port_base + 1, 0x00);
outb(port_base + 3, 0x80);
outb(port_base + 0, 0x03);
outb(port_base + 1, 0x00);
outb(port_base + 3, 0x03);
outb(port_base + 2, 0xC7);
outb(port_base + 4, 0x0B);
}
/*
* serial_init_all - Initializes all available serial ports
*/
void serial_init_all(void) {
serial_init_port(SERIAL_COM1);
serial_init_port(SERIAL_COM2);
}
/*
* serial_is_ready_port - Checks if transmit buffer is empty for specific port
*/
int serial_is_ready_port(serial_port_t port) {
uint16_t port_base = get_port_base(port);
return inb(port_base + 5) & 0x20;
}
/*
* serial_write_char_port - Outputs single character to specific serial port
*/
void serial_write_char_port(serial_port_t port, char c) {
uint16_t port_base = get_port_base(port);
while (!serial_is_ready_port(port));
outb(port_base, (uint8_t)c);
}
/*
* serial_write_port - Outputs null-terminated string to specific serial port
*/
void serial_write_port(serial_port_t port, const char* str) {
while (*str) {
if (*str == '\n') {
serial_write_char_port(port, '\r');
}
serial_write_char_port(port, *str++);
}
}
/*
* serial_write_len_port - Outputs fixed-length string to specific serial port
*/
void serial_write_len_port(serial_port_t port, const char* str, size_t len) {
for (size_t i = 0; i < len; i++) {
if (str[i] == '\n') {
serial_write_char_port(port, '\r');
}
serial_write_char_port(port, str[i]);
}
}
/*
* serial_write_hex_digit_port - Internal helper for hex digit output to specific port
*/
void serial_write_hex_digit_port(serial_port_t port, uint8_t val) {
val &= 0xF;
if (val < 10)
serial_write_char_port(port, '0' + val);
else
serial_write_char_port(port, 'A' + (val - 10));
}
/*
* serial_write_hex8_port - Outputs 8-bit value in hexadecimal to specific port
*/
void serial_write_hex8_port(serial_port_t port, uint8_t value) {
serial_write_hex_digit_port(port, value >> 4);
serial_write_hex_digit_port(port, value & 0xF);
}
/*
* serial_write_hex16_port - Outputs 16-bit value in hexadecimal to specific port
*/
void serial_write_hex16_port(serial_port_t port, uint16_t value) {
for (int i = 12; i >= 0; i -= 4)
serial_write_hex_digit_port(port, (value >> i) & 0xF);
}
/*
* serial_write_hex32_port - Outputs 32-bit value in hexadecimal to specific port
*/
void serial_write_hex32_port(serial_port_t port, uint32_t value) {
for (int i = 28; i >= 0; i -= 4)
serial_write_hex_digit_port(port, (value >> i) & 0xF);
}
/*
* serial_write_hex64_port - Outputs 64-bit value in hexadecimal to specific port
*/
void serial_write_hex64_port(serial_port_t port, uint64_t value) {
for (int i = 60; i >= 0; i -= 4)
serial_write_hex_digit_port(port, (value >> i) & 0xF);
}
// Default implementations (COM1 for backward compatibility)
int serial_is_ready(void) { return serial_is_ready_port(SERIAL_COM1); }
void serial_write_char(char c) { serial_write_char_port(SERIAL_COM1, c); }
void serial_write(const char* str) { serial_write_port(SERIAL_COM1, str); }
void serial_write_len(const char* str, size_t len) { serial_write_len_port(SERIAL_COM1, str, len); }
void serial_write_hex8(uint8_t value) { serial_write_hex8_port(SERIAL_COM1, value); }
void serial_write_hex16(uint16_t value) { serial_write_hex16_port(SERIAL_COM1, value); }
void serial_write_hex32(uint32_t value) { serial_write_hex32_port(SERIAL_COM1, value); }
void serial_write_hex64(uint64_t value) { serial_write_hex64_port(SERIAL_COM1, value); }