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.


tried to reduce compiler warnings, and cut down on debugging output
[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) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <devices/serial.h>
21 #include <palacios/vmm.h>
22
23
24 #define COM1_DATA_PORT           0x3f8
25 #define COM1_IRQ_ENABLE_PORT     0x3f9
26 #define COM1_DIV_LATCH_LSB_PORT  0x3f8
27 #define COM1_DIV_LATCH_MSB_PORT  0x3f9
28 #define COM1_IIR_PORT            0x3fa
29 #define COM1_FIFO_CTRL_PORT      0x3fa
30 #define COM1_LINE_CTRL_PORT      0x3fb
31 #define COM1_MODEM_CTRL_PORT     0x3fc
32 #define COM1_LINE_STATUS_PORT    0x3fd
33 #define COM1_MODEM_STATUS_PORT   0x3fe
34 #define COM1_SCRATCH_PORT        0x3ff
35
36 #define COM2_DATA_PORT           0x2f8
37 #define COM2_IRQ_ENABLE_PORT     0x2f9
38 #define COM2_DIV_LATCH_LSB_PORT  0x2f8
39 #define COM2_DIV_LATCH_MSB_PORT  0x2f9
40 #define COM2_IIR_PORT            0x2fa
41 #define COM2_FIFO_CTRL_PORT      0x2fa
42 #define COM2_LINE_CTRL_PORT      0x2fb
43 #define COM2_MODEM_CTRL_PORT     0x2fc
44 #define COM2_LINE_STATUS_PORT    0x2fd
45 #define COM2_MODEM_STATUS_PORT   0x2fe
46 #define COM2_SCRATCH_PORT        0x2ff
47
48 #define COM3_DATA_PORT           0x3e8
49 #define COM3_IRQ_ENABLE_PORT     0x3e9
50 #define COM3_DIV_LATCH_LSB_PORT  0x3e8
51 #define COM3_DIV_LATCH_MSB_PORT  0x3e9
52 #define COM3_IIR_PORT            0x3ea
53 #define COM3_FIFO_CTRL_PORT      0x3ea
54 #define COM3_LINE_CTRL_PORT      0x3eb
55 #define COM3_MODEM_CTRL_PORT     0x3ec
56 #define COM3_LINE_STATUS_PORT    0x3ed
57 #define COM3_MODEM_STATUS_PORT   0x3ee
58 #define COM3_SCRATCH_PORT        0x3ef
59
60 #define COM4_DATA_PORT           0x2e8
61 #define COM4_IRQ_ENABLE_PORT     0x2e9
62 #define COM4_DIV_LATCH_LSB_PORT  0x2e8
63 #define COM4_DIV_LATCH_MSB_PORT  0x2e9
64 #define COM4_IIR_PORT            0x2ea
65 #define COM4_FIFO_CTRL_PORT      0x2ea
66 #define COM4_LINE_CTRL_PORT      0x2eb
67 #define COM4_MODEM_CTRL_PORT     0x2ec
68 #define COM4_LINE_STATUS_PORT    0x2ed
69 #define COM4_MODEM_STATUS_PORT   0x2ee
70 #define COM4_SCRATCH_PORT        0x2ef
71
72
73
74 struct irq_enable_reg {
75   uint_t erbfi   : 1;  // Enable Receiver Buffer full interrupt
76   uint_t etbei   : 1;  // Enable Transmit buffer empty interrupt
77   uint_t elsi    : 1;  // Enable Line Status Interrupt
78   uint_t edssi   : 1;  // Enable Delta Status signals interrupt
79   uint_t rsvd    : 4;   // MBZ
80 };
81
82
83
84 // Interrupt IDs (in priority order, highest is first)
85 #define STATUS_IRQ_LSR_OE_SET   0x3
86 #define STATUS_IRQ_LSR_PE_SET   0x3
87 #define STATUS_IRQ_LSR_FE_SET   0x3
88 #define STATUS_IRQ_LSR_BI_SET   0x3
89 #define RX_IRQ_DR               0x2
90 #define RX_IRQ_TRIGGER_LEVEL    0x2
91 #define FIFO_IRQ                0x6
92 #define TX_IRQ_THRE             0x1
93 #define MODEL_IRQ_DELTA_SET     0x0
94
95 struct irq_id_reg {
96   uint_t pending : 1; // Interrupt pending (0=interrupt pending)
97   uint_t iid     : 3; // Interrupt Identification
98   uint_t rsvd    : 2; // MBZ
99   uint_t fifo_en : 2; // FIFO enable
100 };
101
102 struct fifo_ctrl_reg {
103   uint_t enable  : 1; // enable fifo
104   uint_t rfres   : 1; // RX FIFO reset
105   uint_t xfres   : 1; // TX FIFO reset
106   uint_t dma_sel : 1; // DMA mode select
107   uint_t rsvd    : 2; // MBZ
108   uint_t rx_trigger: 2; // RX FIFO trigger level select
109 };
110
111 struct line_ctrl_reg {
112   uint_t word_len       : 2;  // word length select
113   uint_t stop_bits      : 1;  // Stop Bit select
114   uint_t parity_enable  : 1;  // Enable parity 
115   uint_t even_sel       : 1;  // Even Parity Select
116   uint_t stick_parity   : 1;  // Stick Parity Select
117   uint_t sbr            : 1;  // Set Break 
118   uint_t dlab           : 1;  // Divisor latch access bit
119 };
120
121
122 struct modem_ctrl_reg { 
123   uint_t dtr      : 1;
124   uint_t rts      : 1;
125   uint_t out1     : 1;
126   uint_t out2     : 1;
127   uint_t loop     : 1;  // loopback mode
128   uint_t rsvd     : 3;  // MBZ
129 };
130
131
132 struct line_status_reg {
133   uint_t rbf      : 1;  // Receiver Buffer Full
134   uint_t oe       : 1;  // Overrun error
135   uint_t pe       : 1;  // Parity Error
136   uint_t fe       : 1;  // Framing Error
137   uint_t brk      : 1;  // broken line detected
138   uint_t thre     : 1;  // Transmitter holding register empty
139   uint_t temt     : 1;  // Transmitter Empty
140   uint_t fifo_err : 1;  // at least one error is pending in the RX FIFO chain
141 };
142
143
144 struct modem_status_reg {
145   uint_t dcts     : 1;  // Delta Clear To Send
146   uint_t ddsr     : 1;  // Delta Data Set Ready
147   uint_t teri     : 1;  // Trailing Edge Ring Indicator
148   uint_t ddcd     : 1;  // Delta Data Carrier Detect
149   uint_t cts      : 1;  // Clear to Send
150   uint_t dsr      : 1;  // Data Set Ready
151   uint_t ri       : 1;  // Ring Indicator
152   uint_t dcd      : 1;  // Data Carrier Detect
153 };
154
155
156 #define SERIAL_BUF_LEN 256
157
158 struct serial_buffer {
159   uint_t head; // most recent data
160   uint_t tail; // oldest char
161   char buffer[SERIAL_BUF_LEN];
162 };
163
164 int queue_data(struct serial_buffer * buf, char data) {
165   uint_t next_loc = (buf->head + 1) % SERIAL_BUF_LEN;
166
167   if (next_loc == buf->tail) {
168     return -1;
169   }
170
171   buf->buffer[next_loc] = data;
172   buf->head = next_loc;
173
174   return 0;
175 }
176
177 int dequeue_data(struct serial_buffer * buf, char * data) {
178   uint_t next_tail = (buf->tail + 1) % SERIAL_BUF_LEN;
179
180   if (buf->head == buf->tail) {
181     return -1;
182   }
183
184   *data = buf->buffer[buf->tail];
185   buf->tail = next_tail;
186
187   return 0;
188 }
189
190
191 struct serial_port {
192   char     ier;
193   char     iir;
194   char     fcr;
195   char     lcr;
196   char     mcr;
197   char     lsr;
198   char     msr;
199
200   struct serial_buffer tx_buffer;
201   struct serial_buffer rx_buffer;
202 };
203
204
205 struct serial_state {
206   struct serial_port com1;
207   struct serial_port com2;
208   struct serial_port com3;
209   struct serial_port com4;
210 };
211
212
213 int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
214   struct serial_state * state = (struct serial_state *)dev->private_data;
215   char * val = (char *)src;
216   PrintDebug("Write to Data Port 0x%x (val=%x)\n", port, *(char*)src);
217
218   if (length != 1) {
219     PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
220     return -1;
221   }
222
223   switch (port) {
224   case COM1_DATA_PORT:
225     queue_data(&(state->com1.tx_buffer), *val);
226     break;
227   case COM2_DATA_PORT:
228     queue_data(&(state->com2.tx_buffer), *val);
229     break;
230   case COM3_DATA_PORT:
231     queue_data(&(state->com3.tx_buffer), *val);
232     break;
233   case COM4_DATA_PORT:
234     queue_data(&(state->com4.tx_buffer), *val);
235     break;
236   default:
237     return -1;
238   }
239   
240
241   return length;
242 }
243
244
245
246 int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
247   struct serial_state * state = (struct serial_state *)dev->private_data;
248   char * val = (char *)dst;
249   PrintDebug("Read from Data Port 0x%x\n", port);
250
251   if (length != 1) {
252     PrintDebug("Invalid length(%d) in write to 0x%x\n", length, port);
253     return -1;
254   }
255
256   switch (port) {
257   case COM1_DATA_PORT:
258     dequeue_data(&(state->com1.tx_buffer), val);
259     break;
260   case COM2_DATA_PORT:
261     dequeue_data(&(state->com2.tx_buffer), val);
262     break;
263   case COM3_DATA_PORT:
264     dequeue_data(&(state->com3.tx_buffer), val);
265     break;
266   case COM4_DATA_PORT:
267     dequeue_data(&(state->com4.tx_buffer), val);
268     break;
269   default:
270     return -1;
271   }
272   
273
274   return length;
275 }
276
277
278
279 int handle_ier_write(struct serial_port * com, struct irq_enable_reg * ier) {
280   
281
282   return -1;
283 }
284
285
286 int write_ctrl_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
287   struct serial_state * state = (struct serial_state *)dev->private_data;
288   char * val = (char *)src;
289   PrintDebug("Write to Control Port (val=%x)\n", *(char *)src);
290
291   if (length != 1) {
292     PrintDebug("Invalid Write length to control port\n", port, port);
293     return -1;
294   }
295
296   switch (port) {
297   case COM1_IRQ_ENABLE_PORT:
298     if (handle_ier_write(&(state->com1), (struct irq_enable_reg *)val) == -1) {
299       return -1;
300     }
301     break;
302   case COM2_IRQ_ENABLE_PORT:
303     if (handle_ier_write(&(state->com2), (struct irq_enable_reg *)val) == -1) {
304       return -1;
305     }
306     break;
307   case COM3_IRQ_ENABLE_PORT:
308     if (handle_ier_write(&(state->com3), (struct irq_enable_reg *)val) == -1) {
309       return -1;
310     }
311     break;
312   case COM4_IRQ_ENABLE_PORT:
313     if (handle_ier_write(&(state->com4), (struct irq_enable_reg *)val) == -1) {
314       return -1;
315     }
316     break;
317
318   case COM1_FIFO_CTRL_PORT:
319   case COM2_FIFO_CTRL_PORT:
320   case COM3_FIFO_CTRL_PORT:
321   case COM4_FIFO_CTRL_PORT:
322
323   case COM1_LINE_CTRL_PORT:
324   case COM2_LINE_CTRL_PORT:
325   case COM3_LINE_CTRL_PORT:
326   case COM4_LINE_CTRL_PORT:
327
328   case COM1_MODEM_CTRL_PORT:
329   case COM2_MODEM_CTRL_PORT:
330   case COM3_MODEM_CTRL_PORT:
331   case COM4_MODEM_CTRL_PORT:
332     
333
334
335   default:
336     return -1;
337   }
338
339
340   return -1;
341 }
342
343
344
345
346 int read_ctrl_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
347   struct serial_state * state = (struct serial_state *)dev->private_data;
348   char * val = (char *)dst;
349   PrintDebug("Read from Control Port\n");
350
351   if (length != 1) {
352     PrintDebug("Invalid Read length to control port\n");
353     return -1;
354   }
355
356   switch (port) {
357   case COM1_IRQ_ENABLE_PORT:
358     *val = state->com1.ier;
359     break;
360   case COM2_IRQ_ENABLE_PORT:
361     *val = state->com2.ier;
362     break;
363   case COM3_IRQ_ENABLE_PORT:
364     *val = state->com3.ier;
365     break;
366   case COM4_IRQ_ENABLE_PORT:
367     *val = state->com4.ier;
368     break;
369
370   case COM1_FIFO_CTRL_PORT:
371     *val = state->com1.fcr;
372     break;
373   case COM2_FIFO_CTRL_PORT:
374     *val = state->com2.fcr;
375     break;
376   case COM3_FIFO_CTRL_PORT:
377     *val = state->com3.fcr;
378     break;
379   case COM4_FIFO_CTRL_PORT:
380     *val = state->com4.fcr;
381     break;
382
383   case COM1_LINE_CTRL_PORT:
384     *val = state->com1.lcr;
385     break;
386   case COM2_LINE_CTRL_PORT:
387     *val = state->com2.lcr;
388     break;
389   case COM3_LINE_CTRL_PORT:
390     *val = state->com3.lcr;
391     break;
392   case COM4_LINE_CTRL_PORT:
393     *val = state->com4.lcr;
394     break;
395
396   case COM1_MODEM_CTRL_PORT:
397     *val = state->com1.mcr;
398     break;
399   case COM2_MODEM_CTRL_PORT:
400     *val = state->com2.mcr;
401     break;
402   case COM3_MODEM_CTRL_PORT:
403     *val = state->com3.mcr;
404     break;
405   case COM4_MODEM_CTRL_PORT:
406     *val = state->com4.mcr;
407     break;
408
409   default:
410     return -1;
411   }
412
413   return length;
414 }
415
416
417 int write_status_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
418   PrintDebug("Write to Status Port 0x%x (val=%x)\n", port, *(char *)src);
419
420   return -1;
421 }
422
423 int read_status_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
424   struct serial_state * state = (struct serial_state *)dev->private_data;
425   char * val = (char *)dst;
426   PrintDebug("Read from Status Port 0x%x\n", port);
427   
428   if (length != 1) {
429     PrintDebug("Invalid Read length to control port\n");
430     return -1;
431   }
432   
433   switch (port) {
434   case COM1_LINE_STATUS_PORT:
435     *val = state->com1.lsr;
436     break;
437   case COM2_LINE_STATUS_PORT:
438     *val = state->com2.lsr;
439     break;
440   case COM3_LINE_STATUS_PORT:
441     *val = state->com3.lsr;
442     break;
443   case COM4_LINE_STATUS_PORT:
444     *val = state->com4.lsr;
445     break;
446     
447   case COM1_MODEM_STATUS_PORT:
448     *val = state->com1.msr;
449     break;
450   case COM2_MODEM_STATUS_PORT:
451     *val = state->com2.msr;
452     break;
453   case COM3_MODEM_STATUS_PORT:
454     *val = state->com3.msr;
455     break;
456   case COM4_MODEM_STATUS_PORT:
457     *val = state->com4.msr;
458     break;
459
460   default:
461     return -1;
462   }
463
464
465
466   return length;
467 }
468
469
470
471
472
473 static int init_serial_port(struct serial_port * com) {
474   //struct irq_enable_reg * ier = (struct irq_enable_reg *)&(com->ier);
475   //struct irq_id_reg * iir = (struct irq_id_reg *)&(com->iir);
476   //struct fifo_ctrl_reg * fcr = (struct fifo_ctrl_reg *)&(com->fcr);
477   //struct line_ctrl_reg * lcr = (struct line_ctrl_reg *)&(com->lcr);
478   //struct modem_ctrl_reg * mcr = (struct modem_ctrl_reg *)&(com->mcr);
479   //struct line_status_reg * lsr = (struct line_status_reg *)&(com->lsr);
480   //struct modem_status_reg * msr = (struct modem_status_reg *)&(com->msr);
481
482   com->ier = 0x00;
483   com->iir = 0x01;
484   com->fcr = 0x00;
485   com->lcr = 0x00;
486   com->mcr = 0x00;
487   com->lsr = 0x60;
488   com->msr = 0x00;
489
490   return 0;
491 }
492
493 int serial_init(struct vm_device * dev) {
494   struct serial_state * state = (struct serial_state *)dev->private_data;
495
496
497   init_serial_port(&(state->com1));
498   init_serial_port(&(state->com2));
499   init_serial_port(&(state->com3));
500   init_serial_port(&(state->com4));
501
502   dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
503   dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
504   dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
505   dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
506   dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
507   dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
508   dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
509   dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
510
511   dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
512   dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
513   dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
514   dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
515   dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
516   dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
517   dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
518   dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
519
520   dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
521   dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
522   dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
523   dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
524   dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
525   dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
526   dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
527   dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
528
529   dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
530   dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
531   dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
532   dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
533   dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
534   dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
535   dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
536   dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
537
538   return 0;
539 }
540
541
542 int serial_deinit(struct vm_device * dev) {
543
544
545   dev_unhook_io(dev, COM1_DATA_PORT);
546   dev_unhook_io(dev, COM1_IRQ_ENABLE_PORT);
547   dev_unhook_io(dev, COM1_FIFO_CTRL_PORT);
548   dev_unhook_io(dev, COM1_LINE_CTRL_PORT);
549   dev_unhook_io(dev, COM1_MODEM_CTRL_PORT);
550   dev_unhook_io(dev, COM1_LINE_STATUS_PORT);
551   dev_unhook_io(dev, COM1_MODEM_STATUS_PORT);
552   dev_unhook_io(dev, COM1_SCRATCH_PORT);
553
554   dev_unhook_io(dev, COM2_DATA_PORT);
555   dev_unhook_io(dev, COM2_IRQ_ENABLE_PORT);
556   dev_unhook_io(dev, COM2_FIFO_CTRL_PORT);
557   dev_unhook_io(dev, COM2_LINE_CTRL_PORT);
558   dev_unhook_io(dev, COM2_MODEM_CTRL_PORT);
559   dev_unhook_io(dev, COM2_LINE_STATUS_PORT);
560   dev_unhook_io(dev, COM2_MODEM_STATUS_PORT);
561   dev_unhook_io(dev, COM2_SCRATCH_PORT);
562
563   dev_unhook_io(dev, COM3_DATA_PORT);
564   dev_unhook_io(dev, COM3_IRQ_ENABLE_PORT);
565   dev_unhook_io(dev, COM3_FIFO_CTRL_PORT);
566   dev_unhook_io(dev, COM3_LINE_CTRL_PORT);
567   dev_unhook_io(dev, COM3_MODEM_CTRL_PORT);
568   dev_unhook_io(dev, COM3_LINE_STATUS_PORT);
569   dev_unhook_io(dev, COM3_MODEM_STATUS_PORT);
570   dev_unhook_io(dev, COM3_SCRATCH_PORT);
571
572   dev_unhook_io(dev, COM4_DATA_PORT);
573   dev_unhook_io(dev, COM4_IRQ_ENABLE_PORT);
574   dev_unhook_io(dev, COM4_FIFO_CTRL_PORT);
575   dev_unhook_io(dev, COM4_LINE_CTRL_PORT);
576   dev_unhook_io(dev, COM4_MODEM_CTRL_PORT);
577   dev_unhook_io(dev, COM4_LINE_STATUS_PORT);
578   dev_unhook_io(dev, COM4_MODEM_STATUS_PORT);
579   dev_unhook_io(dev, COM4_SCRATCH_PORT);
580
581   return 0;
582 }
583
584
585
586 static struct vm_device_ops dev_ops = {
587   .init = serial_init,
588   .deinit = serial_deinit,
589   .reset = NULL,
590   .start = NULL,
591   .stop = NULL,
592 };
593
594
595 struct vm_device * create_serial(int num_ports) {
596   struct serial_state * state = NULL;
597   state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
598   V3_ASSERT(state != NULL);
599
600   struct vm_device * device = create_device("Serial UART", &dev_ops, state);
601
602   return device;
603 }