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.


deallocation of devices
[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/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
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)");
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)");
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         return 0;
397     }
398     
399     buf->buffer[next_loc] = data;
400     buf->head = next_loc;
401     
402     if (buf->head == buf->tail) {
403         buf->full = 1;
404     }
405     
406     if (buf == &(com->rx_buffer)) {
407         com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
408     }
409     
410     if (buf == &(com->tx_buffer)) {
411         com->lsr.thre = 0; //reset thre and temt bits.
412         com->lsr.temt = 0;
413     }
414     
415     updateIRQ(vm, com);
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         PrintDebug("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         PrintDebug("UART:read from NOBODY");
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->write(val, 1, com_port->backend_data);
490         } else {
491             queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
492         }
493     }
494     
495     return length;
496 }
497
498
499
500 static int read_data_port(struct guest_info * core, uint16_t port, 
501                           void * dst, uint_t length, void * priv_data) {
502     struct serial_state * state = priv_data;
503     uint8_t * val = (uint8_t *)dst;
504     struct serial_port * com_port = NULL;
505
506     PrintDebug("Read from Data Port 0x%x\n", port);
507     
508     if (length != 1) {
509         PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
510         return -1;
511     }
512     
513     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
514         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
515         PrintError("Serial Read data port for illegal port Number (%d)\n", port);
516         return -1;
517     }
518
519     com_port = get_com_from_port(state, port);
520
521     if (com_port == NULL) {
522         PrintDebug("UART:read from NOBODY");
523         return -1;
524     }
525     
526     if (com_port->lcr.dlab == 1) {
527         *val = com_port->dll.data;
528     } else {
529         dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val);
530     }    
531         
532     return length;
533 }
534
535
536
537 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
538
539     com->fcr.enable = value & 0x1;
540     
541     if (com->fcr.enable == 0x1) {
542         com->fcr.val = value;
543
544         com->fcr.enable = 1; // Do we need to set this??
545
546         //if rfres set, clear receive buffer.
547         if (com->fcr.rfres == 0x1) {
548             com->rx_buffer.head = 0;
549             com->rx_buffer.tail = 0;
550             com->rx_buffer.full = 0;
551             memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
552             com->fcr.rfres = 0;
553         }
554
555         //if xfres set, clear transmit buffer.
556         if (com->fcr.xfres == 0x1) {
557             com->tx_buffer.head = 0;
558             com->tx_buffer.tail = 0;
559             com->tx_buffer.full = 0;
560             memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
561             com->fcr.xfres = 0;
562         }
563     } else {
564         //clear both buffers.
565         com->tx_buffer.head = 0;
566         com->tx_buffer.tail = 0;
567         com->tx_buffer.full = 0;
568         com->rx_buffer.head = 0;
569         com->rx_buffer.tail = 0;
570         com->rx_buffer.full = 0;
571         
572         memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
573         memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
574     }
575     
576     return 1;
577 }
578
579
580
581
582
583 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src, 
584                            uint_t length, void * priv_data) {
585     struct serial_state * state = priv_data;
586     uint8_t val = *(uint8_t *)src;
587     struct serial_port * com_port = NULL;
588
589     PrintDebug("UART:Write to Control Port (val=%x)\n", val);
590     
591     if (length != 1) {
592         PrintDebug("UART:Invalid Write length to control port%d\n", port);
593         return -1;
594     }
595
596     com_port = get_com_from_port(state, port);
597
598     if (com_port == NULL) {
599         PrintError("Could not find serial port corresponding to IO port %d\n", port);
600         return -1;
601     }
602     
603     //always check dlab first
604     switch (port) {
605         case COM1_IRQ_ENABLE_PORT:
606         case COM2_IRQ_ENABLE_PORT:
607         case COM3_IRQ_ENABLE_PORT:
608         case COM4_IRQ_ENABLE_PORT: {
609             PrintDebug("UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
610
611             if (com_port->lcr.dlab == 1) {
612                 com_port->dlm.data = val;
613             } else {
614                 com_port->ier.val = val;
615             }
616
617             break;
618         }           
619         case COM1_FIFO_CTRL_PORT:
620         case COM2_FIFO_CTRL_PORT:
621         case COM3_FIFO_CTRL_PORT:
622         case COM4_FIFO_CTRL_PORT: {
623             PrintDebug("UART:Write to FCR");
624
625             if (handle_fcr_write(com_port, val) == -1) {
626                 return -1;
627             }
628
629             break;
630         }
631         case COM1_LINE_CTRL_PORT:
632         case COM2_LINE_CTRL_PORT:
633         case COM3_LINE_CTRL_PORT:
634         case COM4_LINE_CTRL_PORT: {
635             PrintDebug("UART:Write to LCR");
636             com_port->lcr.val = val;
637             break;
638         }
639         case COM1_MODEM_CTRL_PORT:
640         case COM2_MODEM_CTRL_PORT:
641         case COM3_MODEM_CTRL_PORT:
642         case COM4_MODEM_CTRL_PORT: {
643             PrintDebug("UART:Write to MCR");
644             com_port->mcr.val = val;
645             break;
646         }
647         case COM1_SCRATCH_PORT:
648         case COM2_SCRATCH_PORT:
649         case COM3_SCRATCH_PORT:
650         case COM4_SCRATCH_PORT: {
651             PrintDebug("UART:Write to SCRATCH");
652             com_port->scr.data = val;
653             break;
654         }
655         default:
656             PrintDebug("UART:Write to NOBODY, ERROR");
657             return -1;
658     }
659     
660
661     return length;
662 }
663
664
665
666
667 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst, 
668                           uint_t length, void * priv_data) {
669     struct serial_state * state = priv_data;
670     uint8_t * val = (uint8_t *)dst;
671     struct serial_port * com_port = NULL;
672
673     PrintDebug("Read from Control Port\n");
674     
675     if (length != 1) {
676         PrintDebug("Invalid Read length to control port\n");
677         return -1;
678     }
679
680     com_port = get_com_from_port(state, port);
681
682     if (com_port == NULL) {
683         PrintError("Could not find serial port corresponding to IO port %d\n", port);
684         return -1;
685     }
686     
687     //always check dlab first
688     switch (port) {
689         case COM1_IRQ_ENABLE_PORT:
690         case COM2_IRQ_ENABLE_PORT:
691         case COM3_IRQ_ENABLE_PORT:
692         case COM4_IRQ_ENABLE_PORT: {
693             PrintDebug("UART:read from IER");
694
695             if (com_port->lcr.dlab == 1) {
696                 *val = com_port->dlm.data;
697             } else {
698                 *val = com_port->ier.val;
699             }
700             break;
701         }
702
703         case COM1_FIFO_CTRL_PORT:
704         case COM2_FIFO_CTRL_PORT:
705         case COM3_FIFO_CTRL_PORT:
706         case COM4_FIFO_CTRL_PORT:
707             PrintDebug("UART:read from FCR");
708             *val = com_port->fcr.val;
709             break;
710
711         case COM1_LINE_CTRL_PORT:
712         case COM2_LINE_CTRL_PORT:
713         case COM3_LINE_CTRL_PORT:
714         case COM4_LINE_CTRL_PORT:
715             PrintDebug("UART:read from LCR");
716             *val = com_port->lcr.val;
717             break;
718
719         case COM1_MODEM_CTRL_PORT:
720         case COM2_MODEM_CTRL_PORT:
721         case COM3_MODEM_CTRL_PORT:
722         case COM4_MODEM_CTRL_PORT:
723             PrintDebug("UART:read from MCR");
724             *val = com_port->mcr.val;
725             break;
726
727         case COM1_SCRATCH_PORT:
728         case COM2_SCRATCH_PORT:
729         case COM3_SCRATCH_PORT:
730         case COM4_SCRATCH_PORT:
731             PrintDebug("UART:read from SCRATCH");
732             *val = com_port->scr.data;
733             break;
734
735         default:
736             PrintDebug("UART:read from NOBODY");
737             return -1;
738     }
739
740     return length;
741 }
742
743
744 static int write_status_port(struct guest_info * core, uint16_t port, void * src, 
745                              uint_t length, void * priv_data) {
746     struct serial_state * state = priv_data;
747     uint8_t val = *(uint8_t *)src;
748     struct serial_port * com_port = NULL;
749
750     PrintDebug("Write to Status Port (val=%x)\n", val);
751
752     if (length != 1) {
753         PrintDebug("Invalid Write length to status port %d\n", port);
754         return -1;
755     }
756
757     com_port = get_com_from_port(state, port);
758
759     if (com_port == NULL) {
760         PrintError("Could not find serial port corresponding to IO port %d\n", port);
761         return -1;
762     }
763
764     switch (port) {
765         case COM1_LINE_STATUS_PORT:
766         case COM2_LINE_STATUS_PORT:
767         case COM3_LINE_STATUS_PORT:
768         case COM4_LINE_STATUS_PORT:
769             PrintDebug("UART:write to LSR");
770             com_port->lsr.val = val;
771             break;
772
773         case COM1_MODEM_STATUS_PORT:
774         case COM2_MODEM_STATUS_PORT:
775         case COM3_MODEM_STATUS_PORT:
776         case COM4_MODEM_STATUS_PORT:
777             PrintDebug("UART:write to MSR");
778             com_port->msr.val = val;
779             break;
780
781         default:
782             PrintDebug("UART:write to NOBODY");
783             return -1;
784     }
785
786     return length;
787 }
788
789 static int read_status_port(struct guest_info * core, uint16_t port, void * dst, 
790                             uint_t length, void * priv_data) {
791     struct serial_state * state = priv_data;
792     uint8_t * val = (uint8_t *)dst;
793     struct serial_port * com_port = NULL;
794
795     PrintDebug("Read from Status Port 0x%x\n", port);
796
797     if (length != 1) {
798         PrintDebug("Invalid Read length to control port\n");
799         return -1;
800     }
801
802     com_port = get_com_from_port(state, port);
803
804     if (com_port == NULL) {
805         PrintError("Could not find serial port corresponding to IO port %d\n", port);
806         return -1;
807     }
808
809     switch (port) {
810         case COM1_LINE_STATUS_PORT:
811         case COM2_LINE_STATUS_PORT:
812         case COM3_LINE_STATUS_PORT:
813         case COM4_LINE_STATUS_PORT:
814             PrintDebug("UART:read from LSR");
815
816             *val = com_port->lsr.val;
817             com_port->lsr.oe = 0;     // Why do we clear this??
818
819             break;
820
821         case COM1_MODEM_STATUS_PORT:
822         case COM2_MODEM_STATUS_PORT:
823         case COM3_MODEM_STATUS_PORT:
824         case COM4_MODEM_STATUS_PORT:
825             PrintDebug("UART:read from COM4 MSR");
826             *val = com_port->msr.val;
827             break;
828
829         default:
830             PrintDebug("UART:read from NOBODY");
831             return -1;
832     }
833
834     return length;
835 }
836
837 static int serial_free(struct serial_state * state) {
838
839     V3_Free(state);
840     return 0;
841 }
842
843
844
845
846 static struct v3_device_ops dev_ops = {
847     .free = (int (*)(void *))serial_free,
848 };
849
850
851
852 static int init_serial_port(struct serial_port * com) {
853
854     com->ier.val = IER_INIT_VAL;
855     com->iir.val = IIR_INIT_VAL;
856     com->fcr.val = FCR_INIT_VAL;
857     com->lcr.val = LCR_INIT_VAL;
858     com->mcr.val = MCR_INIT_VAL;
859     com->lsr.val = LSR_INIT_VAL;
860     com->msr.val = MSR_INIT_VAL;
861
862     com->dll.data =  DLL_INIT_VAL;
863     com->dlm.data =  DLM_INIT_VAL;
864     
865     com->tx_buffer.head = 0;
866     com->tx_buffer.tail = 0;
867     com->tx_buffer.full = 0;
868     memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
869
870     com->rx_buffer.head = 0;
871     com->rx_buffer.tail = 0;
872     com->rx_buffer.full = 0;
873     memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
874     
875     com->ops = NULL;
876     com->backend_data = NULL;
877
878     return 0;
879 }
880
881 static int serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
882     struct serial_port * com_port = (struct serial_port *)priv_data;
883     int i;
884
885     for(i = 0; i < len; i++){
886         queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
887     }
888
889     return len;
890 }
891
892
893 static int connect_fn(struct v3_vm_info * vm, 
894                       void * frontend_data, 
895                       struct v3_dev_char_ops * ops, 
896                       v3_cfg_tree_t * cfg, 
897                       void * private_data, 
898                       void ** push_fn_arg) {
899
900     struct serial_state * serial = (struct serial_state *)frontend_data;
901     struct serial_port * com = NULL;
902     char * com_port = v3_cfg_val(cfg, "com_port");
903     int com_idx = 0;
904
905     if (com_port == NULL) {
906         PrintError("Invalid Serial frontend config: missing \"com_port\"\n");
907         return -1;
908     }
909     
910     com_idx = atoi(com_port) - 1;
911
912     if ((com_idx > 3) || (com_idx < 0)) {
913         PrintError("Invalid Com port (%s) \n", com_port);
914         return -1;
915     }
916
917     com = &(serial->coms[com_idx]);
918
919     com->ops = ops;
920     com->backend_data = private_data;
921
922     com->ops->push = serial_input;
923     *push_fn_arg = com;
924
925     return 0;
926 }
927
928 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
929     struct serial_state * state = NULL;
930     char * dev_id = v3_cfg_val(cfg, "ID");
931     int ret = 0;
932
933     state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
934     
935     if (state == NULL) {
936         PrintError("Could not allocate Serial Device\n");
937         return -1;
938     }
939     
940     memset(state, 0, sizeof(struct serial_state));
941
942     init_serial_port(&(state->coms[0]));
943     init_serial_port(&(state->coms[1]));
944     init_serial_port(&(state->coms[2]));
945     init_serial_port(&(state->coms[3]));
946
947     state->coms[0].irq_number = COM1_IRQ;
948     state->coms[1].irq_number = COM2_IRQ;
949     state->coms[2].irq_number = COM3_IRQ;
950     state->coms[3].irq_number = COM4_IRQ;
951
952
953     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
954
955     if (dev == NULL) {
956         PrintError("Could not attach device %s\n", dev_id);
957         V3_Free(state);
958         return -1;
959     }
960
961     PrintDebug("Serial device attached\n");
962
963     ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
964     ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
965     ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
966     ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
967     ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
968     ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
969     ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
970     ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
971
972     ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
973     ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
974     ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
975     ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
976     ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
977     ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
978     ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
979     ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
980
981     ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
982     ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
983     ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
984     ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
985     ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
986     ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
987     ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
988     ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
989
990     ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
991     ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
992     ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
993     ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
994     ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
995     ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
996     ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
997     ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
998
999     if (ret != 0) {
1000         PrintError("Error hooking Serial IO ports\n");
1001         v3_remove_device(dev);
1002         return -1;
1003     }
1004
1005     PrintDebug("Serial ports hooked\n");
1006
1007
1008
1009     if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1010         PrintError("Could not register %s as frontend\n", dev_id);
1011         v3_remove_device(dev);
1012         return -1;
1013     }
1014
1015
1016     return 0;
1017 }
1018
1019
1020
1021
1022
1023 device_register("SERIAL", serial_init)