Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / geekos / serial.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
14  *
15  * Author: Peter Dinda <pdinda@northwestern.edu>
16  * Author: Jack Lange <jarusl@cs.northwestern.edu>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
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>
27
28
29
30
31 unsigned short serial_io_addr = 0;
32 uint_t serial_print_level;
33
34 static void Serial_Interrupt_Handler(struct Interrupt_State * state) {
35   char rcv_byte;
36   char irq_id;
37
38   Begin_IRQ(state);
39
40   irq_id = In_Byte(serial_io_addr + 2);
41
42
43   if ((irq_id & 0x04) != 0) {
44     rcv_byte = In_Byte(serial_io_addr + 0);
45
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);
52       DumpIDT();
53       DumpGDT();
54     }
55       
56 #if 0
57       SerialPrint("Unreserved serial byte: %d (%c)\r\n", rcv_byte, rcv_byte);
58 #endif
59   }
60   End_IRQ(state);
61 }
62
63
64
65 void InitSerialAddr(unsigned short io_addr) {
66   serial_io_addr = io_addr;
67
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);
74   /* 8N1 */
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);
85 }
86
87
88
89
90 void SerialPutChar(unsigned char c) {
91  
92  //  static unsigned short io_adr;
93   if (serial_io_addr==0) { 
94     return;
95   }
96
97
98   if (c=='\n') { 
99     /* wait for transmitter ready */
100     while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
101     }
102     /* send char */
103     Out_Byte(serial_io_addr + 0, '\r');
104     /* wait for transmitter ready */
105   }
106   while((In_Byte(serial_io_addr + 5) & 0x40) == 0) {
107   }
108   /* send char */
109   Out_Byte(serial_io_addr + 0, c);
110 }
111
112
113
114 void SerialPutLineN(char * line, int len) {
115   int i;
116   for (i = 0; i < len && line[i] != 0; i++) { 
117     SerialPutChar(line[i]); 
118   }
119 }
120
121
122 void SerialPutLine(char * line) {
123   int i;
124   for (i = 0; line[i]!= 0; i++) { 
125     SerialPutChar(line[i]); 
126   }
127 }
128
129
130 void SerialPrintHex(unsigned char x)
131 {
132   unsigned char z;
133   
134   z = (x>>4) & 0xf ;
135   SerialPrint("%x", z);
136   z = x & 0xf;
137   SerialPrint("%x", z);
138 }
139
140 void SerialMemDump(unsigned char *start, int n)
141 {
142   int i, j;
143
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) {
147       SerialPrint(" ");
148       SerialPrintHex(*((unsigned char *)(start+j)));
149       if ((j+1)<n) { 
150         SerialPrintHex(*((unsigned char *)(start+j+1)));
151       }
152     }
153     SerialPrint(" ");
154     for (j=i; j<i+16 && j<n;j++) {
155       SerialPrint("%c", ((start[j]>=32) && (start[j]<=126)) ? start[j] : '.');
156     }
157     SerialPrint("\n");
158   }
159 }
160
161
162 static struct Output_Sink serial_output_sink;
163 static void Serial_Emit(struct Output_Sink * o, int ch) { 
164   SerialPutChar((unsigned char)ch); 
165 }
166 static void Serial_Finish(struct Output_Sink * o) { return; }
167
168
169 static void __inline__ SerialPrintInternal(const char * format, va_list ap) {
170   Format_Output(&serial_output_sink, format, ap);
171 }
172
173
174 void SerialPrint(const char * format, ...) {
175   va_list args;
176   bool iflag = Begin_Int_Atomic();
177
178   va_start(args, format);
179   SerialPrintInternal(format, args);
180   va_end(args);
181
182   End_Int_Atomic(iflag);
183 }
184
185 void SerialPrintList(const char * format, va_list ap) {
186   bool iflag = Begin_Int_Atomic();
187   SerialPrintInternal(format, ap);
188   End_Int_Atomic(iflag);
189
190 }
191
192
193
194
195 void SerialPrintLevel(int level, const char * format, ...) {
196   if (level > serial_print_level) {
197     va_list args;
198     bool iflag = Begin_Int_Atomic();
199     
200     va_start(args, format);
201     SerialPrintInternal(format, args);
202     va_end(args);
203     
204     End_Int_Atomic(iflag);   
205   }
206 }
207
208
209
210
211 void Init_Serial() {
212
213   serial_print_level = SERIAL_PRINT_DEBUG_LEVEL;
214
215   Print("Initialzing Serial\n");
216
217   serial_output_sink.Emit = &Serial_Emit;
218   serial_output_sink.Finish = &Serial_Finish;
219
220   Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
221   Enable_IRQ(COM1_IRQ);
222   InitSerialAddr(DEFAULT_SERIAL_ADDR);
223 }