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.


Replaces PrintDebug with PrintError where appropriate. In addition, this patch allows...
[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 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         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         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->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         PrintError("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         PrintError("UART:read from NOBODY\n");
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         PrintError("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\n");
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\n");
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\n");
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\n");
652             com_port->scr.data = val;
653             break;
654         }
655         default:
656             PrintError("UART:Write to NOBODY, ERROR\n");
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         PrintError("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\n");
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_IIR_PORT:
704         case COM2_IIR_PORT:
705         case COM3_IIR_PORT:
706         case COM4_IIR_PORT:
707             PrintDebug("UART:read from IIR\n");
708             *val = com_port->iir.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\n");
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\n");
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\n");
732             *val = com_port->scr.data;
733             break;
734
735         default:
736             PrintError("UART:read from NOBODY\n");
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         PrintError("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\n");
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\n");
778             com_port->msr.val = val;
779             break;
780
781         default:
782             PrintError("UART:write to NOBODY\n");
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     com_port = get_com_from_port(state, port);
798
799     if (com_port == NULL) {
800         PrintError("Could not find serial port corresponding to IO port %d\n", port);
801         return -1;
802     }
803
804     switch (port) {
805         case COM1_LINE_STATUS_PORT:
806         case COM2_LINE_STATUS_PORT:
807         case COM3_LINE_STATUS_PORT:
808         case COM4_LINE_STATUS_PORT:
809
810             if (length != 1) {
811                 PrintError("Invalid Read length to control port\n");
812                 return -1;
813             }
814
815             PrintDebug("UART:read from LSR\n");
816
817             *val = com_port->lsr.val;
818             com_port->lsr.oe = 0;     // Why do we clear this??
819
820             break;
821
822         case COM1_MODEM_STATUS_PORT:
823         case COM2_MODEM_STATUS_PORT:
824         case COM3_MODEM_STATUS_PORT:
825         case COM4_MODEM_STATUS_PORT:
826             PrintDebug("UART:read from COM4 MSR (length = %d)\n", length);
827
828             if (length > 2) {
829                 PrintError("Invalid Read length to MSR port\n");
830                 return -1;
831             }
832
833             if (length == 2) {
834                 /* Windows XP expects to be able to read this register and the next in one go */
835
836                 if (read_ctrl_port(core, port + 1, val + 1, 1, priv_data) < 0) {
837                     PrintError("Error reading control port for word size read of Status register\n");
838                     return -1;
839                 }
840             }
841
842             // always read low byte...
843             
844             *val = com_port->msr.val;
845             break;
846
847         default:
848             PrintError("UART:read from NOBODY (length = %d)\n", length);
849             return -1;
850     }
851
852     return length;
853 }
854
855 static int serial_free(struct serial_state * state) {
856
857     V3_Free(state);
858     return 0;
859 }
860
861
862
863
864 static struct v3_device_ops dev_ops = {
865     .free = (int (*)(void *))serial_free,
866 };
867
868
869
870 static int init_serial_port(struct serial_port * com) {
871
872     com->ier.val = IER_INIT_VAL;
873     com->iir.val = IIR_INIT_VAL;
874     com->fcr.val = FCR_INIT_VAL;
875     com->lcr.val = LCR_INIT_VAL;
876     com->mcr.val = MCR_INIT_VAL;
877     com->lsr.val = LSR_INIT_VAL;
878     com->msr.val = MSR_INIT_VAL;
879
880     com->dll.data =  DLL_INIT_VAL;
881     com->dlm.data =  DLM_INIT_VAL;
882     
883     com->tx_buffer.head = 0;
884     com->tx_buffer.tail = 0;
885     com->tx_buffer.full = 0;
886     memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
887
888     com->rx_buffer.head = 0;
889     com->rx_buffer.tail = 0;
890     com->rx_buffer.full = 0;
891     memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
892     
893     com->ops = NULL;
894     com->backend_data = NULL;
895
896     return 0;
897 }
898
899 static int serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
900     struct serial_port * com_port = (struct serial_port *)priv_data;
901     int i;
902
903     for(i = 0; i < len; i++){
904         queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
905     }
906
907     return len;
908 }
909
910
911 static int connect_fn(struct v3_vm_info * vm, 
912                       void * frontend_data, 
913                       struct v3_dev_char_ops * ops, 
914                       v3_cfg_tree_t * cfg, 
915                       void * private_data, 
916                       void ** push_fn_arg) {
917
918     struct serial_state * serial = (struct serial_state *)frontend_data;
919     struct serial_port * com = NULL;
920     char * com_port = v3_cfg_val(cfg, "com_port");
921     int com_idx = 0;
922
923     if (com_port == NULL) {
924         PrintError("Invalid Serial frontend config: missing \"com_port\"\n");
925         return -1;
926     }
927     
928     com_idx = atoi(com_port) - 1;
929
930     if ((com_idx > 3) || (com_idx < 0)) {
931         PrintError("Invalid Com port (%s) \n", com_port);
932         return -1;
933     }
934
935     com = &(serial->coms[com_idx]);
936
937     com->ops = ops;
938     com->backend_data = private_data;
939
940     com->ops->push = serial_input;
941     *push_fn_arg = com;
942
943     return 0;
944 }
945
946 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
947     struct serial_state * state = NULL;
948     char * dev_id = v3_cfg_val(cfg, "ID");
949     int ret = 0;
950
951     state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
952     
953     if (state == NULL) {
954         PrintError("Could not allocate Serial Device\n");
955         return -1;
956     }
957     
958     memset(state, 0, sizeof(struct serial_state));
959
960     init_serial_port(&(state->coms[0]));
961     init_serial_port(&(state->coms[1]));
962     init_serial_port(&(state->coms[2]));
963     init_serial_port(&(state->coms[3]));
964
965     state->coms[0].irq_number = COM1_IRQ;
966     state->coms[1].irq_number = COM2_IRQ;
967     state->coms[2].irq_number = COM3_IRQ;
968     state->coms[3].irq_number = COM4_IRQ;
969
970
971     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
972
973     if (dev == NULL) {
974         PrintError("Could not attach device %s\n", dev_id);
975         V3_Free(state);
976         return -1;
977     }
978
979     PrintDebug("Serial device attached\n");
980
981     ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
982     ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
983     ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
984     ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
985     ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
986     ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
987     ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
988     ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
989
990     ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
991     ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
992     ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
993     ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
994     ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
995     ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
996     ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
997     ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
998
999     ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
1000     ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1001     ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1002     ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1003     ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1004     ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1005     ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1006     ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1007
1008     ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
1009     ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1010     ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1011     ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1012     ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1013     ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1014     ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1015     ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1016
1017     if (ret != 0) {
1018         PrintError("Error hooking Serial IO ports\n");
1019         v3_remove_device(dev);
1020         return -1;
1021     }
1022
1023     PrintDebug("Serial ports hooked\n");
1024
1025
1026
1027     if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1028         PrintError("Could not register %s as frontend\n", dev_id);
1029         v3_remove_device(dev);
1030         return -1;
1031     }
1032
1033
1034     return 0;
1035 }
1036
1037
1038
1039
1040
1041 device_register("SERIAL", serial_init)