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.


b5274312a84cf30600842453ebfb9e95a58d8282
[palacios.git] / palacios / src / devices / 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) 2010, Rumou Duan <duanrumou@gmail.com>
11  * Copyright (c) 2010, The V3VEE Project <http://www.v3vee.org>
12  * All rights reserved.
13  *
14  * Author: Rumou Duan <duanrumou@gmail.com>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_dev_mgr.h>
23 #include <palacios/vmm_types.h>
24
25 #include <palacios/vmm_ringbuffer.h>
26 #include <palacios/vmm_lock.h>
27 #include <palacios/vmm_intr.h>
28 #include <palacios/vmm_host_events.h>
29 #include <palacios/vm_guest.h>
30
31
32 #ifndef CONFIG_DEBUG_SERIAL
33 #undef PrintDebug
34 #define PrintDebug(fmt, args...)
35 #endif
36
37
38 #define COM1_DATA_PORT           0x3f8
39 #define COM1_IRQ_ENABLE_PORT     0x3f9
40 #define COM1_DIV_LATCH_LSB_PORT  0x3f8
41 #define COM1_DIV_LATCH_MSB_PORT  0x3f9
42 #define COM1_IIR_PORT            0x3fa
43 #define COM1_FIFO_CTRL_PORT      0x3fa
44 #define COM1_LINE_CTRL_PORT      0x3fb
45 #define COM1_MODEM_CTRL_PORT     0x3fc
46 #define COM1_LINE_STATUS_PORT    0x3fd
47 #define COM1_MODEM_STATUS_PORT   0x3fe
48 #define COM1_SCRATCH_PORT        0x3ff
49
50 #define COM2_DATA_PORT           0x2f8
51 #define COM2_IRQ_ENABLE_PORT     0x2f9
52 #define COM2_DIV_LATCH_LSB_PORT  0x2f8
53 #define COM2_DIV_LATCH_MSB_PORT  0x2f9
54 #define COM2_IIR_PORT            0x2fa
55 #define COM2_FIFO_CTRL_PORT      0x2fa
56 #define COM2_LINE_CTRL_PORT      0x2fb
57 #define COM2_MODEM_CTRL_PORT     0x2fc
58 #define COM2_LINE_STATUS_PORT    0x2fd
59 #define COM2_MODEM_STATUS_PORT   0x2fe
60 #define COM2_SCRATCH_PORT        0x2ff
61
62 #define COM3_DATA_PORT           0x3e8
63 #define COM3_IRQ_ENABLE_PORT     0x3e9
64 #define COM3_DIV_LATCH_LSB_PORT  0x3e8
65 #define COM3_DIV_LATCH_MSB_PORT  0x3e9
66 #define COM3_IIR_PORT            0x3ea
67 #define COM3_FIFO_CTRL_PORT      0x3ea
68 #define COM3_LINE_CTRL_PORT      0x3eb
69 #define COM3_MODEM_CTRL_PORT     0x3ec
70 #define COM3_LINE_STATUS_PORT    0x3ed
71 #define COM3_MODEM_STATUS_PORT   0x3ee
72 #define COM3_SCRATCH_PORT        0x3ef
73
74 #define COM4_DATA_PORT           0x2e8
75 #define COM4_IRQ_ENABLE_PORT     0x2e9
76 #define COM4_DIV_LATCH_LSB_PORT  0x2e8
77 #define COM4_DIV_LATCH_MSB_PORT  0x2e9
78 #define COM4_IIR_PORT            0x2ea
79 #define COM4_FIFO_CTRL_PORT      0x2ea
80 #define COM4_LINE_CTRL_PORT      0x2eb
81 #define COM4_MODEM_CTRL_PORT     0x2ec
82 #define COM4_LINE_STATUS_PORT    0x2ed
83 #define COM4_MODEM_STATUS_PORT   0x2ee
84 #define COM4_SCRATCH_PORT        0x2ef
85
86
87 // Interrupt IDs (in priority order, highest is first)
88 #define STATUS_IRQ_LSR_OE_SET   0x3
89 #define STATUS_IRQ_LSR_PE_SET   0x3
90 #define STATUS_IRQ_LSR_FE_SET   0x3
91 #define STATUS_IRQ_LSR_BI_SET   0x3
92 #define RX_IRQ_DR               0x2
93 #define RX_IRQ_TRIGGER_LEVEL    0x2
94 #define FIFO_IRQ                0x6
95 #define TX_IRQ_THRE             0x1
96 #define MODEL_IRQ_DELTA_SET     0x0
97
98 //COMs IRQ ID
99 #define COM1_IRQ  0x4
100 #define COM2_IRQ  0x3
101 #define COM3_IRQ  0x4
102 #define COM4_IRQ  0x3
103
104 #define RX_BUFFER 0x1
105 #define TX_BUFFER 0x2
106
107 //initial value for registers
108
109 #define  IER_INIT_VAL 0x3
110 //receive data available interrupt and THRE interrupt are enabled
111 #define  IIR_INIT_VAL 0x1
112 //No Pending Interrupt bit is set.
113 #define  FCR_INIT_VAL 0xc0
114 //fifo control register is set to 0
115 #define  LCR_INIT_VAL 0x3
116 #define  MCR_INIT_VAL 0x0
117 #define  LSR_INIT_VAL 0x60
118 #define  MSR_INIT_VAL 0x0
119 #define  DLL_INIT_VAL 0x1
120 #define  DLM_INIT_VAL 0x0
121
122
123
124 //receiver buffer register
125 struct rbr_register {
126     uint8_t data;
127 };
128
129 // transmitter holding register
130 struct thr_register {
131     uint8_t data;
132 };
133
134 //interrupt enable register
135 struct ier_register {
136     union {
137         uint8_t val;
138         struct {
139             uint8_t erbfi   : 1;   // Enable Receiver Buffer full interrupt
140             uint8_t etbei   : 1;  // Enable Transmit buffer empty interrupt
141             uint8_t elsi    : 1;  // Enable Line Status Interrupt
142             uint8_t edssi   : 1;  // Enable Delta Status signals interrupt
143             uint8_t rsvd    : 4;   // MBZ
144         } __attribute__((packed));
145     } __attribute__((packed));
146 } __attribute__((packed));
147
148
149 //interrupt identification register
150 struct iir_register {
151     union {
152         uint8_t val;
153         struct {
154             uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
155             uint8_t iid     : 3; // Interrupt Identification
156             uint8_t rsvd    : 2; // MBZ
157             uint8_t fifo_en : 2; // FIFO enable
158         } __attribute__((packed));
159     } __attribute__((packed));
160 } __attribute__((packed));
161
162 //FIFO control register
163 struct fcr_register {
164     union {
165         uint8_t val;
166         struct {
167             uint8_t enable  : 1; // enable fifo
168             uint8_t rfres   : 1; // RX FIFO reset
169             uint8_t xfres   : 1; // TX FIFO reset
170             uint8_t dma_sel : 1; // DMA mode select
171             uint8_t rsvd    : 2; // MBZ
172             uint8_t rx_trigger: 2; // RX FIFO trigger level select
173         } __attribute__((packed));
174     } __attribute__((packed));
175 } __attribute__((packed));
176
177
178 //line control register
179 struct lcr_register {
180     union {
181         uint8_t val;
182         struct {
183             uint8_t word_len       : 2;  // word length select
184             uint8_t stop_bits      : 1;  // Stop Bit select
185             uint8_t parity_enable  : 1;  // Enable parity
186             uint8_t even_sel       : 1;  // Even Parity Select
187             uint8_t stick_parity   : 1;  // Stick Parity Select
188             uint8_t sbr            : 1;  // Set Break
189             uint8_t dlab           : 1;  // Divisor latch access bit
190         } __attribute__((packed));
191     } __attribute__((packed));
192 } __attribute__((packed));
193
194
195 //modem control register
196 struct mcr_register {
197     union {
198         uint8_t val;
199         struct {
200             uint8_t dtr      : 1;
201             uint8_t rts      : 1;
202             uint8_t out1     : 1;
203             uint8_t out2     : 1;
204             uint8_t loop     : 1;  // loopback mode
205             uint8_t rsvd     : 3;  // MBZ
206         } __attribute__((packed));
207     } __attribute__((packed));
208 } __attribute__((packed));
209
210
211 //line status register
212 struct lsr_register {
213     union {
214         uint8_t val;
215         struct {
216             uint8_t dr      : 1;  // data ready
217             uint8_t oe       : 1;  // Overrun error
218             uint8_t pe       : 1;  // Parity Error
219             uint8_t fe       : 1;  // Framing Error
220             uint8_t brk      : 1;  // broken line detected
221             uint8_t thre     : 1;  // Transmitter holding register empty
222             uint8_t temt     : 1;  // Transmitter Empty
223             uint8_t fifo_err : 1;  // at least one error is pending in the RX FIFO chain
224         } __attribute__((packed));
225     } __attribute__((packed));
226 } __attribute__((packed));
227
228
229 struct msr_register {
230     union {
231         uint8_t val;
232         struct {
233             uint8_t dcts     : 1;  // Delta Clear To Send
234             uint8_t ddsr     : 1;  // Delta Data Set Ready
235             uint8_t teri     : 1;  // Trailing Edge Ring Indicator
236             uint8_t ddcd     : 1;  // Delta Data Carrier Detect
237             uint8_t cts      : 1;  // Clear to Send
238             uint8_t dsr      : 1;  // Data Set Ready
239             uint8_t ri       : 1;  // Ring Indicator
240             uint8_t dcd      : 1;  // Data Carrier Detect
241         } __attribute__((packed));
242     } __attribute__((packed));
243 } __attribute__((packed));
244
245 //scratch register
246 struct scr_register {
247     uint8_t data;
248 };
249
250 //divisor latch LSB
251 struct dll_register {
252     uint8_t data;
253 };
254
255 //divisor latch MSB
256 struct dlm_register {
257     uint8_t data;
258 };
259 #define SERIAL_BUF_LEN 16
260
261 struct serial_buffer {
262     int head; // most recent data
263     int tail; // oldest char
264     int full;
265     uint8_t buffer[SERIAL_BUF_LEN];
266 };
267
268 struct serial_port {
269     struct rbr_register     rbr;
270     struct thr_register     thr;
271     struct ier_register     ier;
272     struct iir_register     iir;
273     struct fcr_register     fcr;
274     struct lcr_register     lcr;
275     struct mcr_register     mcr;
276     struct lsr_register     lsr;
277     struct msr_register     msr;
278     struct scr_register     scr;
279     struct dll_register     dll;
280     struct dlm_register     dlm;
281     
282     
283     struct serial_buffer tx_buffer;
284     struct serial_buffer rx_buffer;
285     uint_t irq_number;
286 };
287
288
289 struct serial_state {
290     struct serial_port com1;
291     struct serial_port com2;
292     struct serial_port com3;
293     struct serial_port com4;
294 };
295
296
297
298 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
299     if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
300         return &(serial->com1);
301     } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
302         return &(serial->com2);
303     } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
304         return &(serial->com3);
305     } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
306         return &(serial->com4);
307     } else {
308         PrintError("Error: Could not find serial port associated with IO port %d\n", port);
309         return NULL;
310     }
311 }
312
313 static inline bool receive_buffer_trigger(int number, int trigger_number) {
314
315     switch (trigger_number) {
316         case 0:
317             return (number >= 1);
318         case 1:
319             return (number >= 4);
320         case 2:
321             return (number >= 8);
322         case 3:
323             return (number >= 14);
324     }
325
326     return false;
327 }
328
329 static int getNumber(struct serial_buffer * buf) {
330     int number = buf->head - buf->tail;
331   
332     if (buf->full == 1) {
333         return SERIAL_BUF_LEN;
334     } else if (number >= 0) {
335         return number;
336     } else {
337         return SERIAL_BUF_LEN + number;
338     }
339 }
340
341 static int updateIRQ(struct serial_port * com, struct vm_device * dev) {
342     
343     if ( (com->ier.erbfi == 0x1) && 
344          (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
345
346         PrintDebug("UART: receive buffer interrupt(trigger level reached)");
347
348         com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
349         v3_raise_irq(dev->vm, com->irq_number);
350     }
351     
352     if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) && 
353          (!(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger))) ) {
354
355         com->iir.iid = 0x0;   //reset interrupt identification register
356         com->iir.pending = 0x1;
357     }
358     
359     if ( (com->iir.iid == TX_IRQ_THRE) && 
360          (getNumber(&(com->tx_buffer)) == SERIAL_BUF_LEN)) {
361
362         com->iir.iid = 0x0; //reset interrupt identification register
363         com->iir.pending = 0x1;
364
365     } else if ( (com->ier.etbei == 0x1) && 
366                 (getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
367         
368         PrintDebug("UART: transmit buffer interrupt(buffer not full)");
369
370         com->iir.iid = TX_IRQ_THRE;
371         com->iir.pending = 0;
372
373         v3_raise_irq(dev->vm, com->irq_number);
374     }
375
376     return 1;
377 }
378
379
380 static int queue_data(struct serial_buffer * buf, uint8_t  data, 
381                       struct serial_port * com, struct vm_device * dev) {
382
383     int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;    
384
385     if (buf->full == 1) {
386         PrintDebug("Buffer is full!\n");
387
388         if (buf == &(com->rx_buffer)) {
389             com->lsr.oe = 1; //overrun error bit set
390         }
391
392         return 0;
393     }
394     
395     buf->buffer[next_loc] = data;
396     buf->head = next_loc;
397     
398     if (buf->head == buf->tail) {
399         buf->full = 1;
400     }
401     
402     if (buf == &(com->rx_buffer)) {
403         com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
404     }
405     
406     if (buf == &(com->tx_buffer)) {
407         com->lsr.thre = 0; //reset thre and temt bits.
408         com->lsr.temt = 0;
409     }
410     
411     updateIRQ(com, dev);
412     
413     return 0;
414 }
415
416 static int dequeue_data(struct serial_buffer * buf, uint8_t * data, 
417                         struct serial_port * com, struct vm_device * dev) {
418
419     int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
420
421
422     if ( (buf->head == buf->tail) && (buf->full != 1) ) {
423         PrintDebug("no data to delete!\n");
424         return -1;
425     }
426     
427     if (buf->full == 1) {
428         buf->full = 0;
429     }
430     
431         
432     *data = buf->buffer[next_tail];
433     buf->buffer[next_tail] = 0;
434     buf->tail = next_tail;
435     
436     if ( (buf == &(com->rx_buffer)) && (getNumber(&(com->rx_buffer)) == 0) ) {
437         com->lsr.dr = 0;
438     }
439     
440     if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
441         com->lsr.thre = 1;
442         com->lsr.temt = 1;
443     }
444     
445     updateIRQ(com, dev);
446     
447     return 0;
448 }
449
450 /*
451 static void printBuffer(struct serial_buffer * buf) {
452     int i = 0;
453
454     for (i = 0; i < SERIAL_BUF_LEN; i++) {
455         PrintDebug(" %d ", buf->buffer[i]);
456     }
457
458     PrintDebug("\n the number of elements is %d \n", getNumber(buf));
459 }
460 */
461
462 //note: write to data port is NOT implemented and corresponding codes are commented out
463 static int write_data_port(struct guest_info * core, uint16_t port, 
464                            void * src, uint_t length, struct vm_device * dev) {
465     struct serial_state * state = (struct serial_state *)dev->private_data;
466     uint8_t * val = (uint8_t *)src;
467     struct serial_port * com_port = NULL;
468
469     PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
470     
471     if (length != 1) {
472         PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
473         return -1;
474     }
475
476     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
477         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
478         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
479         return -1;
480     }
481
482     com_port = get_com_from_port(state, port);
483
484     if (com_port == NULL) {
485         PrintDebug("UART:read from NOBODY");
486         return -1;
487     }
488     
489
490     // dlab is always checked first
491     if (com_port->lcr.dlab == 1) {
492         com_port->dll.data = *val;
493     }  else {
494         queue_data(&(com_port->tx_buffer), *val, com_port, dev);
495     }
496     
497     
498     return length;
499 }
500
501
502
503 static int read_data_port(struct guest_info * core, uint16_t port, 
504                           void * dst, uint_t length, struct vm_device * dev) {
505     struct serial_state * state = (struct serial_state *)dev->private_data;
506     uint8_t * val = (uint8_t *)dst;
507     struct serial_port * com_port = NULL;
508
509     PrintDebug("Read from Data Port 0x%x\n", port);
510     
511     if (length != 1) {
512         PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
513         return -1;
514     }
515     
516     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
517         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
518         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
519         return -1;
520     }
521
522     com_port = get_com_from_port(state, port);
523
524     if (com_port == NULL) {
525         PrintDebug("UART:read from NOBODY");
526         return -1;
527     }
528     
529     if (com_port->lcr.dlab == 1) {
530         *val = com_port->dll.data;
531     } else {
532         dequeue_data(&(com_port->rx_buffer), val, com_port, dev);
533     }
534     
535     return length;
536 }
537
538
539
540 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
541
542     com->fcr.enable = value & 0x1;
543     
544     if (com->fcr.enable == 0x1) {
545         com->fcr.val = value;
546
547         com->fcr.enable = 1; // Do we need to set this??
548
549         //if rfres set, clear receive buffer.
550         if (com->fcr.rfres == 0x1) {
551             com->rx_buffer.head = 0;
552             com->rx_buffer.tail = 0;
553             com->rx_buffer.full = 0;
554             memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
555             com->fcr.rfres = 0;
556         }
557
558         //if xfres set, clear transmit buffer.
559         if (com->fcr.xfres == 0x1) {
560             com->tx_buffer.head = 0;
561             com->tx_buffer.tail = 0;
562             com->tx_buffer.full = 0;
563             memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
564             com->fcr.xfres = 0;
565         }
566     } else {
567         //clear both buffers.
568         com->tx_buffer.head = 0;
569         com->tx_buffer.tail = 0;
570         com->tx_buffer.full = 0;
571         com->rx_buffer.head = 0;
572         com->rx_buffer.tail = 0;
573         com->rx_buffer.full = 0;
574         
575         memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
576         memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
577     }
578     
579     return 1;
580 }
581
582
583
584
585
586 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src, 
587                            uint_t length, struct vm_device * dev) {
588     struct serial_state * state = (struct serial_state *)dev->private_data;
589     uint8_t val = *(uint8_t *)src;
590     struct serial_port * com_port = NULL;
591
592     PrintDebug("UART:Write to Control Port (val=%x)\n", val);
593     
594     if (length != 1) {
595         PrintDebug("UART:Invalid Write length to control port%d\n", port);
596         return -1;
597     }
598
599     com_port = get_com_from_port(state, port);
600
601     if (com_port == NULL) {
602         PrintError("Could not find serial port corresponding to IO port %d\n", port);
603         return -1;
604     }
605     
606     //always check dlab first
607     switch (port) {
608         case COM1_IRQ_ENABLE_PORT:
609         case COM2_IRQ_ENABLE_PORT:
610         case COM3_IRQ_ENABLE_PORT:
611         case COM4_IRQ_ENABLE_PORT: {
612             PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
613
614             if (com_port->lcr.dlab == 1) {
615                 com_port->dlm.data = val;
616             } else {
617                 com_port->ier.val = val;
618             }
619
620             break;
621         }           
622         case COM1_FIFO_CTRL_PORT:
623         case COM2_FIFO_CTRL_PORT:
624         case COM3_FIFO_CTRL_PORT:
625         case COM4_FIFO_CTRL_PORT: {
626             PrintDebug("UART:Write to FCR");
627
628             if (handle_fcr_write(com_port, val) == -1) {
629                 return -1;
630             }
631
632             break;
633         }
634         case COM1_LINE_CTRL_PORT:
635         case COM2_LINE_CTRL_PORT:
636         case COM3_LINE_CTRL_PORT:
637         case COM4_LINE_CTRL_PORT: {
638             PrintDebug("UART:Write to LCR");
639             com_port->lcr.val = val;
640             break;
641         }
642         case COM1_MODEM_CTRL_PORT:
643         case COM2_MODEM_CTRL_PORT:
644         case COM3_MODEM_CTRL_PORT:
645         case COM4_MODEM_CTRL_PORT: {
646             PrintDebug("UART:Write to MCR");
647             com_port->mcr.val = val;
648             break;
649         }
650         case COM1_SCRATCH_PORT:
651         case COM2_SCRATCH_PORT:
652         case COM3_SCRATCH_PORT:
653         case COM4_SCRATCH_PORT: {
654             PrintDebug("UART:Write to SCRATCH");
655             com_port->scr.data = val;
656             break;
657         }
658         default:
659             PrintDebug("UART:Write to NOBODY, ERROR");
660             return -1;
661     }
662     
663
664     return length;
665 }
666
667
668
669
670 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst, 
671                           uint_t length, struct vm_device * dev) {
672     struct serial_state * state = (struct serial_state *)dev->private_data;
673     uint8_t * val = (uint8_t *)dst;
674     struct serial_port * com_port = NULL;
675
676     PrintDebug("Read from Control Port\n");
677     
678     if (length != 1) {
679         PrintDebug("Invalid Read length to control port\n");
680         return -1;
681     }
682
683     com_port = get_com_from_port(state, port);
684
685     if (com_port == NULL) {
686         PrintError("Could not find serial port corresponding to IO port %d\n", port);
687         return -1;
688     }
689     
690     //always check dlab first
691     switch (port) {
692         case COM1_IRQ_ENABLE_PORT:
693         case COM2_IRQ_ENABLE_PORT:
694         case COM3_IRQ_ENABLE_PORT:
695         case COM4_IRQ_ENABLE_PORT: {
696             PrintDebug("UART:read from IER");
697
698             if (com_port->lcr.dlab == 1) {
699                 *val = com_port->dlm.data;
700             } else {
701                 *val = com_port->ier.val;
702             }
703             break;
704         }
705
706         case COM1_FIFO_CTRL_PORT:
707         case COM2_FIFO_CTRL_PORT:
708         case COM3_FIFO_CTRL_PORT:
709         case COM4_FIFO_CTRL_PORT:
710             PrintDebug("UART:read from FCR");
711             *val = com_port->fcr.val;
712             break;
713
714         case COM1_LINE_CTRL_PORT:
715         case COM2_LINE_CTRL_PORT:
716         case COM3_LINE_CTRL_PORT:
717         case COM4_LINE_CTRL_PORT:
718             PrintDebug("UART:read from LCR");
719             *val = com_port->lcr.val;
720             break;
721
722         case COM1_MODEM_CTRL_PORT:
723         case COM2_MODEM_CTRL_PORT:
724         case COM3_MODEM_CTRL_PORT:
725         case COM4_MODEM_CTRL_PORT:
726             PrintDebug("UART:read from MCR");
727             *val = com_port->mcr.val;
728             break;
729
730         case COM1_SCRATCH_PORT:
731         case COM2_SCRATCH_PORT:
732         case COM3_SCRATCH_PORT:
733         case COM4_SCRATCH_PORT:
734             PrintDebug("UART:read from SCRATCH");
735             *val = com_port->scr.data;
736             break;
737
738         default:
739             PrintDebug("UART:read from NOBODY");
740             return -1;
741     }
742
743     return length;
744 }
745
746
747 static int write_status_port(struct guest_info * core, uint16_t port, void * src, 
748                              uint_t length, struct vm_device * dev) {
749     struct serial_state * state = (struct serial_state *)dev->private_data;
750     uint8_t val = *(uint8_t *)src;
751     struct serial_port * com_port = NULL;
752
753     PrintDebug("Write to Status Port (val=%x)\n", val);
754
755     if (length != 1) {
756         PrintDebug("Invalid Write length to status port %d\n", port);
757         return -1;
758     }
759
760     com_port = get_com_from_port(state, port);
761
762     if (com_port == NULL) {
763         PrintError("Could not find serial port corresponding to IO port %d\n", port);
764         return -1;
765     }
766
767     switch (port) {
768         case COM1_LINE_STATUS_PORT:
769         case COM2_LINE_STATUS_PORT:
770         case COM3_LINE_STATUS_PORT:
771         case COM4_LINE_STATUS_PORT:
772             PrintDebug("UART:write to LSR");
773             com_port->lsr.val = val;
774             break;
775
776         case COM1_MODEM_STATUS_PORT:
777         case COM2_MODEM_STATUS_PORT:
778         case COM3_MODEM_STATUS_PORT:
779         case COM4_MODEM_STATUS_PORT:
780             PrintDebug("UART:write to MSR");
781             com_port->msr.val = val;
782             break;
783
784         default:
785             PrintDebug("UART:write to NOBODY");
786             return -1;
787     }
788
789     return length;
790 }
791
792 static int read_status_port(struct guest_info * core, uint16_t port, void * dst, 
793                             uint_t length, struct vm_device * dev) {
794     struct serial_state * state = (struct serial_state *)dev->private_data;
795     uint8_t * val = (uint8_t *)dst;
796     struct serial_port * com_port = NULL;
797
798     PrintDebug("Read from Status Port 0x%x\n", port);
799
800     if (length != 1) {
801         PrintDebug("Invalid Read length to control port\n");
802         return -1;
803     }
804
805     com_port = get_com_from_port(state, port);
806
807     if (com_port == NULL) {
808         PrintError("Could not find serial port corresponding to IO port %d\n", port);
809         return -1;
810     }
811
812     switch (port) {
813         case COM1_LINE_STATUS_PORT:
814         case COM2_LINE_STATUS_PORT:
815         case COM3_LINE_STATUS_PORT:
816         case COM4_LINE_STATUS_PORT:
817             PrintDebug("UART:read from LSR");
818
819             *val = com_port->lsr.val;
820             com_port->lsr.oe = 0;     // Why do we clear this??
821
822             break;
823
824         case COM1_MODEM_STATUS_PORT:
825         case COM2_MODEM_STATUS_PORT:
826         case COM3_MODEM_STATUS_PORT:
827         case COM4_MODEM_STATUS_PORT:
828             PrintDebug("UART:read from COM4 MSR");
829             *val = com_port->msr.val;
830             break;
831
832         default:
833             PrintDebug("UART:read from NOBODY");
834             return -1;
835     }
836
837     return length;
838 }
839
840 static int serial_deinit(struct vm_device * dev) {
841
842
843     v3_dev_unhook_io(dev, COM1_DATA_PORT);
844     v3_dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
845     v3_dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
846     v3_dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
847     v3_dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
848     v3_dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
849     v3_dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
850     v3_dev_unhook_io(dev, COM1_SCRATCH_PORT);
851
852     v3_dev_unhook_io(dev, COM2_DATA_PORT);
853     v3_dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
854     v3_dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
855     v3_dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
856     v3_dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
857     v3_dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
858     v3_dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
859     v3_dev_unhook_io(dev, COM2_SCRATCH_PORT);
860
861     v3_dev_unhook_io(dev, COM3_DATA_PORT);
862     v3_dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
863     v3_dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
864     v3_dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
865     v3_dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
866     v3_dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
867     v3_dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
868     v3_dev_unhook_io(dev, COM3_SCRATCH_PORT);
869
870     v3_dev_unhook_io(dev, COM4_DATA_PORT);
871     v3_dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
872     v3_dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
873     v3_dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
874     v3_dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
875     v3_dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
876     v3_dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
877     v3_dev_unhook_io(dev, COM4_SCRATCH_PORT);
878
879     return 0;
880 }
881
882
883
884
885 static struct v3_device_ops dev_ops = {
886     //.init = serial_init,
887     .free = serial_deinit,
888     .reset = NULL,
889     .start = NULL,
890     .stop = NULL,
891 };
892
893
894
895 static int init_serial_port(struct serial_port * com) {
896
897     com->ier.val = IER_INIT_VAL;
898     com->iir.val = IIR_INIT_VAL;
899     com->fcr.val = FCR_INIT_VAL;
900     com->lcr.val = LCR_INIT_VAL;
901     com->mcr.val = MCR_INIT_VAL;
902     com->lsr.val = LSR_INIT_VAL;
903     com->msr.val = MSR_INIT_VAL;
904
905     com->dll.data =  DLL_INIT_VAL;
906     com->dlm.data =  DLM_INIT_VAL;
907     
908     com->tx_buffer.head = 0;
909     com->tx_buffer.tail = 0;
910     com->tx_buffer.full = 0;
911     memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
912
913     com->rx_buffer.head = 0;
914     com->rx_buffer.tail = 0;
915     com->rx_buffer.full = 0;
916     memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
917     
918     return 0;
919 }
920
921 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
922     struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
923     char * dev_id = v3_cfg_val(cfg, "ID");
924
925     PrintDebug("UART: init_device\n");
926     init_serial_port(&(state->com1));
927     init_serial_port(&(state->com2));
928     init_serial_port(&(state->com3));
929     init_serial_port(&(state->com4));
930
931     state->com1.irq_number = COM1_IRQ;
932     state->com2.irq_number = COM2_IRQ;
933     state->com3.irq_number = COM3_IRQ;
934     state->com4.irq_number = COM4_IRQ;
935
936
937     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
938
939     if (v3_attach_device(vm, dev) == -1) {
940         PrintError("Could not attach device %s\n", dev_id);
941         return -1;
942     }
943
944     v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
945     v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
946     v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
947     v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
948     v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
949     v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
950     v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
951     v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
952
953     v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
954     v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
955     v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
956     v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
957     v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
958     v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
959     v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
960     v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
961
962     v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
963     v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
964     v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
965     v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
966     v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
967     v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
968     v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
969     v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
970
971     v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
972     v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
973     v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
974     v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
975     v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
976     v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
977     v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
978     v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
979
980     return 0;
981 }
982
983
984 device_register("SERIAL", serial_init)