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.


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