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.


Fix virtual serial to use stream backend access
[palacios.releases.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  *             Lei Xia <lxia@northwestern.edu>
16  *
17  * This is free software.  You are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20
21
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_dev_mgr.h>
24 #include <palacios/vmm_types.h>
25
26 #include <palacios/vmm_ringbuffer.h>
27 #include <palacios/vmm_lock.h>
28 #include <palacios/vmm_intr.h>
29 #include <palacios/vm_guest.h>
30
31 #include <devices/serial.h>
32
33
34 #ifndef V3_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
290     void * backend_data;
291     struct v3_dev_char_ops * ops;
292
293 };
294
295
296 struct serial_state {
297     struct serial_port coms[4];
298
299 };
300
301
302
303 static struct serial_port * get_com_from_port(struct serial_state * serial, uint16_t port) {
304     if ((port >= COM1_DATA_PORT) && (port <= COM1_SCRATCH_PORT)) {
305         return &(serial->coms[0]);
306     } else if ((port >= COM2_DATA_PORT) && (port <= COM2_SCRATCH_PORT)) {
307         return &(serial->coms[1]);
308     } else if ((port >= COM3_DATA_PORT) && (port <= COM3_SCRATCH_PORT)) {
309         return &(serial->coms[2]);
310     } else if ((port >= COM4_DATA_PORT) && (port <= COM4_SCRATCH_PORT)) {
311         return &(serial->coms[3]);
312     } else {
313         PrintError("Error: Could not find serial port associated with IO port %d\n", port);
314         return NULL;
315     }
316 }
317
318 static inline bool receive_buffer_trigger(int number, int trigger_number) {
319
320     switch (trigger_number) {
321         case 0:
322             return (number >= 1);
323         case 1:
324             return (number >= 4);
325         case 2:
326             return (number >= 8);
327         case 3:
328             return (number >= 14);
329     }
330
331     return false;
332 }
333
334 static int getNumber(struct serial_buffer * buf) {
335     int number = buf->head - buf->tail;
336   
337     if (buf->full == 1) {
338         return SERIAL_BUF_LEN;
339     } else if (number >= 0) {
340         return number;
341     } else {
342         return SERIAL_BUF_LEN + number;
343     }
344 }
345
346 static int updateIRQ(struct v3_vm_info * vm, struct serial_port * com) {
347     
348     if ( (com->ier.erbfi == 0x1) && 
349          (receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger)) ) {
350
351         PrintDebug("UART: receive buffer interrupt(trigger level reached)\n");
352
353         com->iir.iid = RX_IRQ_TRIGGER_LEVEL;
354         v3_raise_irq(vm, com->irq_number);
355     }
356     
357     if ( (com->iir.iid == RX_IRQ_TRIGGER_LEVEL) && 
358          (!(receive_buffer_trigger( getNumber(&(com->rx_buffer)), com->fcr.rx_trigger))) ) {
359
360         com->iir.iid = 0x0;   //reset interrupt identification register
361         com->iir.pending = 0x1;
362     }
363     
364     if ( (com->iir.iid == TX_IRQ_THRE) && 
365          (getNumber(&(com->tx_buffer)) == SERIAL_BUF_LEN)) {
366
367         com->iir.iid = 0x0; //reset interrupt identification register
368         com->iir.pending = 0x1;
369
370     } else if ( (com->ier.etbei == 0x1) && 
371                 (getNumber(&(com->tx_buffer)) != SERIAL_BUF_LEN )) {
372         
373         PrintDebug("UART: transmit buffer interrupt(buffer not full)\n");
374
375         com->iir.iid = TX_IRQ_THRE;
376         com->iir.pending = 0;
377
378         v3_raise_irq(vm, com->irq_number);
379     }
380
381     return 1;
382 }
383
384
385 static int queue_data(struct v3_vm_info * vm, struct serial_port * com,
386                       struct serial_buffer * buf, uint8_t data) {
387     int next_loc = (buf->head + 1) % SERIAL_BUF_LEN;    
388
389     if (buf->full == 1) {
390         PrintDebug("Buffer is full!\n");
391
392         if (buf == &(com->rx_buffer)) {
393             com->lsr.oe = 1; //overrun error bit set
394         }
395
396         updateIRQ(vm, com);
397
398         return 0;
399     }
400     
401     buf->buffer[next_loc] = data;
402     buf->head = next_loc;
403     
404     if (buf->head == buf->tail) {
405         buf->full = 1;
406     }
407     
408     if (buf == &(com->rx_buffer)) {
409         com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
410     }
411     
412     if (buf == &(com->tx_buffer)) {
413         com->lsr.thre = 0; //reset thre and temt bits.
414         com->lsr.temt = 0;
415     }
416         
417     return 0;
418 }
419
420 static int dequeue_data(struct v3_vm_info * vm, struct serial_port * com,
421                         struct serial_buffer * buf, uint8_t * data) {
422
423     int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
424
425
426     if ( (buf->head == buf->tail) && (buf->full != 1) ) {
427         PrintDebug("no data to delete!\n");
428         return -1;
429     }
430     
431     if (buf->full == 1) {
432         buf->full = 0;
433     }
434     
435         
436     *data = buf->buffer[next_tail];
437     buf->buffer[next_tail] = 0;
438     buf->tail = next_tail;
439     
440     if ( (buf == &(com->rx_buffer)) && (getNumber(&(com->rx_buffer)) == 0) ) {
441         com->lsr.dr = 0;
442     }
443     
444     if ((buf == &(com->tx_buffer)) && (getNumber(&(com->tx_buffer)) == 0)) {
445         com->lsr.thre = 1;
446         com->lsr.temt = 1;
447     }
448     
449     updateIRQ(vm, com);
450     
451     return 0;
452 }
453
454 static int write_data_port(struct guest_info * core, uint16_t port, 
455                            void * src, uint_t length, void * priv_data) {
456     struct serial_state * state = priv_data;
457     uint8_t * val = (uint8_t *)src;
458     struct serial_port * com_port = NULL;
459
460     PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
461     
462     if (length != 1) {
463         PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
464         return -1;
465     }
466
467     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
468         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
469         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
470         return -1;
471     }
472
473     com_port = get_com_from_port(state, port);
474
475     if (com_port == NULL) {
476         PrintError("UART:read from NOBODY\n");
477         return -1;
478     }
479     
480
481     // dlab is always checked first
482     if (com_port->lcr.dlab == 1) {
483         com_port->dll.data = *val;
484     }  else {
485         
486
487         /* JRL: Some buffering would probably be a good idea here.... */
488         if (com_port->ops) {
489             com_port->ops->output(val, 1, com_port->backend_data);
490         } else {
491             queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
492             updateIRQ(core->vm_info, com_port);
493         }
494     }
495     
496     return length;
497 }
498
499
500
501 static int read_data_port(struct guest_info * core, uint16_t port, 
502                           void * dst, uint_t length, void * priv_data) {
503     struct serial_state * state = priv_data;
504     uint8_t * val = (uint8_t *)dst;
505     struct serial_port * com_port = NULL;
506
507     PrintDebug("Read from Data Port 0x%x\n", port);
508     
509     if (length != 1) {
510         PrintError("Invalid length(%d) in write to 0x%x\n", length, port);
511         return -1;
512     }
513     
514     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
515         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
516         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
517         return -1;
518     }
519
520     com_port = get_com_from_port(state, port);
521
522     if (com_port == NULL) {
523         PrintError("UART:read from NOBODY\n");
524         return -1;
525     }
526     
527     if (com_port->lcr.dlab == 1) {
528         *val = com_port->dll.data;
529     } else {
530         dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val);
531     }    
532         
533     return length;
534 }
535
536
537
538 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
539
540     com->fcr.enable = value & 0x1;
541     
542     if (com->fcr.enable == 0x1) {
543         com->fcr.val = value;
544
545         com->fcr.enable = 1; // Do we need to set this??
546
547         //if rfres set, clear receive buffer.
548         if (com->fcr.rfres == 0x1) {
549             com->rx_buffer.head = 0;
550             com->rx_buffer.tail = 0;
551             com->rx_buffer.full = 0;
552             memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
553             com->fcr.rfres = 0;
554         }
555
556         //if xfres set, clear transmit buffer.
557         if (com->fcr.xfres == 0x1) {
558             com->tx_buffer.head = 0;
559             com->tx_buffer.tail = 0;
560             com->tx_buffer.full = 0;
561             memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
562             com->fcr.xfres = 0;
563         }
564     } else {
565         //clear both buffers.
566         com->tx_buffer.head = 0;
567         com->tx_buffer.tail = 0;
568         com->tx_buffer.full = 0;
569         com->rx_buffer.head = 0;
570         com->rx_buffer.tail = 0;
571         com->rx_buffer.full = 0;
572         
573         memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
574         memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
575     }
576     
577     return 1;
578 }
579
580
581
582
583
584 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src, 
585                            uint_t length, void * priv_data) {
586     struct serial_state * state = priv_data;
587     uint8_t val = *(uint8_t *)src;
588     struct serial_port * com_port = NULL;
589
590     PrintDebug("UART:Write to Control Port (val=%x)\n", val);
591     
592     if (length != 1) {
593         PrintError("UART:Invalid Write length to control port%d\n", port);
594         return -1;
595     }
596
597     com_port = get_com_from_port(state, port);
598
599     if (com_port == NULL) {
600         PrintError("Could not find serial port corresponding to IO port %d\n", port);
601         return -1;
602     }
603     
604     //always check dlab first
605     switch (port) {
606         case COM1_IRQ_ENABLE_PORT:
607         case COM2_IRQ_ENABLE_PORT:
608         case COM3_IRQ_ENABLE_PORT:
609         case COM4_IRQ_ENABLE_PORT: {
610             PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
611
612             if (com_port->lcr.dlab == 1) {
613                 com_port->dlm.data = val;
614             } else {
615                 com_port->ier.val = val;
616             }
617
618             break;
619         }           
620         case COM1_FIFO_CTRL_PORT:
621         case COM2_FIFO_CTRL_PORT:
622         case COM3_FIFO_CTRL_PORT:
623         case COM4_FIFO_CTRL_PORT: {
624             PrintDebug("UART:Write to FCR\n");
625
626             if (handle_fcr_write(com_port, val) == -1) {
627                 return -1;
628             }
629
630             break;
631         }
632         case COM1_LINE_CTRL_PORT:
633         case COM2_LINE_CTRL_PORT:
634         case COM3_LINE_CTRL_PORT:
635         case COM4_LINE_CTRL_PORT: {
636             PrintDebug("UART:Write to LCR\n");
637             com_port->lcr.val = val;
638             break;
639         }
640         case COM1_MODEM_CTRL_PORT:
641         case COM2_MODEM_CTRL_PORT:
642         case COM3_MODEM_CTRL_PORT:
643         case COM4_MODEM_CTRL_PORT: {
644             PrintDebug("UART:Write to MCR\n");
645             com_port->mcr.val = val;
646             break;
647         }
648         case COM1_SCRATCH_PORT:
649         case COM2_SCRATCH_PORT:
650         case COM3_SCRATCH_PORT:
651         case COM4_SCRATCH_PORT: {
652             PrintDebug("UART:Write to SCRATCH\n");
653             com_port->scr.data = val;
654             break;
655         }
656         default:
657             PrintError("UART:Write to NOBODY, ERROR\n");
658             return -1;
659     }
660     
661
662     return length;
663 }
664
665
666
667
668 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst, 
669                           uint_t length, void * priv_data) {
670     struct serial_state * state = priv_data;
671     uint8_t * val = (uint8_t *)dst;
672     struct serial_port * com_port = NULL;
673
674     PrintDebug("Read from Control Port\n");
675     
676     if (length != 1) {
677         PrintError("Invalid Read length to control port\n");
678         return -1;
679     }
680
681     com_port = get_com_from_port(state, port);
682
683     if (com_port == NULL) {
684         PrintError("Could not find serial port corresponding to IO port %d\n", port);
685         return -1;
686     }
687     
688     //always check dlab first
689     switch (port) {
690         case COM1_IRQ_ENABLE_PORT:
691         case COM2_IRQ_ENABLE_PORT:
692         case COM3_IRQ_ENABLE_PORT:
693         case COM4_IRQ_ENABLE_PORT: {
694             PrintDebug("UART:read from IER\n");
695
696             if (com_port->lcr.dlab == 1) {
697                 *val = com_port->dlm.data;
698             } else {
699                 *val = com_port->ier.val;
700             }
701             break;
702         }
703
704         case COM1_IIR_PORT:
705         case COM2_IIR_PORT:
706         case COM3_IIR_PORT:
707         case COM4_IIR_PORT:
708             PrintDebug("UART:read from IIR\n");
709             *val = com_port->iir.val;
710             break;
711
712         case COM1_LINE_CTRL_PORT:
713         case COM2_LINE_CTRL_PORT:
714         case COM3_LINE_CTRL_PORT:
715         case COM4_LINE_CTRL_PORT:
716             PrintDebug("UART:read from LCR\n");
717             *val = com_port->lcr.val;
718             break;
719
720         case COM1_MODEM_CTRL_PORT:
721         case COM2_MODEM_CTRL_PORT:
722         case COM3_MODEM_CTRL_PORT:
723         case COM4_MODEM_CTRL_PORT:
724             PrintDebug("UART:read from MCR\n");
725             *val = com_port->mcr.val;
726             break;
727
728         case COM1_SCRATCH_PORT:
729         case COM2_SCRATCH_PORT:
730         case COM3_SCRATCH_PORT:
731         case COM4_SCRATCH_PORT:
732             PrintDebug("UART:read from SCRATCH\n");
733             *val = com_port->scr.data;
734             break;
735
736         default:
737             PrintError("UART:read from NOBODY\n");
738             return -1;
739     }
740
741     return length;
742 }
743
744
745 static int write_status_port(struct guest_info * core, uint16_t port, void * src, 
746                              uint_t length, void * priv_data) {
747     struct serial_state * state = priv_data;
748     uint8_t val = *(uint8_t *)src;
749     struct serial_port * com_port = NULL;
750
751     PrintDebug("Write to Status Port (val=%x)\n", val);
752
753     if (length != 1) {
754         PrintError("Invalid Write length to status port %d\n", port);
755         return -1;
756     }
757
758     com_port = get_com_from_port(state, port);
759
760     if (com_port == NULL) {
761         PrintError("Could not find serial port corresponding to IO port %d\n", port);
762         return -1;
763     }
764
765     switch (port) {
766         case COM1_LINE_STATUS_PORT:
767         case COM2_LINE_STATUS_PORT:
768         case COM3_LINE_STATUS_PORT:
769         case COM4_LINE_STATUS_PORT:
770             PrintDebug("UART:write to LSR\n");
771             com_port->lsr.val = val;
772             break;
773
774         case COM1_MODEM_STATUS_PORT:
775         case COM2_MODEM_STATUS_PORT:
776         case COM3_MODEM_STATUS_PORT:
777         case COM4_MODEM_STATUS_PORT:
778             PrintDebug("UART:write to MSR\n");
779             com_port->msr.val = val;
780             break;
781
782         default:
783             PrintError("UART:write to NOBODY\n");
784             return -1;
785     }
786
787     return length;
788 }
789
790 static int read_status_port(struct guest_info * core, uint16_t port, void * dst, 
791                             uint_t length, void * priv_data) {
792     struct serial_state * state = priv_data;
793     uint8_t * val = (uint8_t *)dst;
794     struct serial_port * com_port = NULL;
795
796     PrintDebug("Read from Status Port 0x%x\n", port);
797
798     com_port = get_com_from_port(state, port);
799
800     if (com_port == NULL) {
801         PrintError("Could not find serial port corresponding to IO port %d\n", port);
802         return -1;
803     }
804
805     switch (port) {
806         case COM1_LINE_STATUS_PORT:
807         case COM2_LINE_STATUS_PORT:
808         case COM3_LINE_STATUS_PORT:
809         case COM4_LINE_STATUS_PORT:
810
811             if (length != 1) {
812                 PrintError("Invalid Read length to control port\n");
813                 return -1;
814             }
815
816             PrintDebug("UART:read from LSR\n");
817
818             *val = com_port->lsr.val;
819             com_port->lsr.oe = 0;     // Why do we clear this??
820
821             break;
822
823         case COM1_MODEM_STATUS_PORT:
824         case COM2_MODEM_STATUS_PORT:
825         case COM3_MODEM_STATUS_PORT:
826         case COM4_MODEM_STATUS_PORT:
827             PrintDebug("UART:read from COM4 MSR (length = %d)\n", length);
828
829             if (length > 2) {
830                 PrintError("Invalid Read length to MSR port\n");
831                 return -1;
832             }
833
834             if (length == 2) {
835                 /* Windows XP expects to be able to read this register and the next in one go */
836
837                 if (read_ctrl_port(core, port + 1, val + 1, 1, priv_data) < 0) {
838                     PrintError("Error reading control port for word size read of Status register\n");
839                     return -1;
840                 }
841             }
842
843             // always read low byte...
844             
845             *val = com_port->msr.val;
846             break;
847
848         default:
849             PrintError("UART:read from NOBODY (length = %d)\n", length);
850             return -1;
851     }
852
853     return length;
854 }
855
856 static int serial_free(struct serial_state * state) {
857
858     V3_Free(state);
859     return 0;
860 }
861
862
863
864
865 static struct v3_device_ops dev_ops = {
866     .free = (int (*)(void *))serial_free,
867 };
868
869
870
871 static int init_serial_port(struct serial_port * com) {
872
873     com->ier.val = IER_INIT_VAL;
874     com->iir.val = IIR_INIT_VAL;
875     com->fcr.val = FCR_INIT_VAL;
876     com->lcr.val = LCR_INIT_VAL;
877     com->mcr.val = MCR_INIT_VAL;
878     com->lsr.val = LSR_INIT_VAL;
879     com->msr.val = MSR_INIT_VAL;
880
881     com->dll.data =  DLL_INIT_VAL;
882     com->dlm.data =  DLM_INIT_VAL;
883     
884     com->tx_buffer.head = 0;
885     com->tx_buffer.tail = 0;
886     com->tx_buffer.full = 0;
887     memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
888
889     com->rx_buffer.head = 0;
890     com->rx_buffer.tail = 0;
891     com->rx_buffer.full = 0;
892     memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
893     
894     com->ops = NULL;
895     com->backend_data = NULL;
896
897     return 0;
898 }
899
900 static uint64_t serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
901     struct serial_port * com_port = (struct serial_port *)priv_data;
902     int i;
903
904     for(i = 0; i < len; i++){
905         queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
906     }
907
908     updateIRQ(vm, com_port);
909
910     return len;
911 }
912
913
914 static int connect_fn(struct v3_vm_info * vm, 
915                       void * frontend_data, 
916                       struct v3_dev_char_ops * ops, 
917                       v3_cfg_tree_t * cfg, 
918                       void * private_data, 
919                       void ** push_fn_arg) {
920
921     struct serial_state * serial = (struct serial_state *)frontend_data;
922     struct serial_port * com = NULL;
923     char * com_port = v3_cfg_val(cfg, "com_port");
924     int com_idx = 0;
925
926     if (com_port == NULL) {
927         PrintError("Invalid Serial frontend config: missing \"com_port\"\n");
928         return -1;
929     }
930     
931     com_idx = atoi(com_port) - 1;
932
933     if ((com_idx > 3) || (com_idx < 0)) {
934         PrintError("Invalid Com port (%s) \n", com_port);
935         return -1;
936     }
937
938     com = &(serial->coms[com_idx]);
939
940     com->ops = ops;
941     com->backend_data = private_data;
942
943     com->ops->input = serial_input;
944     *push_fn_arg = com;
945
946     return 0;
947 }
948
949 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
950     struct serial_state * state = NULL;
951     char * dev_id = v3_cfg_val(cfg, "ID");
952     int ret = 0;
953
954     state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
955     
956     if (state == NULL) {
957         PrintError("Could not allocate Serial Device\n");
958         return -1;
959     }
960     
961     memset(state, 0, sizeof(struct serial_state));
962
963     init_serial_port(&(state->coms[0]));
964     init_serial_port(&(state->coms[1]));
965     init_serial_port(&(state->coms[2]));
966     init_serial_port(&(state->coms[3]));
967
968     state->coms[0].irq_number = COM1_IRQ;
969     state->coms[1].irq_number = COM2_IRQ;
970     state->coms[2].irq_number = COM3_IRQ;
971     state->coms[3].irq_number = COM4_IRQ;
972
973
974     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
975
976     if (dev == NULL) {
977         PrintError("Could not attach device %s\n", dev_id);
978         V3_Free(state);
979         return -1;
980     }
981
982     PrintDebug("Serial device attached\n");
983
984     ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
985     ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
986     ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
987     ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
988     ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
989     ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
990     ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
991     ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
992
993     ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
994     ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
995     ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
996     ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
997     ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
998     ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
999     ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1000     ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1001
1002     ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
1003     ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1004     ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1005     ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1006     ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1007     ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1008     ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1009     ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1010
1011     ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
1012     ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1013     ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1014     ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1015     ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1016     ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1017     ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1018     ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1019
1020     if (ret != 0) {
1021         PrintError("Error hooking Serial IO ports\n");
1022         v3_remove_device(dev);
1023         return -1;
1024     }
1025
1026     PrintDebug("Serial ports hooked\n");
1027
1028
1029
1030     if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1031         PrintError("Could not register %s as frontend\n", dev_id);
1032         v3_remove_device(dev);
1033         return -1;
1034     }
1035
1036
1037     return 0;
1038 }
1039
1040
1041
1042
1043
1044 device_register("SERIAL", serial_init)