2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu>
11 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
12 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Peter Dinda <pdinda@northwestern.edu>
16 * Author: Jack Lange <jarusl@cs.northwestern.edu>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <geekos/serial.h>
23 #include <geekos/reboot.h>
24 #include <geekos/gdt.h>
25 #include <geekos/idt.h>
26 #include <geekos/fmtout.h>
31 unsigned short serial_io_addr = 0;
32 uint_t serial_print_level;
34 static void Serial_Interrupt_Handler(struct Interrupt_State * state) {
40 irq_id = In_Byte(serial_io_addr + 2);
43 if ((irq_id & 0x04) != 0) {
44 rcv_byte = In_Byte(serial_io_addr + 0);
46 if (rcv_byte == 'k') {
47 SerialPrint("Restarting Machine\r\n");
48 machine_real_restart();
49 } else if (rcv_byte=='d') {
50 SerialPrint("Dumping Machine State\n");
51 Dump_Interrupt_State(state);
57 SerialPrint("Unreserved serial byte: %d (%c)\r\n", rcv_byte, rcv_byte);
65 void InitSerialAddr(unsigned short io_addr) {
66 serial_io_addr = io_addr;
68 Print("Initializing Polled Serial Output on COM1 - 115200 N81 noflow\n");
69 // io_adr = 0x3F8; /* 3F8=COM1, 2F8=COM2, 3E8=COM3, 2E8=COM4 */
70 Out_Byte(io_addr + 3, 0x80);
71 // 115200 /* 115200 / 12 = 9600 baud */
72 Out_Byte(io_addr + 0, 1);
73 Out_Byte(io_addr + 1, 0);
75 Out_Byte(io_addr + 3, 0x03);
76 /* all interrupts disabled */
77 // Out_Byte(io_addr + 1, 0);
78 Out_Byte(io_addr + 1, 0x01);
79 /* turn off FIFO, if any */
80 Out_Byte(io_addr + 2, 0);
81 /* loopback off, interrupts (Out2) off, Out1/RTS/DTR off */
82 // Out_Byte(io_addr + 4, 0);
83 // enable interrupts (bit 3)
84 Out_Byte(io_addr + 4, 0x08);
90 void SerialPutChar(unsigned char c) {
92 // static unsigned short io_adr;
93 if (serial_io_addr==0) {
99 /* wait for transmitter ready */
100 while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
103 Out_Byte(serial_io_addr + 0, '\r');
104 /* wait for transmitter ready */
106 while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
109 Out_Byte(serial_io_addr + 0, c);
114 void SerialPutLineN(char * line, int len) {
116 for (i = 0; i < len && line[i] != 0; i++) {
117 SerialPutChar(line[i]);
122 void SerialPutLine(char * line) {
124 for (i = 0; line[i]!= 0; i++) {
125 SerialPutChar(line[i]);
130 void SerialPrintHex(unsigned char x)
135 SerialPrint("%x", z);
137 SerialPrint("%x", z);
140 void SerialMemDump(unsigned char *start, int n)
144 for (i=0;i<n;i+=16) {
145 SerialPrint("%8x", (unsigned)(start+i));
146 for (j=i; j<i+16 && j<n; j+=2) {
148 SerialPrintHex(*((unsigned char *)(start+j)));
150 SerialPrintHex(*((unsigned char *)(start+j+1)));
154 for (j=i; j<i+16 && j<n;j++) {
155 SerialPrint("%c", ((start[j]>=32) && (start[j]<=126)) ? start[j] : '.');
162 static struct Output_Sink serial_output_sink;
163 static void Serial_Emit(struct Output_Sink * o, int ch) {
164 SerialPutChar((unsigned char)ch);
166 static void Serial_Finish(struct Output_Sink * o) { return; }
169 static void __inline__ SerialPrintInternal(const char * format, va_list ap) {
170 Format_Output(&serial_output_sink, format, ap);
174 void SerialPrint(const char * format, ...) {
176 bool iflag = Begin_Int_Atomic();
178 va_start(args, format);
179 SerialPrintInternal(format, args);
182 End_Int_Atomic(iflag);
185 void SerialPrintList(const char * format, va_list ap) {
186 bool iflag = Begin_Int_Atomic();
187 SerialPrintInternal(format, ap);
188 End_Int_Atomic(iflag);
195 void SerialPrintLevel(int level, const char * format, ...) {
196 if (level > serial_print_level) {
198 bool iflag = Begin_Int_Atomic();
200 va_start(args, format);
201 SerialPrintInternal(format, args);
204 End_Int_Atomic(iflag);
213 serial_print_level = SERIAL_PRINT_DEBUG_LEVEL;
215 Print("Initialzing Serial\n");
217 serial_output_sink.Emit = &Serial_Emit;
218 serial_output_sink.Finish = &Serial_Finish;
220 Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
221 Enable_IRQ(COM1_IRQ);
222 InitSerialAddr(DEFAULT_SERIAL_ADDR);