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.


added copyright tags
[palacios.git] / palacios / src / devices / serial.c
1 /* Northwestern University */
2 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
3
4 #include <devices/serial.h>
5 #include <palacios/vmm.h>
6
7
8 #define COM1_DATA_PORT           0x3f8
9 #define COM1_IRQ_ENABLE_PORT     0x3f9
10 #define COM1_DIV_LATCH_LSB_PORT  0x3f8
11 #define COM1_DIV_LATCH_MSB_PORT  0x3f9
12 #define COM1_IIR_PORT            0x3fa
13 #define COM1_FIFO_CTRL_PORT      0x3fa
14 #define COM1_LINE_CTRL_PORT      0x3fb
15 #define COM1_MODEM_CTRL_PORT     0x3fc
16 #define COM1_LINE_STATUS_PORT    0x3fd
17 #define COM1_MODEM_STATUS_PORT   0x3fe
18 #define COM1_SCRATCH_PORT        0x3ff
19
20 #define COM2_DATA_PORT           0x2f8
21 #define COM2_IRQ_ENABLE_PORT     0x2f9
22 #define COM2_DIV_LATCH_LSB_PORT  0x2f8
23 #define COM2_DIV_LATCH_MSB_PORT  0x2f9
24 #define COM2_IIR_PORT            0x2fa
25 #define COM2_FIFO_CTRL_PORT      0x2fa
26 #define COM2_LINE_CTRL_PORT      0x2fb
27 #define COM2_MODEM_CTRL_PORT     0x2fc
28 #define COM2_LINE_STATUS_PORT    0x2fd
29 #define COM2_MODEM_STATUS_PORT   0x2fe
30 #define COM2_SCRATCH_PORT        0x2ff
31
32 #define COM3_DATA_PORT           0x3e8
33 #define COM3_IRQ_ENABLE_PORT     0x3e9
34 #define COM3_DIV_LATCH_LSB_PORT  0x3e8
35 #define COM3_DIV_LATCH_MSB_PORT  0x3e9
36 #define COM3_IIR_PORT            0x3ea
37 #define COM3_FIFO_CTRL_PORT      0x3ea
38 #define COM3_LINE_CTRL_PORT      0x3eb
39 #define COM3_MODEM_CTRL_PORT     0x3ec
40 #define COM3_LINE_STATUS_PORT    0x3ed
41 #define COM3_MODEM_STATUS_PORT   0x3ee
42 #define COM3_SCRATCH_PORT        0x3ef
43
44 #define COM4_DATA_PORT           0x2e8
45 #define COM4_IRQ_ENABLE_PORT     0x2e9
46 #define COM4_DIV_LATCH_LSB_PORT  0x2e8
47 #define COM4_DIV_LATCH_MSB_PORT  0x2e9
48 #define COM4_IIR_PORT            0x2ea
49 #define COM4_FIFO_CTRL_PORT      0x2ea
50 #define COM4_LINE_CTRL_PORT      0x2eb
51 #define COM4_MODEM_CTRL_PORT     0x2ec
52 #define COM4_LINE_STATUS_PORT    0x2ed
53 #define COM4_MODEM_STATUS_PORT   0x2ee
54 #define COM4_SCRATCH_PORT        0x2ef
55
56
57
58 struct irq_enable_reg {
59   uint_t erbfi   : 1;  // Enable Receiver Buffer full interrupt
60   uint_t etbei   : 1;  // Enable Transmit buffer empty interrupt
61   uint_t elsi    : 1;  // Enable Line Status Interrupt
62   uint_t edssi   : 1;  // Enable Delta Status signals interrupt
63   uint_t rsvd    : 4;   // MBZ
64 };
65
66
67
68 // Interrupt IDs (in priority order, highest is first)
69 #define STATUS_IRQ_LSR_OE_SET   0x3
70 #define STATUS_IRQ_LSR_PE_SET   0x3
71 #define STATUS_IRQ_LSR_FE_SET   0x3
72 #define STATUS_IRQ_LSR_BI_SET   0x3
73 #define RX_IRQ_DR               0x2
74 #define RX_IRQ_TRIGGER_LEVEL    0x2
75 #define FIFO_IRQ                0x6
76 #define TX_IRQ_THRE             0x1
77 #define MODEL_IRQ_DELTA_SET     0x0
78
79 struct irq_id_reg {
80   uint_t pending : 1; // Interrupt pending (0=interrupt pending)
81   uint_t iid     : 3; // Interrupt Identification
82   uint_t rsvd    : 2; // MBZ
83   uint_t fifo_en : 2; // FIFO enable
84 };
85
86 struct fifo_ctrl_reg {
87   uint_t enable  : 1; // enable fifo
88   uint_t rfres   : 1; // RX FIFO reset
89   uint_t xfres   : 1; // TX FIFO reset
90   uint_t dma_sel : 1; // DMA mode select
91   uint_t rsvd    : 2; // MBZ
92   uint_t rx_trigger: 2; // RX FIFO trigger level select
93 };
94
95 struct line_ctrl_reg {
96   uint_t word_len       : 2;  // word length select
97   uint_t stop_bits      : 1;  // Stop Bit select
98   uint_t parity_enable  : 1;  // Enable parity 
99   uint_t even_sel       : 1;  // Even Parity Select
100   uint_t stick_parity   : 1;  // Stick Parity Select
101   uint_t sbr            : 1;  // Set Break 
102   uint_t dlab           : 1;  // Divisor latch access bit
103 };
104
105
106 struct modem_ctrl_reg { 
107   uint_t dtr      : 1;
108   uint_t rts      : 1;
109   uint_t out1     : 1;
110   uint_t out2     : 1;
111   uint_t loop     : 1;  // loopback mode
112   uint_t rsvd     : 3;  // MBZ
113 };
114
115
116 struct line_status_reg {
117   uint_t rbf      : 1;  // Receiver Buffer Full
118   uint_t oe       : 1;  // Overrun error
119   uint_t pe       : 1;  // Parity Error
120   uint_t fe       : 1;  // Framing Error
121   uint_t brk      : 1;  // broken line detected
122   uint_t thre     : 1;  // Transmitter holding register empty
123   uint_t temt     : 1;  // Transmitter Empty
124   uint_t fifo_err : 1;  // at least one error is pending in the RX FIFO chain
125 };
126
127
128 struct modem_status_reg {
129   uint_t dcts     : 1;  // Delta Clear To Send
130   uint_t ddsr     : 1;  // Delta Data Set Ready
131   uint_t teri     : 1;  // Trailing Edge Ring Indicator
132   uint_t ddcd     : 1;  // Delta Data Carrier Detect
133   uint_t cts      : 1;  // Clear to Send
134   uint_t dsr      : 1;  // Data Set Ready
135   uint_t ri       : 1;  // Ring Indicator
136   uint_t dcd      : 1;  // Data Carrier Detect
137 };
138
139
140 #define SERIAL_BUF_LEN 256
141
142 struct serial_buffer {
143   uint_t head; // most recent data
144   uint_t tail; // oldest char
145   char buffer[SERIAL_BUF_LEN];
146 };
147
148 int queue_data(struct serial_buffer * buf, char data) {
149   int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
150
151   if (next_loc == buf->tail) {
152     return -1;
153   }
154
155   buf->buffer[next_loc] = data;
156   buf->head = next_loc;
157
158   return 0;
159 }
160
161 int dequeue_data(struct serial_buffer * buf, char * data) {
162   int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
163
164   if (buf->head == buf->tail) {
165     return -1;
166   }
167
168   *data = buf->buffer[buf->tail];
169   buf->tail = next_tail;
170
171   return 0;
172 }
173
174
175 struct serial_port {
176   char     ier;
177   char     iir;
178   char     fcr;
179   char     lcr;
180   char     mcr;
181   char     lsr;
182   char     msr;
183
184   struct serial_buffer tx_buffer;
185   struct serial_buffer rx_buffer;
186 };
187
188
189 struct serial_state {
190   struct serial_port com1;
191   struct serial_port com2;
192   struct serial_port com3;
193   struct serial_port com4;
194 };
195
196
197 int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
198   struct serial_state * state = (struct serial_state *)dev->private_data;
199   char * val = (char *)src;
200   PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src);
201
202   if (length != 1) {
203     PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
204     return -1;
205   }
206
207   switch (port) {
208   case COM1_DATA_PORT:
209     queue_data(&(state->com1.tx_buffer), *val);
210     break;
211   case COM2_DATA_PORT:
212     queue_data(&(state->com2.tx_buffer), *val);
213     break;
214   case COM3_DATA_PORT:
215     queue_data(&(state->com3.tx_buffer), *val);
216     break;
217   case COM4_DATA_PORT:
218     queue_data(&(state->com4.tx_buffer), *val);
219     break;
220   default:
221     return -1;
222   }
223   
224
225   return length;
226 }
227
228
229
230 int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
231   struct serial_state * state = (struct serial_state *)dev->private_data;
232   char * val = (char *)dst;
233   PrintDebug("Read from Data Port 0x%x\n", port);
234
235   if (length != 1) {
236     PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
237     return -1;
238   }
239
240   switch (port) {
241   case COM1_DATA_PORT:
242     dequeue_data(&(state->com1.tx_buffer), val);
243     break;
244   case COM2_DATA_PORT:
245     dequeue_data(&(state->com2.tx_buffer), val);
246     break;
247   case COM3_DATA_PORT:
248     dequeue_data(&(state->com3.tx_buffer), val);
249     break;
250   case COM4_DATA_PORT:
251     dequeue_data(&(state->com4.tx_buffer), val);
252     break;
253   default:
254     return -1;
255   }
256   
257
258   return length;
259 }
260
261
262
263 int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) {
264   
265
266   return -1;
267 }
268
269
270 int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
271   struct serial_state * state = (struct serial_state *)dev->private_data;
272   char * val = (char *)src;
273   PrintDebug("Write to Control Port (val=%x)\n", *(char *)src);
274
275   if (length != 1) {
276     PrintDebug("Invalid Write length to control port\n", port, port);
277     return -1;
278   }
279
280   switch (port) {
281   case COM1_IRQ_ENABLE_PORT:
282     if (handle_ier_write(&(state->com1), (struct irq_enable_reg *)val) == -1) {
283       return -1;
284     }
285     break;
286   case COM2_IRQ_ENABLE_PORT:
287     if (handle_ier_write(&(state->com2), (struct irq_enable_reg *)val) == -1) {
288       return -1;
289     }
290     break;
291   case COM3_IRQ_ENABLE_PORT:
292     if (handle_ier_write(&(state->com3), (struct irq_enable_reg *)val) == -1) {
293       return -1;
294     }
295     break;
296   case COM4_IRQ_ENABLE_PORT:
297     if (handle_ier_write(&(state->com4), (struct irq_enable_reg *)val) == -1) {
298       return -1;
299     }
300     break;
301
302   case COM1_FIFO_CTRL_PORT:
303   case COM2_FIFO_CTRL_PORT:
304   case COM3_FIFO_CTRL_PORT:
305   case COM4_FIFO_CTRL_PORT:
306
307   case COM1_LINE_CTRL_PORT:
308   case COM2_LINE_CTRL_PORT:
309   case COM3_LINE_CTRL_PORT:
310   case COM4_LINE_CTRL_PORT:
311
312   case COM1_MODEM_CTRL_PORT:
313   case COM2_MODEM_CTRL_PORT:
314   case COM3_MODEM_CTRL_PORT:
315   case COM4_MODEM_CTRL_PORT:
316     
317
318
319   default:
320     return -1;
321   }
322
323
324   return -1;
325 }
326
327
328
329
330 int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
331   struct serial_state * state = (struct serial_state *)dev->private_data;
332   char * val = (char *)dst;
333   PrintDebug("Read from Control Port\n");
334
335   if (length != 1) {
336     PrintDebug("Invalid Read length to control port\n");
337     return -1;
338   }
339
340   switch (port) {
341   case COM1_IRQ_ENABLE_PORT:
342     *val = state->com1.ier;
343     break;
344   case COM2_IRQ_ENABLE_PORT:
345     *val = state->com2.ier;
346     break;
347   case COM3_IRQ_ENABLE_PORT:
348     *val = state->com3.ier;
349     break;
350   case COM4_IRQ_ENABLE_PORT:
351     *val = state->com4.ier;
352     break;
353
354   case COM1_FIFO_CTRL_PORT:
355     *val = state->com1.fcr;
356     break;
357   case COM2_FIFO_CTRL_PORT:
358     *val = state->com2.fcr;
359     break;
360   case COM3_FIFO_CTRL_PORT:
361     *val = state->com3.fcr;
362     break;
363   case COM4_FIFO_CTRL_PORT:
364     *val = state->com4.fcr;
365     break;
366
367   case COM1_LINE_CTRL_PORT:
368     *val = state->com1.lcr;
369     break;
370   case COM2_LINE_CTRL_PORT:
371     *val = state->com2.lcr;
372     break;
373   case COM3_LINE_CTRL_PORT:
374     *val = state->com3.lcr;
375     break;
376   case COM4_LINE_CTRL_PORT:
377     *val = state->com4.lcr;
378     break;
379
380   case COM1_MODEM_CTRL_PORT:
381     *val = state->com1.mcr;
382     break;
383   case COM2_MODEM_CTRL_PORT:
384     *val = state->com2.mcr;
385     break;
386   case COM3_MODEM_CTRL_PORT:
387     *val = state->com3.mcr;
388     break;
389   case COM4_MODEM_CTRL_PORT:
390     *val = state->com4.mcr;
391     break;
392
393   default:
394     return -1;
395   }
396
397   return length;
398 }
399
400
401 int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
402   PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src);
403
404   return -1;
405 }
406
407 int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
408   struct serial_state * state = (struct serial_state *)dev->private_data;
409   char * val = (char *)dst;
410   PrintDebug("Read from Status Port 0x%x\n", port);
411   
412   if (length != 1) {
413     PrintDebug("Invalid Read length to control port\n");
414     return -1;
415   }
416   
417   switch (port) {
418   case COM1_LINE_STATUS_PORT:
419     *val = state->com1.lsr;
420     break;
421   case COM2_LINE_STATUS_PORT:
422     *val = state->com2.lsr;
423     break;
424   case COM3_LINE_STATUS_PORT:
425     *val = state->com3.lsr;
426     break;
427   case COM4_LINE_STATUS_PORT:
428     *val = state->com4.lsr;
429     break;
430     
431   case COM1_MODEM_STATUS_PORT:
432     *val = state->com1.msr;
433     break;
434   case COM2_MODEM_STATUS_PORT:
435     *val = state->com2.msr;
436     break;
437   case COM3_MODEM_STATUS_PORT:
438     *val = state->com3.msr;
439     break;
440   case COM4_MODEM_STATUS_PORT:
441     *val = state->com4.msr;
442     break;
443
444   default:
445     return -1;
446   }
447
448
449
450   return length;
451 }
452
453
454
455
456
457 static int init_serial_port(struct serial_port * com) {
458   //struct irq_enable_reg * ier = (struct irq_enable_reg *)&(com->ier);
459   //struct irq_id_reg * iir = (struct irq_id_reg *)&(com->iir);
460   //struct fifo_ctrl_reg * fcr = (struct fifo_ctrl_reg *)&(com->fcr);
461   //struct line_ctrl_reg * lcr = (struct line_ctrl_reg *)&(com->lcr);
462   //struct modem_ctrl_reg * mcr = (struct modem_ctrl_reg *)&(com->mcr);
463   //struct line_status_reg * lsr = (struct line_status_reg *)&(com->lsr);
464   //struct modem_status_reg * msr = (struct modem_status_reg *)&(com->msr);
465
466   com->ier = 0x00;
467   com->iir = 0x01;
468   com->fcr = 0x00;
469   com->lcr = 0x00;
470   com->mcr = 0x00;
471   com->lsr = 0x60;
472   com->msr = 0x00;
473
474   return 0;
475 }
476
477 int serial_init(struct vm_device * dev) {
478   struct serial_state * state = (struct serial_state *)dev->private_data;
479
480
481   init_serial_port(&(state->com1));
482   init_serial_port(&(state->com2));
483   init_serial_port(&(state->com3));
484   init_serial_port(&(state->com4));
485
486   dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
487   dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
488   dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
489   dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
490   dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
491   dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
492   dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
493   dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
494
495   dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
496   dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
497   dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
498   dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
499   dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
500   dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
501   dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
502   dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
503
504   dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
505   dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
506   dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
507   dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
508   dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
509   dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
510   dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
511   dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
512
513   dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
514   dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
515   dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
516   dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
517   dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
518   dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
519   dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
520   dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
521
522   return 0;
523 }
524
525
526 int serial_deinit(struct vm_device * dev) {
527
528
529   dev_unhook_io(dev, COM1_DATA_PORT);
530   dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
531   dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
532   dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
533   dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
534   dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
535   dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
536   dev_unhook_io(dev, COM1_SCRATCH_PORT);
537
538   dev_unhook_io(dev, COM2_DATA_PORT);
539   dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
540   dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
541   dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
542   dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
543   dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
544   dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
545   dev_unhook_io(dev, COM2_SCRATCH_PORT);
546
547   dev_unhook_io(dev, COM3_DATA_PORT);
548   dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
549   dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
550   dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
551   dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
552   dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
553   dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
554   dev_unhook_io(dev, COM3_SCRATCH_PORT);
555
556   dev_unhook_io(dev, COM4_DATA_PORT);
557   dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
558   dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
559   dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
560   dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
561   dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
562   dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
563   dev_unhook_io(dev, COM4_SCRATCH_PORT);
564
565   return 0;
566 }
567
568
569
570 static struct vm_device_ops dev_ops = {
571   .init = serial_init,
572   .deinit = serial_deinit,
573   .reset = NULL,
574   .start = NULL,
575   .stop = NULL,
576 };
577
578
579 struct vm_device * create_serial(int num_ports) {
580   struct serial_state * state = NULL;
581   state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
582   V3_ASSERT(state != NULL);
583
584   struct vm_device * device = create_device("Serial UART", &dev_ops, state);
585
586   return device;
587 }