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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[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 V3_CONFIG_DEBUG_SERIAL
35 #undef PrintDebug
36 #define PrintDebug(fmt, args...)
37 #endif
38
39
40 #define COM1_DATA_PORT           0x3f8
41 #define COM1_IRQ_ENABLE_PORT     0x3f9
42 #define COM1_DIV_LATCH_LSB_PORT  0x3f8
43 #define COM1_DIV_LATCH_MSB_PORT  0x3f9
44 #define COM1_IIR_PORT            0x3fa
45 #define COM1_FIFO_CTRL_PORT      0x3fa
46 #define COM1_LINE_CTRL_PORT      0x3fb
47 #define COM1_MODEM_CTRL_PORT     0x3fc
48 #define COM1_LINE_STATUS_PORT    0x3fd
49 #define COM1_MODEM_STATUS_PORT   0x3fe
50 #define COM1_SCRATCH_PORT        0x3ff
51
52 #define COM2_DATA_PORT           0x2f8
53 #define COM2_IRQ_ENABLE_PORT     0x2f9
54 #define COM2_DIV_LATCH_LSB_PORT  0x2f8
55 #define COM2_DIV_LATCH_MSB_PORT  0x2f9
56 #define COM2_IIR_PORT            0x2fa
57 #define COM2_FIFO_CTRL_PORT      0x2fa
58 #define COM2_LINE_CTRL_PORT      0x2fb
59 #define COM2_MODEM_CTRL_PORT     0x2fc
60 #define COM2_LINE_STATUS_PORT    0x2fd
61 #define COM2_MODEM_STATUS_PORT   0x2fe
62 #define COM2_SCRATCH_PORT        0x2ff
63
64 #define COM3_DATA_PORT           0x3e8
65 #define COM3_IRQ_ENABLE_PORT     0x3e9
66 #define COM3_DIV_LATCH_LSB_PORT  0x3e8
67 #define COM3_DIV_LATCH_MSB_PORT  0x3e9
68 #define COM3_IIR_PORT            0x3ea
69 #define COM3_FIFO_CTRL_PORT      0x3ea
70 #define COM3_LINE_CTRL_PORT      0x3eb
71 #define COM3_MODEM_CTRL_PORT     0x3ec
72 #define COM3_LINE_STATUS_PORT    0x3ed
73 #define COM3_MODEM_STATUS_PORT   0x3ee
74 #define COM3_SCRATCH_PORT        0x3ef
75
76 #define COM4_DATA_PORT           0x2e8
77 #define COM4_IRQ_ENABLE_PORT     0x2e9
78 #define COM4_DIV_LATCH_LSB_PORT  0x2e8
79 #define COM4_DIV_LATCH_MSB_PORT  0x2e9
80 #define COM4_IIR_PORT            0x2ea
81 #define COM4_FIFO_CTRL_PORT      0x2ea
82 #define COM4_LINE_CTRL_PORT      0x2eb
83 #define COM4_MODEM_CTRL_PORT     0x2ec
84 #define COM4_LINE_STATUS_PORT    0x2ed
85 #define COM4_MODEM_STATUS_PORT   0x2ee
86 #define COM4_SCRATCH_PORT        0x2ef
87
88
89 // Interrupt IDs (in priority order, highest is first)
90 #define STATUS_IRQ_LSR_OE_SET   0x3
91 #define STATUS_IRQ_LSR_PE_SET   0x3
92 #define STATUS_IRQ_LSR_FE_SET   0x3
93 #define STATUS_IRQ_LSR_BI_SET   0x3
94 #define RX_IRQ_DR               0x2
95 #define RX_IRQ_TRIGGER_LEVEL    0x2
96 #define FIFO_IRQ                0x6
97 #define TX_IRQ_THRE             0x1
98 #define MODEL_IRQ_DELTA_SET     0x0
99
100 //COMs IRQ ID
101 #define COM1_IRQ  0x4
102 #define COM2_IRQ  0x3
103 #define COM3_IRQ  0x4
104 #define COM4_IRQ  0x3
105
106 #define RX_BUFFER 0x1
107 #define TX_BUFFER 0x2
108
109 //initial value for registers
110
111 #define  IER_INIT_VAL 0x3
112 //receive data available interrupt and THRE interrupt are enabled
113 #define  IIR_INIT_VAL 0x1
114 //No Pending Interrupt bit is set.
115 #define  FCR_INIT_VAL 0xc0
116 //fifo control register is set to 0
117 #define  LCR_INIT_VAL 0x3
118 #define  MCR_INIT_VAL 0x0
119 #define  LSR_INIT_VAL 0x60
120 #define  MSR_INIT_VAL 0x0
121 #define  DLL_INIT_VAL 0x1
122 #define  DLM_INIT_VAL 0x0
123
124
125
126 //receiver buffer register
127 struct rbr_register {
128     uint8_t data;
129 };
130
131 // transmitter holding register
132 struct thr_register {
133     uint8_t data;
134 };
135
136 //interrupt enable register
137 struct ier_register {
138     union {
139         uint8_t val;
140         struct {
141             uint8_t erbfi   : 1;   // Enable Receiver Buffer full interrupt
142             uint8_t etbei   : 1;  // Enable Transmit buffer empty interrupt
143             uint8_t elsi    : 1;  // Enable Line Status Interrupt
144             uint8_t edssi   : 1;  // Enable Delta Status signals interrupt
145             uint8_t rsvd    : 4;   // MBZ
146         } __attribute__((packed));
147     } __attribute__((packed));
148 } __attribute__((packed));
149
150
151 //interrupt identification register
152 struct iir_register {
153     union {
154         uint8_t val;
155         struct {
156             uint8_t pending : 1; // Interrupt pending (0=interrupt pending)
157             uint8_t iid     : 3; // Interrupt Identification
158             uint8_t rsvd    : 2; // MBZ
159             uint8_t fifo_en : 2; // FIFO enable
160         } __attribute__((packed));
161     } __attribute__((packed));
162 } __attribute__((packed));
163
164 //FIFO control register
165 struct fcr_register {
166     union {
167         uint8_t val;
168         struct {
169             uint8_t enable  : 1; // enable fifo
170             uint8_t rfres   : 1; // RX FIFO reset
171             uint8_t xfres   : 1; // TX FIFO reset
172             uint8_t dma_sel : 1; // DMA mode select
173             uint8_t rsvd    : 2; // MBZ
174             uint8_t rx_trigger: 2; // RX FIFO trigger level select
175         } __attribute__((packed));
176     } __attribute__((packed));
177 } __attribute__((packed));
178
179
180 //line control register
181 struct lcr_register {
182     union {
183         uint8_t val;
184         struct {
185             uint8_t word_len       : 2;  // word length select
186             uint8_t stop_bits      : 1;  // Stop Bit select
187             uint8_t parity_enable  : 1;  // Enable parity
188             uint8_t even_sel       : 1;  // Even Parity Select
189             uint8_t stick_parity   : 1;  // Stick Parity Select
190             uint8_t sbr            : 1;  // Set Break
191             uint8_t dlab           : 1;  // Divisor latch access bit
192         } __attribute__((packed));
193     } __attribute__((packed));
194 } __attribute__((packed));
195
196
197 //modem control register
198 struct mcr_register {
199     union {
200         uint8_t val;
201         struct {
202             uint8_t dtr      : 1;
203             uint8_t rts      : 1;
204             uint8_t out1     : 1;
205             uint8_t out2     : 1;
206             uint8_t loop     : 1;  // loopback mode
207             uint8_t rsvd     : 3;  // MBZ
208         } __attribute__((packed));
209     } __attribute__((packed));
210 } __attribute__((packed));
211
212
213 //line status register
214 struct lsr_register {
215     union {
216         uint8_t val;
217         struct {
218             uint8_t dr      : 1;  // data ready
219             uint8_t oe       : 1;  // Overrun error
220             uint8_t pe       : 1;  // Parity Error
221             uint8_t fe       : 1;  // Framing Error
222             uint8_t brk      : 1;  // broken line detected
223             uint8_t thre     : 1;  // Transmitter holding register empty
224             uint8_t temt     : 1;  // Transmitter Empty
225             uint8_t fifo_err : 1;  // at least one error is pending in the RX FIFO chain
226         } __attribute__((packed));
227     } __attribute__((packed));
228 } __attribute__((packed));
229
230
231 struct msr_register {
232     union {
233         uint8_t val;
234         struct {
235             uint8_t dcts     : 1;  // Delta Clear To Send
236             uint8_t ddsr     : 1;  // Delta Data Set Ready
237             uint8_t teri     : 1;  // Trailing Edge Ring Indicator
238             uint8_t ddcd     : 1;  // Delta Data Carrier Detect
239             uint8_t cts      : 1;  // Clear to Send
240             uint8_t dsr      : 1;  // Data Set Ready
241             uint8_t ri       : 1;  // Ring Indicator
242             uint8_t dcd      : 1;  // Data Carrier Detect
243         } __attribute__((packed));
244     } __attribute__((packed));
245 } __attribute__((packed));
246
247 //scratch register
248 struct scr_register {
249     uint8_t data;
250 };
251
252 //divisor latch LSB
253 struct dll_register {
254     uint8_t data;
255 };
256
257 //divisor latch MSB
258 struct dlm_register {
259     uint8_t data;
260 };
261 #define SERIAL_BUF_LEN 128
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(VM_NONE, VCORE_NONE, "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(vm, VCORE_NONE, "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(vm, VCORE_NONE, "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(vm, VCORE_NONE, "Buffer is full!\n");
391
392         if (buf == &(com->rx_buffer)) {
393             com->lsr.oe = 1; //overrun error bit set
394         }
395
396         updateIRQ(vm, com);
397
398         return 0;
399     }
400     
401     buf->buffer[next_loc] = data;
402     buf->head = next_loc;
403     
404     if (buf->head == buf->tail) {
405         buf->full = 1;
406     }
407     
408     if (buf == &(com->rx_buffer)) {
409         com->lsr.dr = 1; //as soon as new data arrives at receive buffer, set data ready bit in lsr.
410     }
411     
412     if (buf == &(com->tx_buffer)) {
413         com->lsr.thre = 0; //reset thre and temt bits.
414         com->lsr.temt = 0;
415     }
416         
417     return 0;
418 }
419
420 static int dequeue_data(struct v3_vm_info * vm, struct serial_port * com,
421                         struct serial_buffer * buf, uint8_t * data) {
422
423     int next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
424
425
426     if ( (buf->head == buf->tail) && (buf->full != 1) ) {
427         PrintDebug(vm, VCORE_NONE, "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(core->vm_info, core, "Write to Data Port 0x%x (val=%x)\n", port, *val);
461     
462     if (length != 1) {
463         PrintError(core->vm_info, core, "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(core->vm_info, core, "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(core->vm_info, core, "UART:read from NOBODY\n");
477         return -1;
478     }
479     
480
481     // dlab is always checked first
482     if (com_port->lcr.dlab == 1) {
483         com_port->dll.data = *val;
484     }  else {
485         
486
487         /* JRL: Some buffering would probably be a good idea here.... */
488         if (com_port->ops) {
489             com_port->ops->output(val, 1, com_port->backend_data);
490         } else {
491             queue_data(core->vm_info, com_port, &(com_port->tx_buffer), *val);
492             updateIRQ(core->vm_info, com_port);
493         }
494     }
495     
496     return length;
497 }
498
499
500
501 static int read_data_port(struct guest_info * core, uint16_t port, 
502                           void * dst, uint_t length, void * priv_data) {
503     struct serial_state * state = priv_data;
504     uint8_t * val = (uint8_t *)dst;
505     struct serial_port * com_port = NULL;
506
507     PrintDebug(core->vm_info, core, "Read from Data Port 0x%x\n", port);
508     
509     if (length != 1) {
510         PrintError(core->vm_info, core, "Invalid length(%d) in write to 0x%x\n", length, port);
511         return -1;
512     }
513     
514     if ((port != COM1_DATA_PORT) && (port != COM2_DATA_PORT) && 
515         (port != COM3_DATA_PORT) && (port != COM4_DATA_PORT)) {
516         PrintError(core->vm_info, core, "Serial Read data port for illegal port Number (%d)\n", port);
517         return -1;
518     }
519
520     com_port = get_com_from_port(state, port);
521
522     if (com_port == NULL) {
523         PrintError(core->vm_info, core, "UART:read from NOBODY\n");
524         return -1;
525     }
526     
527     if (com_port->lcr.dlab == 1) {
528         *val = com_port->dll.data;
529     } else {
530         dequeue_data(core->vm_info, com_port, &(com_port->rx_buffer), val);
531     }    
532         
533     return length;
534 }
535
536
537
538 static int handle_fcr_write(struct serial_port * com, uint8_t value) {
539
540     com->fcr.enable = value & 0x1;
541     
542     if (com->fcr.enable == 0x1) {
543         com->fcr.val = value;
544
545         com->fcr.enable = 1; // Do we need to set this??
546
547         //if rfres set, clear receive buffer.
548         if (com->fcr.rfres == 0x1) {
549             com->rx_buffer.head = 0;
550             com->rx_buffer.tail = 0;
551             com->rx_buffer.full = 0;
552             memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
553             com->fcr.rfres = 0;
554         }
555
556         //if xfres set, clear transmit buffer.
557         if (com->fcr.xfres == 0x1) {
558             com->tx_buffer.head = 0;
559             com->tx_buffer.tail = 0;
560             com->tx_buffer.full = 0;
561             memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
562             com->fcr.xfres = 0;
563         }
564     } else {
565         //clear both buffers.
566         com->tx_buffer.head = 0;
567         com->tx_buffer.tail = 0;
568         com->tx_buffer.full = 0;
569         com->rx_buffer.head = 0;
570         com->rx_buffer.tail = 0;
571         com->rx_buffer.full = 0;
572         
573         memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
574         memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
575     }
576     
577     return 1;
578 }
579
580
581
582
583
584 static int write_ctrl_port(struct guest_info * core, uint16_t port, void * src, 
585                            uint_t length, void * priv_data) {
586     struct serial_state * state = priv_data;
587     uint8_t val = *(uint8_t *)src;
588     struct serial_port * com_port = NULL;
589
590     PrintDebug(core->vm_info, core, "UART:Write to Control Port (val=%x)\n", val);
591     
592     if (length != 1) {
593         PrintError(core->vm_info, core, "UART:Invalid Write length to control port%d\n", port);
594         return -1;
595     }
596
597     com_port = get_com_from_port(state, port);
598
599     if (com_port == NULL) {
600         PrintError(core->vm_info, core, "Could not find serial port corresponding to IO port %d\n", port);
601         return -1;
602     }
603     
604     //always check dlab first
605     switch (port) {
606         case COM1_IRQ_ENABLE_PORT:
607         case COM2_IRQ_ENABLE_PORT:
608         case COM3_IRQ_ENABLE_PORT:
609         case COM4_IRQ_ENABLE_PORT: {
610             PrintDebug(core->vm_info, core, "UART:Write to IER/LATCH port: dlab is %x\n", com_port->lcr.dlab);
611
612             if (com_port->lcr.dlab == 1) {
613                 com_port->dlm.data = val;
614             } else {
615                 com_port->ier.val = val;
616             }
617
618             break;
619         }           
620         case COM1_FIFO_CTRL_PORT:
621         case COM2_FIFO_CTRL_PORT:
622         case COM3_FIFO_CTRL_PORT:
623         case COM4_FIFO_CTRL_PORT: {
624             PrintDebug(core->vm_info, core, "UART:Write to FCR\n");
625
626             if (handle_fcr_write(com_port, val) == -1) {
627                 return -1;
628             }
629
630             break;
631         }
632         case COM1_LINE_CTRL_PORT:
633         case COM2_LINE_CTRL_PORT:
634         case COM3_LINE_CTRL_PORT:
635         case COM4_LINE_CTRL_PORT: {
636             PrintDebug(core->vm_info, core, "UART:Write to LCR\n");
637             com_port->lcr.val = val;
638             break;
639         }
640         case COM1_MODEM_CTRL_PORT:
641         case COM2_MODEM_CTRL_PORT:
642         case COM3_MODEM_CTRL_PORT:
643         case COM4_MODEM_CTRL_PORT: {
644             PrintDebug(core->vm_info, core, "UART:Write to MCR\n");
645             com_port->mcr.val = val;
646             break;
647         }
648         case COM1_SCRATCH_PORT:
649         case COM2_SCRATCH_PORT:
650         case COM3_SCRATCH_PORT:
651         case COM4_SCRATCH_PORT: {
652             PrintDebug(core->vm_info, core, "UART:Write to SCRATCH\n");
653             com_port->scr.data = val;
654             break;
655         }
656         default:
657             PrintError(core->vm_info, core, "UART:Write to NOBODY, ERROR\n");
658             return -1;
659     }
660     
661
662     return length;
663 }
664
665
666
667
668 static int read_ctrl_port(struct guest_info * core, uint16_t port, void * dst, 
669                           uint_t length, void * priv_data) {
670     struct serial_state * state = priv_data;
671     uint8_t * val = (uint8_t *)dst;
672     struct serial_port * com_port = NULL;
673
674     PrintDebug(core->vm_info, core, "Read from Control Port\n");
675     
676     if (length != 1) {
677         PrintError(core->vm_info, core, "Invalid Read length to control port\n");
678         return -1;
679     }
680
681     com_port = get_com_from_port(state, port);
682
683     if (com_port == NULL) {
684         PrintError(core->vm_info, core, "Could not find serial port corresponding to IO port %d\n", port);
685         return -1;
686     }
687     
688     //always check dlab first
689     switch (port) {
690         case COM1_IRQ_ENABLE_PORT:
691         case COM2_IRQ_ENABLE_PORT:
692         case COM3_IRQ_ENABLE_PORT:
693         case COM4_IRQ_ENABLE_PORT: {
694             PrintDebug(core->vm_info, core, "UART:read from IER\n");
695
696             if (com_port->lcr.dlab == 1) {
697                 *val = com_port->dlm.data;
698             } else {
699                 *val = com_port->ier.val;
700             }
701             break;
702         }
703
704         case COM1_IIR_PORT:
705         case COM2_IIR_PORT:
706         case COM3_IIR_PORT:
707         case COM4_IIR_PORT:
708             PrintDebug(core->vm_info, core, "UART:read from IIR\n");
709             *val = com_port->iir.val;
710             break;
711
712         case COM1_LINE_CTRL_PORT:
713         case COM2_LINE_CTRL_PORT:
714         case COM3_LINE_CTRL_PORT:
715         case COM4_LINE_CTRL_PORT:
716             PrintDebug(core->vm_info, core, "UART:read from LCR\n");
717             *val = com_port->lcr.val;
718             break;
719
720         case COM1_MODEM_CTRL_PORT:
721         case COM2_MODEM_CTRL_PORT:
722         case COM3_MODEM_CTRL_PORT:
723         case COM4_MODEM_CTRL_PORT:
724             PrintDebug(core->vm_info, core, "UART:read from MCR\n");
725             *val = com_port->mcr.val;
726             break;
727
728         case COM1_SCRATCH_PORT:
729         case COM2_SCRATCH_PORT:
730         case COM3_SCRATCH_PORT:
731         case COM4_SCRATCH_PORT:
732             PrintDebug(core->vm_info, core, "UART:read from SCRATCH\n");
733             *val = com_port->scr.data;
734             break;
735
736         default:
737             PrintError(core->vm_info, core, "UART:read from NOBODY\n");
738             return -1;
739     }
740
741     return length;
742 }
743
744
745 static int write_status_port(struct guest_info * core, uint16_t port, void * src, 
746                              uint_t length, void * priv_data) {
747     struct serial_state * state = priv_data;
748     uint8_t val = *(uint8_t *)src;
749     struct serial_port * com_port = NULL;
750
751     PrintDebug(core->vm_info, core, "Write to Status Port (val=%x)\n", val);
752
753     if (length != 1) {
754         PrintError(core->vm_info, core, "Invalid Write length to status port %d\n", port);
755         return -1;
756     }
757
758     com_port = get_com_from_port(state, port);
759
760     if (com_port == NULL) {
761         PrintError(core->vm_info, core, "Could not find serial port corresponding to IO port %d\n", port);
762         return -1;
763     }
764
765     switch (port) {
766         case COM1_LINE_STATUS_PORT:
767         case COM2_LINE_STATUS_PORT:
768         case COM3_LINE_STATUS_PORT:
769         case COM4_LINE_STATUS_PORT:
770             PrintDebug(core->vm_info, core, "UART:write to LSR\n");
771             com_port->lsr.val = val;
772             break;
773
774         case COM1_MODEM_STATUS_PORT:
775         case COM2_MODEM_STATUS_PORT:
776         case COM3_MODEM_STATUS_PORT:
777         case COM4_MODEM_STATUS_PORT:
778             PrintDebug(core->vm_info, core, "UART:write to MSR\n");
779             com_port->msr.val = val;
780             break;
781
782         default:
783             PrintError(core->vm_info, core, "UART:write to NOBODY\n");
784             return -1;
785     }
786
787     return length;
788 }
789
790 static int read_status_port(struct guest_info * core, uint16_t port, void * dst, 
791                             uint_t length, void * priv_data) {
792     struct serial_state * state = priv_data;
793     uint8_t * val = (uint8_t *)dst;
794     struct serial_port * com_port = NULL;
795
796     PrintDebug(core->vm_info, core, "Read from Status Port 0x%x\n", port);
797
798     com_port = get_com_from_port(state, port);
799
800     if (com_port == NULL) {
801         PrintError(core->vm_info, core, "Could not find serial port corresponding to IO port %d\n", port);
802         return -1;
803     }
804
805     switch (port) {
806         case COM1_LINE_STATUS_PORT:
807         case COM2_LINE_STATUS_PORT:
808         case COM3_LINE_STATUS_PORT:
809         case COM4_LINE_STATUS_PORT:
810
811             if (length != 1) {
812                 PrintError(core->vm_info, core, "Invalid Read length to control port\n");
813                 return -1;
814             }
815
816             PrintDebug(core->vm_info, core, "UART:read from LSR\n");
817
818             *val = com_port->lsr.val;
819             com_port->lsr.oe = 0;     // Why do we clear this??
820
821             break;
822
823         case COM1_MODEM_STATUS_PORT:
824         case COM2_MODEM_STATUS_PORT:
825         case COM3_MODEM_STATUS_PORT:
826         case COM4_MODEM_STATUS_PORT:
827             PrintDebug(core->vm_info, core, "UART:read from COM4 MSR (length = %d)\n", length);
828
829             if (length > 2) {
830                 PrintError(core->vm_info, core, "Invalid Read length to MSR port\n");
831                 return -1;
832             }
833
834             if (length == 2) {
835                 /* Windows XP expects to be able to read this register and the next in one go */
836
837                 if (read_ctrl_port(core, port + 1, val + 1, 1, priv_data) < 0) {
838                     PrintError(core->vm_info, core, "Error reading control port for word size read of Status register\n");
839                     return -1;
840                 }
841             }
842
843             // always read low byte...
844             
845             *val = com_port->msr.val;
846             break;
847
848         default:
849             PrintError(core->vm_info, core, "UART:read from NOBODY (length = %d)\n", length);
850             return -1;
851     }
852
853     return length;
854 }
855
856 static int serial_free(struct serial_state * state) {
857
858     V3_Free(state);
859     return 0;
860 }
861
862
863
864 #ifdef V3_CONFIG_CHECKPOINT
865
866 #include <palacios/vmm_sprintf.h>
867
868 static int serial_buffer_save(struct v3_chkpt_ctx * ctx, int port, struct serial_buffer *sb) {
869   
870   char keyname[128];
871   
872   snprintf(keyname,128,"COM%d_SB_HEAD", port);
873   V3_CHKPT_SAVE(ctx,keyname,sb->head,failout);
874   snprintf(keyname,128,"COM%d_SB_TAIL", port);
875   V3_CHKPT_SAVE(ctx,keyname,sb->tail,failout);
876   snprintf(keyname,128,"COM%d_SB_FULL", port);
877   V3_CHKPT_SAVE(ctx,keyname,sb->full,failout);
878   snprintf(keyname,128,"COM%d_SB_DATA", port);
879   V3_CHKPT_SAVE(ctx,keyname,sb->buffer,failout);
880   
881   return 0;
882   
883  failout:
884   PrintError(VM_NONE, VCORE_NONE, "Failed to save serial buffer\n");
885   return -1;
886 }
887
888  
889 static int serial_buffer_load(struct v3_chkpt_ctx * ctx, int port,  struct serial_buffer *sb) {
890
891   char keyname[128];
892
893   snprintf(keyname,128,"COM%d_SB_HEAD", port);
894   V3_CHKPT_LOAD(ctx,keyname,sb->head,failout);
895   snprintf(keyname,128,"COM%d_SB_TAIL", port);
896   V3_CHKPT_LOAD(ctx,keyname,sb->tail,failout);
897   snprintf(keyname,128,"COM%d_SB_FULL", port);
898   V3_CHKPT_LOAD(ctx,keyname,sb->full,failout);
899   snprintf(keyname,128,"COM%d_SB_DATA", port);
900   V3_CHKPT_LOAD(ctx,keyname,sb->buffer,failout);
901   
902   return 0;
903   
904  failout:
905   PrintError(VM_NONE, VCORE_NONE, "Failed to load serial buffer\n");
906   return -1;
907 }
908  
909 static int serial_save(struct v3_chkpt_ctx * ctx, void * private_data) {
910   struct serial_state *state = (struct serial_state *)private_data;
911   struct serial_port *serial;
912   char keyname[128];
913   int i;
914   
915   for (i=0;i<4;i++) { 
916     serial = &(state->coms[i]);
917     snprintf(keyname, 128,"COM%d_RBR",i);
918     V3_CHKPT_SAVE(ctx, keyname, serial->rbr.data,failout);
919     snprintf(keyname, 128,"COM%d_THR",i);
920     V3_CHKPT_SAVE(ctx, keyname, serial->thr.data,failout);
921     snprintf(keyname, 128,"COM%d_IER",i);
922     V3_CHKPT_SAVE(ctx, keyname, serial->ier.val,failout);
923     snprintf(keyname, 128,"COM%d_IIR",i);
924     V3_CHKPT_SAVE(ctx, keyname, serial->iir.val,failout);
925     snprintf(keyname, 128,"COM%d_FCR",i);
926     V3_CHKPT_SAVE(ctx, keyname, serial->fcr.val,failout);
927     snprintf(keyname, 128,"COM%d_LCR",i);
928     V3_CHKPT_SAVE(ctx, keyname, serial->lcr.val,failout);
929     snprintf(keyname, 128,"COM%d_MCR",i);
930     V3_CHKPT_SAVE(ctx, keyname, serial->mcr.val,failout);
931     snprintf(keyname, 128,"COM%d_LSR",i);
932     V3_CHKPT_SAVE(ctx, keyname, serial->lsr.val,failout);
933     snprintf(keyname, 128,"COM%d_MSR",i);
934     V3_CHKPT_SAVE(ctx, keyname, serial->msr.val,failout);
935     snprintf(keyname, 128,"COM%d_SCR",i);
936     V3_CHKPT_SAVE(ctx, keyname, serial->scr.data,failout);
937     snprintf(keyname, 128,"COM%d_DLL",i);
938     V3_CHKPT_SAVE(ctx, keyname, serial->dll.data,failout);
939     snprintf(keyname, 128,"COM%d_DLM",i);
940     V3_CHKPT_SAVE(ctx, keyname, serial->dlm.data,failout);
941     
942     if (serial_buffer_save(ctx, i, &(serial->tx_buffer))) { 
943       PrintError(VM_NONE, VCORE_NONE, "Failed to save serial tx buffer %d\n",i);
944       goto failout;
945     }
946     
947     if (serial_buffer_save(ctx, i, &(serial->rx_buffer))) { 
948       PrintError(VM_NONE, VCORE_NONE, "Failed to save serial rx buffer %d\n",i);
949       goto failout;
950     }
951     
952     V3_CHKPT_SAVE(ctx, keyname, serial->irq_number,failout);
953   }
954
955   return 0;
956
957  failout:
958   PrintError(VM_NONE, VCORE_NONE, "Failed to save serial device\n");
959   return -1;
960   
961 }
962  
963 static int serial_load(struct v3_chkpt_ctx * ctx, void * private_data) {
964   struct serial_state *state = (struct serial_state *)private_data;
965   struct serial_port *serial;
966   char keyname[128];
967   int i;
968   
969   for (i=0;i<4;i++) { 
970     serial = &(state->coms[i]);
971     snprintf(keyname, 128,"COM%d_RBR",i);
972     V3_CHKPT_LOAD(ctx, keyname, serial->rbr.data,failout);
973     snprintf(keyname, 128,"COM%d_THR",i);
974     V3_CHKPT_LOAD(ctx, keyname, serial->thr.data,failout);
975     snprintf(keyname, 128,"COM%d_IER",i);
976     V3_CHKPT_LOAD(ctx, keyname, serial->ier.val,failout);
977     snprintf(keyname, 128,"COM%d_IIR",i);
978     V3_CHKPT_LOAD(ctx, keyname, serial->iir.val,failout);
979     snprintf(keyname, 128,"COM%d_FCR",i);
980     V3_CHKPT_LOAD(ctx, keyname, serial->fcr.val,failout);
981     snprintf(keyname, 128,"COM%d_LCR",i);
982     V3_CHKPT_LOAD(ctx, keyname, serial->lcr.val,failout);
983     snprintf(keyname, 128,"COM%d_MCR",i);
984     V3_CHKPT_LOAD(ctx, keyname, serial->mcr.val,failout);
985     snprintf(keyname, 128,"COM%d_LSR",i);
986     V3_CHKPT_LOAD(ctx, keyname, serial->lsr.val,failout);
987     snprintf(keyname, 128,"COM%d_MSR",i);
988     V3_CHKPT_LOAD(ctx, keyname, serial->msr.val,failout);
989     snprintf(keyname, 128,"COM%d_SCR",i);
990     V3_CHKPT_LOAD(ctx, keyname, serial->scr.data,failout);
991     snprintf(keyname, 128,"COM%d_DLL",i);
992     V3_CHKPT_LOAD(ctx, keyname, serial->dll.data,failout);
993     snprintf(keyname, 128,"COM%d_DLM",i);
994     V3_CHKPT_LOAD(ctx, keyname, serial->dlm.data,failout);
995     
996     if (serial_buffer_load(ctx, i, &(serial->tx_buffer))) { 
997       PrintError(VM_NONE, VCORE_NONE, "Failed to load serial tx buffer %d\n",i);
998       goto failout;
999     }
1000     
1001     if (serial_buffer_load(ctx, i, &(serial->rx_buffer))) { 
1002       PrintError(VM_NONE, VCORE_NONE, "Failed to load serial rx buffer %d\n",i);
1003       goto failout;
1004     }
1005     
1006     V3_CHKPT_LOAD(ctx, keyname, serial->irq_number,failout);
1007   }
1008
1009   return 0;
1010
1011  failout:
1012   PrintError(VM_NONE, VCORE_NONE,"Failed to load serial device\n");
1013   return -1;
1014   
1015 }
1016
1017 #endif
1018
1019 static struct v3_device_ops dev_ops = {
1020     .free = (int (*)(void *))serial_free,
1021 #ifdef V3_CONFIG_CHECKPOINT
1022     .save = serial_save, 
1023     .load = serial_load
1024 #endif
1025 };
1026
1027
1028
1029 static int init_serial_port(struct serial_port * com) {
1030
1031     com->ier.val = IER_INIT_VAL;
1032     com->iir.val = IIR_INIT_VAL;
1033     com->fcr.val = FCR_INIT_VAL;
1034     com->lcr.val = LCR_INIT_VAL;
1035     com->mcr.val = MCR_INIT_VAL;
1036     com->lsr.val = LSR_INIT_VAL;
1037     com->msr.val = MSR_INIT_VAL;
1038
1039     com->dll.data =  DLL_INIT_VAL;
1040     com->dlm.data =  DLM_INIT_VAL;
1041     
1042     com->tx_buffer.head = 0;
1043     com->tx_buffer.tail = 0;
1044     com->tx_buffer.full = 0;
1045     memset(com->tx_buffer.buffer, 0, SERIAL_BUF_LEN);
1046
1047     com->rx_buffer.head = 0;
1048     com->rx_buffer.tail = 0;
1049     com->rx_buffer.full = 0;
1050     memset(com->rx_buffer.buffer, 0, SERIAL_BUF_LEN);
1051     
1052     com->ops = NULL;
1053     com->backend_data = NULL;
1054
1055     return 0;
1056 }
1057
1058 static uint64_t serial_input(struct v3_vm_info * vm, uint8_t * buf, uint64_t len, void * priv_data){
1059     struct serial_port * com_port = (struct serial_port *)priv_data;
1060     int i;
1061
1062     for(i = 0; i < len; i++){
1063         queue_data(vm, com_port, &(com_port->rx_buffer), buf[i]);
1064     }
1065
1066     updateIRQ(vm, com_port);
1067
1068     return len;
1069 }
1070
1071
1072 static int connect_fn(struct v3_vm_info * vm, 
1073                       void * frontend_data, 
1074                       struct v3_dev_char_ops * ops, 
1075                       v3_cfg_tree_t * cfg, 
1076                       void * private_data, 
1077                       void ** push_fn_arg) {
1078
1079     struct serial_state * serial = (struct serial_state *)frontend_data;
1080     struct serial_port * com = NULL;
1081     char * com_port = v3_cfg_val(cfg, "com_port");
1082     int com_idx = 0;
1083
1084     if (com_port == NULL) {
1085         PrintError(vm, VCORE_NONE, "Invalid Serial frontend config: missing \"com_port\"\n");
1086         return -1;
1087     }
1088     
1089     com_idx = atoi(com_port) - 1;
1090
1091     if ((com_idx > 3) || (com_idx < 0)) {
1092       PrintError(vm, VCORE_NONE, "Invalid Com port (%s) \n", com_port);
1093         return -1;
1094     }
1095
1096     com = &(serial->coms[com_idx]);
1097
1098     com->ops = ops;
1099     com->backend_data = private_data;
1100
1101     com->ops->input = serial_input;
1102     *push_fn_arg = com;
1103
1104     return 0;
1105 }
1106
1107 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1108     struct serial_state * state = NULL;
1109     char * dev_id = v3_cfg_val(cfg, "ID");
1110     int ret = 0;
1111
1112     state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
1113     
1114     if (state == NULL) {
1115         PrintError(vm,VCORE_NONE, "Could not allocate Serial Device\n");
1116         return -1;
1117     }
1118     
1119     memset(state, 0, sizeof(struct serial_state));
1120
1121     init_serial_port(&(state->coms[0]));
1122     init_serial_port(&(state->coms[1]));
1123     init_serial_port(&(state->coms[2]));
1124     init_serial_port(&(state->coms[3]));
1125
1126     state->coms[0].irq_number = COM1_IRQ;
1127     state->coms[1].irq_number = COM2_IRQ;
1128     state->coms[2].irq_number = COM3_IRQ;
1129     state->coms[3].irq_number = COM4_IRQ;
1130
1131
1132     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
1133
1134     if (dev == NULL) {
1135         PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
1136         V3_Free(state);
1137         return -1;
1138     }
1139
1140     PrintDebug(vm, VCORE_NONE, "Serial device attached\n");
1141
1142     ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
1143     ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1144     ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1145     ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1146     ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1147     ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1148     ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1149     ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1150
1151     ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
1152     ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1153     ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1154     ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1155     ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1156     ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1157     ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1158     ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1159
1160     ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
1161     ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1162     ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1163     ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1164     ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1165     ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1166     ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1167     ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1168
1169     ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
1170     ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
1171     ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1172     ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1173     ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
1174     ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
1175     ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
1176     ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
1177
1178     if (ret != 0) {
1179         PrintError(vm, VCORE_NONE, "Error hooking Serial IO ports\n");
1180         v3_remove_device(dev);
1181         return -1;
1182     }
1183
1184     PrintDebug(vm, VCORE_NONE, "Serial ports hooked\n");
1185
1186
1187
1188     if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
1189         PrintError(vm, VCORE_NONE, "Could not register %s as frontend\n", dev_id);
1190         v3_remove_device(dev);
1191         return -1;
1192     }
1193
1194
1195     return 0;
1196 }
1197
1198
1199
1200
1201
1202 device_register("SERIAL", serial_init)