1 #include <geekos/serial.h>
2 #include <geekos/reboot.h>
3 #include <geekos/gdt.h>
4 #include <geekos/idt.h>
5 #include <geekos/fmtout.h>
10 unsigned short serial_io_addr = 0;
11 uint_t serial_print_level;
14 static void Serial_Interrupt_Handler(struct Interrupt_State * state) {
20 irq_id = In_Byte(serial_io_addr + 2);
23 if ((irq_id & 0x04) != 0) {
24 rcv_byte = In_Byte(serial_io_addr + 0);
26 if (rcv_byte == 'k') {
27 SerialPrint("Restarting Machine\r\n");
28 machine_real_restart();
29 } else if (rcv_byte=='d') {
30 SerialPrint("Dumping Machine State\n");
31 Dump_Interrupt_State(state);
37 SerialPrint("Unreserved serial byte: %d (%c)\r\n", rcv_byte, rcv_byte);
45 void InitSerialAddr(unsigned short io_addr) {
46 serial_io_addr = io_addr;
48 Print("Initializing Polled Serial Output on COM1 - 115200 N81 noflow\n");
49 // io_adr = 0x3F8; /* 3F8=COM1, 2F8=COM2, 3E8=COM3, 2E8=COM4 */
50 Out_Byte(io_addr + 3, 0x80);
51 // 115200 /* 115200 / 12 = 9600 baud */
52 Out_Byte(io_addr + 0, 1);
53 Out_Byte(io_addr + 1, 0);
55 Out_Byte(io_addr + 3, 0x03);
56 /* all interrupts disabled */
57 // Out_Byte(io_addr + 1, 0);
58 Out_Byte(io_addr + 1, 0x01);
59 /* turn off FIFO, if any */
60 Out_Byte(io_addr + 2, 0);
61 /* loopback off, interrupts (Out2) off, Out1/RTS/DTR off */
62 // Out_Byte(io_addr + 4, 0);
63 // enable interrupts (bit 3)
64 Out_Byte(io_addr + 4, 0x08);
70 inline static void SerialPutChar(unsigned char c) {
72 // static unsigned short io_adr;
73 if (serial_io_addr==0) {
79 /* wait for transmitter ready */
80 while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
83 Out_Byte(serial_io_addr + 0, '\r');
84 /* wait for transmitter ready */
86 while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
89 Out_Byte(serial_io_addr + 0, c);
94 void SerialPutLineN(char * line, int len) {
96 for (i = 0; i < len && line[i] != 0; i++) {
97 SerialPutChar(line[i]);
102 void SerialPutLine(char * line) {
104 for (i = 0; line[i]!= 0; i++) {
105 SerialPutChar(line[i]);
110 void SerialPrintHex(unsigned char x)
115 SerialPrint("%x", z);
117 SerialPrint("%x", z);
120 void SerialMemDump(unsigned char *start, int n)
124 for (i=0;i<n;i+=16) {
125 SerialPrint("%8x", (unsigned)(start+i));
126 for (j=i; j<i+16 && j<n; j+=2) {
128 SerialPrintHex(*((unsigned char *)(start+j)));
130 SerialPrintHex(*((unsigned char *)(start+j+1)));
134 for (j=i; j<i+16 && j<n;j++) {
135 SerialPrint("%c", ((start[j]>=32) && (start[j]<=126)) ? start[j] : '.');
142 static struct Output_Sink serial_output_sink;
143 static void Serial_Emit(struct Output_Sink * o, int ch) {
144 SerialPutChar((unsigned char)ch);
146 static void Serial_Finish(struct Output_Sink * o) { return; }
149 static void __inline__ SerialPrintInternal(const char * format, va_list ap) {
150 Format_Output(&serial_output_sink, format, ap);
154 void SerialPrint(const char * format, ...) {
156 bool iflag = Begin_Int_Atomic();
158 va_start(args, format);
159 SerialPrintInternal(format, args);
162 End_Int_Atomic(iflag);
165 void SerialPrintList(const char * format, va_list ap) {
166 bool iflag = Begin_Int_Atomic();
167 SerialPrintInternal(format, ap);
168 End_Int_Atomic(iflag);
175 void SerialPrintLevel(int level, const char * format, ...) {
176 if (level > serial_print_level) {
178 bool iflag = Begin_Int_Atomic();
180 va_start(args, format);
181 SerialPrintInternal(format, args);
184 End_Int_Atomic(iflag);
193 serial_print_level = SERIAL_PRINT_DEBUG_LEVEL;
195 Print("Initialzing Serial\n");
197 serial_output_sink.Emit = &Serial_Emit;
198 serial_output_sink.Finish = &Serial_Finish;
200 Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
201 Enable_IRQ(COM1_IRQ);
202 InitSerialAddr(DEFAULT_SERIAL_ADDR);