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.


virtual console works with stream-serial implementation
[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  *             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/vmm_host_events.h>
30 #include <palacios/vm_guest.h>
31
32 #include <devices/serial.h>
33
34
35 #ifndef CONFIG_DEBUG_SERIAL
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40
41 #define COM1_DATA_PORT           0x3f8
42 #define COM1_IRQ_ENABLE_PORT     0x3f9
43 #define COM1_DIV_LATCH_LSB_PORT  0x3f8
44 #define COM1_DIV_LATCH_MSB_PORT  0x3f9
45 #define COM1_IIR_PORT            0x3fa
46 #define COM1_FIFO_CTRL_PORT      0x3fa
47 #define COM1_LINE_CTRL_PORT      0x3fb
48 #define COM1_MODEM_CTRL_PORT     0x3fc
49 #define COM1_LINE_STATUS_PORT    0x3fd
50 #define COM1_MODEM_STATUS_PORT   0x3fe
51 #define COM1_SCRATCH_PORT        0x3ff
52
53 #define COM2_DATA_PORT           0x2f8
54 #define COM2_IRQ_ENABLE_PORT     0x2f9
55 #define COM2_DIV_LATCH_LSB_PORT  0x2f8
56 #define COM2_DIV_LATCH_MSB_PORT  0x2f9
57 #define COM2_IIR_PORT            0x2fa
58 #define COM2_FIFO_CTRL_PORT      0x2fa
59 #define COM2_LINE_CTRL_PORT      0x2fb
60 #define COM2_MODEM_CTRL_PORT     0x2fc
61 #define COM2_LINE_STATUS_PORT    0x2fd
62 #define COM2_MODEM_STATUS_PORT   0x2fe
63 #define COM2_SCRATCH_PORT        0x2ff
64
65 #define COM3_DATA_PORT           0x3e8
66 #define COM3_IRQ_ENABLE_PORT     0x3e9
67 #define COM3_DIV_LATCH_LSB_PORT  0x3e8
68 #define COM3_DIV_LATCH_MSB_PORT  0x3e9
69 #define COM3_IIR_PORT            0x3ea
70 #define COM3_FIFO_CTRL_PORT      0x3ea
71 #define COM3_LINE_CTRL_PORT      0x3eb
72 #define COM3_MODEM_CTRL_PORT     0x3ec
73 #define COM3_LINE_STATUS_PORT    0x3ed
74 #define COM3_MODEM_STATUS_PORT   0x3ee
75 #define COM3_SCRATCH_PORT        0x3ef
76
77 #define COM4_DATA_PORT           0x2e8
78 #define COM4_IRQ_ENABLE_PORT     0x2e9
79 #define COM4_DIV_LATCH_LSB_PORT  0x2e8
80 #define COM4_DIV_LATCH_MSB_PORT  0x2e9
81 #define COM4_IIR_PORT            0x2ea
82 #define COM4_FIFO_CTRL_PORT      0x2ea
83 #define COM4_LINE_CTRL_PORT      0x2eb
84 #define COM4_MODEM_CTRL_PORT     0x2ec
85 #define COM4_LINE_STATUS_PORT    0x2ed
86 #define COM4_MODEM_STATUS_PORT   0x2ee
87 #define COM4_SCRATCH_PORT        0x2ef
88
89
90 // Interrupt IDs (in priority order, highest is first)
91 #define STATUS_IRQ_LSR_OE_SET   0x3
92 #define STATUS_IRQ_LSR_PE_SET   0x3
93 #define STATUS_IRQ_LSR_FE_SET   0x3
94 #define STATUS_IRQ_LSR_BI_SET   0x3
95 #define RX_IRQ_DR               0x2
96 #define RX_IRQ_TRIGGER_LEVEL    0x2
97 #define FIFO_IRQ                0x6
98 #define TX_IRQ_THRE             0x1
99 #define MODEL_IRQ_DELTA_SET     0x0
100
101 //COMs IRQ ID
102 #define COM1_IRQ  0x4
103 #define COM2_IRQ  0x3
104 #define COM3_IRQ  0x4
105 #define COM4_IRQ  0x3
106
107 #define RX_BUFFER 0x1
108 #define TX_BUFFER 0x2
109
110 //initial value for registers
111
112 #define  IER_INIT_VAL 0x3
113 //receive data available interrupt and THRE interrupt are enabled
114 #define  IIR_INIT_VAL 0x1
115 //No Pending Interrupt bit is set.
116 #define  FCR_INIT_VAL 0xc0
117 //fifo control register is set to 0
118 #define  LCR_INIT_VAL 0x3
119 #define  MCR_INIT_VAL 0x0
120 #define  LSR_INIT_VAL 0x60
121 #define  MSR_INIT_VAL 0x0
122 #define  DLL_INIT_VAL 0x1
123 #define  DLM_INIT_VAL 0x0
124
125
126
127 //receiver buffer register
128 struct rbr_register {
129     uint8_t data;
130 };
131
132 // transmitter holding register
133 struct thr_register {
134     uint8_t data;
135 };
136
137 //interrupt enable register
138 struct ier_register {
139     union {
140         uint8_t val;
141         struct {
142             uint8_t erbfi   : 1;   // Enable Receiver Buffer full interrupt
143             uint8_t etbei   : 1;  // Enable Transmit buffer empty interrupt
144             uint8_t elsi    : 1;  // Enable Line Status Interrupt
145             uint8_t edssi   : 1;  // Enable Delta Status signals interrupt
146             uint8_t rsvd    : 4;   // MBZ
147         } __attribute__((packed));
148     } __attribute__((packed));
149 } __attribute__((packed));
150
151
152 //interrupt identification register
153 struct iir_register {
154     union {
155         uint8_t val;
156         struct {
157             uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
158             uint8_t iid     : 3; // Interrupt Identification
159             uint8_t rsvd    : 2; // MBZ
160             uint8_t fifo_en : 2; // FIFO enable
161         } __attribute__((packed));
162     } __attribute__((packed));
163 } __attribute__((packed));
164
165 //FIFO control register
166 struct fcr_register {
167     union {
168         uint8_t val;
169         struct {
170             uint8_t enable  : 1; // enable fifo
171             uint8_t rfres   : 1; // RX FIFO reset
172             uint8_t xfres   : 1; // TX FIFO reset
173             uint8_t dma_sel : 1; // DMA mode select
174             uint8_t rsvd    : 2; // MBZ
175             uint8_t rx_trigger: 2; // RX FIFO trigger level select
176         } __attribute__((packed));
177     } __attribute__((packed));
178 } __attribute__((packed));
179
180
181 //line control register
182 struct lcr_register {
183     union {
184         uint8_t val;
185         struct {
186             uint8_t word_len       : 2;  // word length select
187             uint8_t stop_bits      : 1;  // Stop Bit select
188             uint8_t parity_enable  : 1;  // Enable parity
189             uint8_t even_sel       : 1;  // Even Parity Select
190             uint8_t stick_parity   : 1;  // Stick Parity Select
191             uint8_t sbr            : 1;  // Set Break
192             uint8_t dlab           : 1;  // Divisor latch access bit
193         } __attribute__((packed));
194     } __attribute__((packed));
195 } __attribute__((packed));
196
197
198 //modem control register
199 struct mcr_register {
200     union {
201         uint8_t val;
202         struct {
203             uint8_t dtr      : 1;
204             uint8_t rts      : 1;
205             uint8_t out1     : 1;
206             uint8_t out2     : 1;
207             uint8_t loop     : 1;  // loopback mode
208             uint8_t rsvd     : 3;  // MBZ
209         } __attribute__((packed));
210     } __attribute__((packed));
211 } __attribute__((packed));
212
213
214 //line status register
215 struct lsr_register {
216     union {
217         uint8_t val;
218         struct {
219             uint8_t dr      : 1;  // data ready
220             uint8_t oe       : 1;  // Overrun error
221             uint8_t pe       : 1;  // Parity Error
222             uint8_t fe       : 1;  // Framing Error
223             uint8_t brk      : 1;  // broken line detected
224             uint8_t thre     : 1;  // Transmitter holding register empty
225             uint8_t temt     : 1;  // Transmitter Empty
226             uint8_t fifo_err : 1;  // at least one error is pending in the RX FIFO chain
227         } __attribute__((packed));
228     } __attribute__((packed));
229 } __attribute__((packed));
230
231
232 struct msr_register {
233     union {
234         uint8_t val;
235         struct {
236             uint8_t dcts     : 1;  // Delta Clear To Send
237             uint8_t ddsr     : 1;  // Delta Data Set Ready
238             uint8_t teri     : 1;  // Trailing Edge Ring Indicator
239             uint8_t ddcd     : 1;  // Delta Data Carrier Detect
240             uint8_t cts      : 1;  // Clear to Send
241             uint8_t dsr      : 1;  // Data Set Ready
242             uint8_t ri       : 1;  // Ring Indicator
243             uint8_t dcd      : 1;  // Data Carrier Detect
244         } __attribute__((packed));
245     } __attribute__((packed));
246 } __attribute__((packed));
247
248 //scratch register
249 struct scr_register {
250     uint8_t data;
251 };
252
253 //divisor latch LSB
254 struct dll_register {
255     uint8_t data;
256 };
257
258 //divisor latch MSB
259 struct dlm_register {
260     uint8_t data;
261 };
262 #define SERIAL_BUF_LEN 16
263
264 struct serial_buffer {
265     int head; // most recent data
266     int tail; // oldest char
267     int full;
268     uint8_t buffer[SERIAL_BUF_LEN];
269 };
270
271 struct serial_port {
272     struct rbr_register     rbr;
273     struct thr_register     thr;
274     struct ier_register     ier;
275     struct iir_register     iir;
276     struct fcr_register     fcr;
277     struct lcr_register     lcr;
278     struct mcr_register     mcr;
279     struct lsr_register     lsr;
280     struct msr_register     msr;
281     struct scr_register     scr;
282     struct dll_register     dll;
283     struct dlm_register     dlm;
284     
285     
286     struct serial_buffer tx_buffer;
287     struct serial_buffer rx_buffer;
288     uint_t irq_number;
289
290     struct v3_stream_ops *stream_ops;
291     void                 *backend_data;
292
293     struct vm_device * vm_dev;
294 };
295
296
297 struct serial_state {
298     struct serial_port com1;
299     struct serial_port com2;
300     struct serial_port com3;
301     struct serial_port com4;
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 static int write_data_port(struct guest_info * core, uint16_t port, 
459                            void * src, uint_t length, struct vm_device * dev) {
460     struct serial_state * state = (struct serial_state *)dev->private_data;
461     uint8_t * val = (uint8_t *)src;
462     struct serial_port * com_port = NULL;
463
464     PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *val);
465     
466     if (length != 1) {
467         PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
468         return -1;
469     }
470
471     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
472         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
473         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
474         return -1;
475     }
476
477     com_port = get_com_from_port(state, port);
478
479     if (com_port == NULL) {
480         PrintDebug("UART:read from NOBODY");
481         return -1;
482     }
483     
484
485     // dlab is always checked first
486     if (com_port->lcr.dlab == 1) {
487         com_port->dll.data = *val;
488     }  else {
489         queue_data(&(com_port->tx_buffer), *val, com_port, dev);
490         if (com_port->stream_ops) { 
491             uint8_t c;
492             dequeue_data(&(com_port->tx_buffer), &c, com_port, dev);
493             com_port->stream_ops->write(&c,1,com_port->backend_data);
494         }
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_input(char *buf, uint_t len, void *front_data){
922     struct serial_port *com_port = (struct serial_port *)front_data;
923     int i;
924
925     for(i=0; i<len; i++){
926         queue_data(&(com_port->rx_buffer), buf[i], com_port, com_port->vm_dev);
927     }
928
929     return len;
930 }
931
932 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
933     struct serial_state * state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
934     char * dev_id = v3_cfg_val(cfg, "ID");
935
936     init_serial_port(&(state->com1));
937     init_serial_port(&(state->com2));
938     init_serial_port(&(state->com3));
939     init_serial_port(&(state->com4));
940
941     state->com1.irq_number = COM1_IRQ;
942     state->com2.irq_number = COM2_IRQ;
943     state->com3.irq_number = COM3_IRQ;
944     state->com4.irq_number = COM4_IRQ;
945
946     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
947     if (v3_attach_device(vm, dev) == -1) {
948         PrintError("Could not attach device %s\n", dev_id);
949         return -1;
950     }
951
952     state->com1.vm_dev = dev;
953     state->com2.vm_dev = dev;
954     state->com3.vm_dev = dev;
955     state->com4.vm_dev = dev;   
956
957     PrintDebug("Serial device attached\n");
958
959     v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
960     v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
961     v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
962     v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
963     v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
964     v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
965     v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
966     v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
967
968     v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
969     v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
970     v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
971     v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
972     v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
973     v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
974     v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
975     v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
976
977     v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
978     v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
979     v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
980     v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
981     v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
982     v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
983     v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
984     v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
985
986     v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
987     v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
988     v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
989     v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
990     v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
991     v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
992     v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
993     v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
994
995     PrintDebug("Serial ports hooked\n");
996
997     return 0;
998 }
999
1000 int v3_stream_register_serial(struct vm_device * serial_dev, struct v3_stream_ops * ops, void * private_data)
1001 {
1002     struct serial_state *state = (struct serial_state *)(serial_dev->private_data);
1003
1004     state->com1.stream_ops = ops;
1005     state->com1.backend_data = private_data;
1006     /* bind to other ports here */
1007
1008     ops->input = serial_input;
1009     ops->front_data = &(state->com1);
1010
1011     return 0;
1012 }
1013
1014
1015 device_register("SERIAL", serial_init)