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.


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