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,6 +8,7 @@ version 0.7.3:
8 - ES1370 PCI audio device (malc) 8 - ES1370 PCI audio device (malc)
9 - Initial USB support 9 - Initial USB support
10 - Linux host serial port access 10 - Linux host serial port access
  11 + - Linux host low level parallel port access
11 12
12 version 0.7.2: 13 version 0.7.2:
13 14
hw/parallel.c
1 /* 1 /*
2 * QEMU Parallel PORT emulation 2 * QEMU Parallel PORT emulation
3 * 3 *
4 - * Copyright (c) 2003-2004 Fabrice Bellard 4 + * Copyright (c) 2003-2005 Fabrice Bellard
5 * 5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal 7 * of this software and associated documentation files (the "Software"), to deal
@@ -50,6 +50,7 @@ struct ParallelState { @@ -50,6 +50,7 @@ struct ParallelState {
50 int irq; 50 int irq;
51 int irq_pending; 51 int irq_pending;
52 CharDriverState *chr; 52 CharDriverState *chr;
  53 + int hw_driver;
53 }; 54 };
54 55
55 static void parallel_update_irq(ParallelState *s) 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,29 +71,39 @@ static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
70 #endif 71 #endif
71 switch(addr) { 72 switch(addr) {
72 case 0: 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 break; 81 break;
76 case 2: 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 break; 107 break;
97 } 108 }
98 } 109 }
@@ -105,24 +116,35 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr) @@ -105,24 +116,35 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
105 addr &= 7; 116 addr &= 7;
106 switch(addr) { 117 switch(addr) {
107 case 0: 118 case 0:
  119 + if (s->hw_driver) {
  120 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
  121 + }
108 ret = s->data; 122 ret = s->data;
109 break; 123 break;
110 case 1: 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 break; 143 break;
125 case 2: 144 case 2:
  145 + if (s->hw_driver) {
  146 + qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
  147 + }
126 ret = s->control; 148 ret = s->control;
127 break; 149 break;
128 } 150 }
@@ -153,18 +175,20 @@ static void parallel_receive1(void *opaque, const uint8_t *buf, int size) @@ -153,18 +175,20 @@ static void parallel_receive1(void *opaque, const uint8_t *buf, int size)
153 parallel_receive_byte(s, buf[0]); 175 parallel_receive_byte(s, buf[0]);
154 } 176 }
155 177
156 -static void parallel_event(void *opaque, int event)  
157 -{  
158 -}  
159 -  
160 /* If fd is zero, it means that the parallel device uses the console */ 178 /* If fd is zero, it means that the parallel device uses the console */
161 ParallelState *parallel_init(int base, int irq, CharDriverState *chr) 179 ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
162 { 180 {
163 ParallelState *s; 181 ParallelState *s;
  182 + uint8_t dummy;
164 183
165 s = qemu_mallocz(sizeof(ParallelState)); 184 s = qemu_mallocz(sizeof(ParallelState));
166 if (!s) 185 if (!s)
167 return NULL; 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 s->irq = irq; 192 s->irq = irq;
169 s->data = 0; 193 s->data = 0;
170 s->status = PARA_STS_BUSY; 194 s->status = PARA_STS_BUSY;
@@ -176,8 +200,6 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr) @@ -176,8 +200,6 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
176 200
177 register_ioport_write(base, 8, 1, parallel_ioport_write, s); 201 register_ioport_write(base, 8, 1, parallel_ioport_write, s);
178 register_ioport_read(base, 8, 1, parallel_ioport_read, s); 202 register_ioport_read(base, 8, 1, parallel_ioport_read, s);
179 - s->chr = chr;  
180 qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s); 203 qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s);
181 - qemu_chr_add_event_handler(chr, parallel_event);  
182 return s; 204 return s;
183 } 205 }
qemu-doc.texi
@@ -364,8 +364,11 @@ Virtual console @@ -364,8 +364,11 @@ Virtual console
364 @item null 364 @item null
365 void device 365 void device
366 @item /dev/XXX 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 parameters are set according to the emulated ones. 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 @item file:filename 372 @item file:filename
370 Write output to filename. No character can be read. 373 Write output to filename. No character can be read.
371 @item stdio 374 @item stdio
@@ -379,6 +382,15 @@ non graphical mode. @@ -379,6 +382,15 @@ non graphical mode.
379 This option can be used several times to simulate up to 4 serials 382 This option can be used several times to simulate up to 4 serials
380 ports. 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 @item -monitor dev 394 @item -monitor dev
383 Redirect the monitor to host device @var{dev} (same devices as the 395 Redirect the monitor to host device @var{dev} (same devices as the
384 serial port). 396 serial port).
@@ -51,6 +51,7 @@ @@ -51,6 +51,7 @@
51 #include <pty.h> 51 #include <pty.h>
52 #include <malloc.h> 52 #include <malloc.h>
53 #include <linux/rtc.h> 53 #include <linux/rtc.h>
  54 +#include <linux/ppdev.h>
54 #endif 55 #endif
55 #endif 56 #endif
56 57
@@ -1013,21 +1014,13 @@ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) @@ -1013,21 +1014,13 @@ int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
1013 return s->chr_write(s, buf, len); 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 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) 1024 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
1032 { 1025 {
1033 char buf[4096]; 1026 char buf[4096];
@@ -1379,7 +1372,11 @@ static void tty_serial_init(int fd, int speed, @@ -1379,7 +1372,11 @@ static void tty_serial_init(int fd, int speed,
1379 struct termios tty; 1372 struct termios tty;
1380 speed_t spd; 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 switch(speed) { 1381 switch(speed) {
1385 case 50: 1382 case 50:
@@ -1459,20 +1456,29 @@ static void tty_serial_init(int fd, int speed, @@ -1459,20 +1456,29 @@ static void tty_serial_init(int fd, int speed,
1459 tcsetattr (fd, TCSANOW, &tty); 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 FDCharDriver *s = chr->opaque; 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 CharDriverState *qemu_chr_open_tty(const char *filename) 1484 CharDriverState *qemu_chr_open_tty(const char *filename)
@@ -1480,7 +1486,7 @@ CharDriverState *qemu_chr_open_tty(const char *filename) @@ -1480,7 +1486,7 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
1480 CharDriverState *chr; 1486 CharDriverState *chr;
1481 int fd; 1487 int fd;
1482 1488
1483 - fd = open(filename, O_RDWR); 1489 + fd = open(filename, O_RDWR | O_NONBLOCK);
1484 if (fd < 0) 1490 if (fd < 0)
1485 return NULL; 1491 return NULL;
1486 fcntl(fd, F_SETFL, O_NONBLOCK); 1492 fcntl(fd, F_SETFL, O_NONBLOCK);
@@ -1488,8 +1494,70 @@ CharDriverState *qemu_chr_open_tty(const char *filename) @@ -1488,8 +1494,70 @@ CharDriverState *qemu_chr_open_tty(const char *filename)
1488 chr = qemu_chr_open_fd(fd, fd); 1494 chr = qemu_chr_open_fd(fd, fd);
1489 if (!chr) 1495 if (!chr)
1490 return NULL; 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 return chr; 1561 return chr;
1494 } 1562 }
1495 1563
@@ -1522,6 +1590,9 @@ CharDriverState *qemu_chr_open(const char *filename) @@ -1522,6 +1590,9 @@ CharDriverState *qemu_chr_open(const char *filename)
1522 } else 1590 } else
1523 #endif 1591 #endif
1524 #if defined(__linux__) 1592 #if defined(__linux__)
  1593 + if (strstart(filename, "/dev/parport", NULL)) {
  1594 + return qemu_chr_open_pp(filename);
  1595 + } else
1525 if (strstart(filename, "/dev/", NULL)) { 1596 if (strstart(filename, "/dev/", NULL)) {
1526 return qemu_chr_open_tty(filename); 1597 return qemu_chr_open_tty(filename);
1527 } else 1598 } else