Commit e57a8c0eefcf648bd0f357abd94ee2871888f43d

Authored by bellard
1 parent 2122c51a

low level host parallel port access


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1611 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -8,6 +8,7 @@ version 0.7.3:
8 8 - ES1370 PCI audio device (malc)
9 9 - Initial USB support
10 10 - Linux host serial port access
  11 + - Linux host low level parallel port access
11 12  
12 13 version 0.7.2:
13 14  
... ...
hw/parallel.c
1 1 /*
2 2 * QEMU Parallel PORT emulation
3 3 *
4   - * Copyright (c) 2003-2004 Fabrice Bellard
  4 + * Copyright (c) 2003-2005 Fabrice Bellard
5 5 *
6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 7 * of this software and associated documentation files (the "Software"), to deal
... ... @@ -50,6 +50,7 @@ struct ParallelState {
50 50 int irq;
51 51 int irq_pending;
52 52 CharDriverState *chr;
  53 + int hw_driver;
53 54 };
54 55  
55 56 static void parallel_update_irq(ParallelState *s)
... ... @@ -70,29 +71,39 @@ static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
70 71 #endif
71 72 switch(addr) {
72 73 case 0:
73   - s->data = val;
74   - parallel_update_irq(s);
  74 + if (s->hw_driver) {
  75 + s->data = val;
  76 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
  77 + } else {
  78 + s->data = val;
  79 + parallel_update_irq(s);
  80 + }
75 81 break;
76 82 case 2:
77   - if ((val & PARA_CTR_INIT) == 0 ) {
78   - s->status = PARA_STS_BUSY;
79   - s->status |= PARA_STS_ACK;
80   - s->status |= PARA_STS_ONLINE;
81   - s->status |= PARA_STS_ERROR;
82   - }
83   - else if (val & PARA_CTR_SELECT) {
84   - if (val & PARA_CTR_STROBE) {
85   - s->status &= ~PARA_STS_BUSY;
86   - if ((s->control & PARA_CTR_STROBE) == 0)
87   - qemu_chr_write(s->chr, &s->data, 1);
88   - } else {
89   - if (s->control & PARA_CTR_INTEN) {
90   - s->irq_pending = 1;
  83 + if (s->hw_driver) {
  84 + s->control = val;
  85 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
  86 + } else {
  87 + if ((val & PARA_CTR_INIT) == 0 ) {
  88 + s->status = PARA_STS_BUSY;
  89 + s->status |= PARA_STS_ACK;
  90 + s->status |= PARA_STS_ONLINE;
  91 + s->status |= PARA_STS_ERROR;
  92 + }
  93 + else if (val & PARA_CTR_SELECT) {
  94 + if (val & PARA_CTR_STROBE) {
  95 + s->status &= ~PARA_STS_BUSY;
  96 + if ((s->control & PARA_CTR_STROBE) == 0)
  97 + qemu_chr_write(s->chr, &s->data, 1);
  98 + } else {
  99 + if (s->control & PARA_CTR_INTEN) {
  100 + s->irq_pending = 1;
  101 + }
91 102 }
92 103 }
  104 + parallel_update_irq(s);
  105 + s->control = val;
93 106 }
94   - parallel_update_irq(s);
95   - s->control = val;
96 107 break;
97 108 }
98 109 }
... ... @@ -105,24 +116,35 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
105 116 addr &= 7;
106 117 switch(addr) {
107 118 case 0:
  119 + if (s->hw_driver) {
  120 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
  121 + }
108 122 ret = s->data;
109 123 break;
110 124 case 1:
111   - ret = s->status;
112   - s->irq_pending = 0;
113   - if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
114   - /* XXX Fixme: wait 5 microseconds */
115   - if (s->status & PARA_STS_ACK)
116   - s->status &= ~PARA_STS_ACK;
117   - else {
118   - /* XXX Fixme: wait 5 microseconds */
119   - s->status |= PARA_STS_ACK;
120   - s->status |= PARA_STS_BUSY;
  125 + if (s->hw_driver) {
  126 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
  127 + ret = s->status;
  128 + } else {
  129 + ret = s->status;
  130 + s->irq_pending = 0;
  131 + if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
  132 + /* XXX Fixme: wait 5 microseconds */
  133 + if (s->status & PARA_STS_ACK)
  134 + s->status &= ~PARA_STS_ACK;
  135 + else {
  136 + /* XXX Fixme: wait 5 microseconds */
  137 + s->status |= PARA_STS_ACK;
  138 + s->status |= PARA_STS_BUSY;
  139 + }
121 140 }
  141 + parallel_update_irq(s);
122 142 }
123   - parallel_update_irq(s);
124 143 break;
125 144 case 2:
  145 + if (s->hw_driver) {
  146 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
  147 + }
126 148 ret = s->control;
127 149 break;
128 150 }
... ... @@ -153,18 +175,20 @@ static void parallel_receive1(void *opaque, const uint8_t *buf, int size)
153 175 parallel_receive_byte(s, buf[0]);
154 176 }
155 177  
156   -static void parallel_event(void *opaque, int event)
157   -{
158   -}
159   -
160 178 /* If fd is zero, it means that the parallel device uses the console */
161 179 ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
162 180 {
163 181 ParallelState *s;
  182 + uint8_t dummy;
164 183  
165 184 s = qemu_mallocz(sizeof(ParallelState));
166 185 if (!s)
167 186 return NULL;
  187 + s->chr = chr;
  188 + s->hw_driver = 0;
  189 + if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
  190 + s->hw_driver = 1;
  191 +
168 192 s->irq = irq;
169 193 s->data = 0;
170 194 s->status = PARA_STS_BUSY;
... ... @@ -176,8 +200,6 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
176 200  
177 201 register_ioport_write(base, 8, 1, parallel_ioport_write, s);
178 202 register_ioport_read(base, 8, 1, parallel_ioport_read, s);
179   - s->chr = chr;
180 203 qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s);
181   - qemu_chr_add_event_handler(chr, parallel_event);
182 204 return s;
183 205 }
... ...
qemu-doc.texi
... ... @@ -364,8 +364,11 @@ Virtual console
364 364 @item null
365 365 void device
366 366 @item /dev/XXX
367   -[Linux only]Use host tty, e.g. @file{/dev/ttyS0}. The host serial port
  367 +[Linux only] Use host tty, e.g. @file{/dev/ttyS0}. The host serial port
368 368 parameters are set according to the emulated ones.
  369 +@item /dev/parportN
  370 +[Linux only, parallel port only] Use host parallel port
  371 +@var{N}. Currently only SPP parallel port features can be used.
369 372 @item file:filename
370 373 Write output to filename. No character can be read.
371 374 @item stdio
... ... @@ -379,6 +382,15 @@ non graphical mode.
379 382 This option can be used several times to simulate up to 4 serials
380 383 ports.
381 384  
  385 +@item -parallel dev
  386 +Redirect the virtual parallel port to host device @var{dev} (same
  387 +devices as the serial port). On Linux hosts, @file{/dev/parportN} can
  388 +be used to use hardware devices connected on the corresponding host
  389 +parallel port.
  390 +
  391 +This option can be used several times to simulate up to 3 parallel
  392 +ports.
  393 +
382 394 @item -monitor dev
383 395 Redirect the monitor to host device @var{dev} (same devices as the
384 396 serial port).
... ...
... ... @@ -51,6 +51,7 @@
51 51 #include <pty.h>
52 52 #include <malloc.h>
53 53 #include <linux/rtc.h>
  54 +#include <linux/ppdev.h>
54 55 #endif
55 56 #endif
56 57  
... ... @@ -1013,21 +1014,13 @@ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
1013 1014 return s->chr_write(s, buf, len);
1014 1015 }
1015 1016  
1016   -void qemu_chr_set_serial_parameters(CharDriverState *s,
1017   - int speed, int parity,
1018   - int data_bits, int stop_bits)
  1017 +int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg)
1019 1018 {
1020   - if (s->chr_set_serial_parameters)
1021   - s->chr_set_serial_parameters(s, speed, parity, data_bits, stop_bits);
  1019 + if (!s->chr_ioctl)
  1020 + return -ENOTSUP;
  1021 + return s->chr_ioctl(s, cmd, arg);
1022 1022 }
1023 1023  
1024   -void qemu_chr_set_serial_break(CharDriverState *s, int enable)
1025   -{
1026   - if (s->chr_set_serial_break)
1027   - s->chr_set_serial_break(s, enable);
1028   -}
1029   -
1030   -
1031 1024 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
1032 1025 {
1033 1026 char buf[4096];
... ... @@ -1379,7 +1372,11 @@ static void tty_serial_init(int fd, int speed,
1379 1372 struct termios tty;
1380 1373 speed_t spd;
1381 1374  
1382   - tcgetattr (0, &tty);
  1375 +#if 0
  1376 + printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
  1377 + speed, parity, data_bits, stop_bits);
  1378 +#endif
  1379 + tcgetattr (fd, &tty);
1383 1380  
1384 1381 switch(speed) {
1385 1382 case 50:
... ... @@ -1459,20 +1456,29 @@ static void tty_serial_init(int fd, int speed,
1459 1456 tcsetattr (fd, TCSANOW, &tty);
1460 1457 }
1461 1458  
1462   -static void tty_set_serial_parameters(CharDriverState *chr,
1463   - int speed, int parity,
1464   - int data_bits, int stop_bits)
  1459 +static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
1465 1460 {
1466 1461 FDCharDriver *s = chr->opaque;
1467   - tty_serial_init(s->fd_in, speed, parity, data_bits, stop_bits);
1468   -}
1469   -
1470   -static void tty_set_serial_break(CharDriverState *chr, int enable)
1471   -{
1472   - FDCharDriver *s = chr->opaque;
1473   - /* XXX: find a better solution */
1474   - if (enable)
1475   - tcsendbreak(s->fd_in, 1);
  1462 +
  1463 + switch(cmd) {
  1464 + case CHR_IOCTL_SERIAL_SET_PARAMS:
  1465 + {
  1466 + QEMUSerialSetParams *ssp = arg;
  1467 + tty_serial_init(s->fd_in, ssp->speed, ssp->parity,
  1468 + ssp->data_bits, ssp->stop_bits);
  1469 + }
  1470 + break;
  1471 + case CHR_IOCTL_SERIAL_SET_BREAK:
  1472 + {
  1473 + int enable = *(int *)arg;
  1474 + if (enable)
  1475 + tcsendbreak(s->fd_in, 1);
  1476 + }
  1477 + break;
  1478 + default:
  1479 + return -ENOTSUP;
  1480 + }
  1481 + return 0;
1476 1482 }
1477 1483  
1478 1484 CharDriverState *qemu_chr_open_tty(const char *filename)
... ... @@ -1480,7 +1486,7 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
1480 1486 CharDriverState *chr;
1481 1487 int fd;
1482 1488  
1483   - fd = open(filename, O_RDWR);
  1489 + fd = open(filename, O_RDWR | O_NONBLOCK);
1484 1490 if (fd < 0)
1485 1491 return NULL;
1486 1492 fcntl(fd, F_SETFL, O_NONBLOCK);
... ... @@ -1488,8 +1494,70 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
1488 1494 chr = qemu_chr_open_fd(fd, fd);
1489 1495 if (!chr)
1490 1496 return NULL;
1491   - chr->chr_set_serial_parameters = tty_set_serial_parameters;
1492   - chr->chr_set_serial_break = tty_set_serial_break;
  1497 + chr->chr_ioctl = tty_serial_ioctl;
  1498 + return chr;
  1499 +}
  1500 +
  1501 +static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
  1502 +{
  1503 + int fd = (int)chr->opaque;
  1504 + uint8_t b;
  1505 +
  1506 + switch(cmd) {
  1507 + case CHR_IOCTL_PP_READ_DATA:
  1508 + if (ioctl(fd, PPRDATA, &b) < 0)
  1509 + return -ENOTSUP;
  1510 + *(uint8_t *)arg = b;
  1511 + break;
  1512 + case CHR_IOCTL_PP_WRITE_DATA:
  1513 + b = *(uint8_t *)arg;
  1514 + if (ioctl(fd, PPWDATA, &b) < 0)
  1515 + return -ENOTSUP;
  1516 + break;
  1517 + case CHR_IOCTL_PP_READ_CONTROL:
  1518 + if (ioctl(fd, PPRCONTROL, &b) < 0)
  1519 + return -ENOTSUP;
  1520 + *(uint8_t *)arg = b;
  1521 + break;
  1522 + case CHR_IOCTL_PP_WRITE_CONTROL:
  1523 + b = *(uint8_t *)arg;
  1524 + if (ioctl(fd, PPWCONTROL, &b) < 0)
  1525 + return -ENOTSUP;
  1526 + break;
  1527 + case CHR_IOCTL_PP_READ_STATUS:
  1528 + if (ioctl(fd, PPRSTATUS, &b) < 0)
  1529 + return -ENOTSUP;
  1530 + *(uint8_t *)arg = b;
  1531 + break;
  1532 + default:
  1533 + return -ENOTSUP;
  1534 + }
  1535 + return 0;
  1536 +}
  1537 +
  1538 +CharDriverState *qemu_chr_open_pp(const char *filename)
  1539 +{
  1540 + CharDriverState *chr;
  1541 + int fd;
  1542 +
  1543 + fd = open(filename, O_RDWR);
  1544 + if (fd < 0)
  1545 + return NULL;
  1546 +
  1547 + if (ioctl(fd, PPCLAIM) < 0) {
  1548 + close(fd);
  1549 + return NULL;
  1550 + }
  1551 +
  1552 + chr = qemu_mallocz(sizeof(CharDriverState));
  1553 + if (!chr) {
  1554 + close(fd);
  1555 + return NULL;
  1556 + }
  1557 + chr->opaque = (void *)fd;
  1558 + chr->chr_write = null_chr_write;
  1559 + chr->chr_add_read_handler = null_chr_add_read_handler;
  1560 + chr->chr_ioctl = pp_ioctl;
1493 1561 return chr;
1494 1562 }
1495 1563  
... ... @@ -1522,6 +1590,9 @@ CharDriverState *qemu_chr_open(const char *filename)
1522 1590 } else
1523 1591 #endif
1524 1592 #if defined(__linux__)
  1593 + if (strstart(filename, "/dev/parport", NULL)) {
  1594 + return qemu_chr_open_pp(filename);
  1595 + } else
1525 1596 if (strstart(filename, "/dev/", NULL)) {
1526 1597 return qemu_chr_open_tty(filename);
1527 1598 } else
... ...