Commit 6508fe59e07b263a8f9afd0f5f13e6240651f42c

Authored by bellard
1 parent e5843bc8

PC parallel port support (Mark Jonckheere)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1221 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -12,6 +12,7 @@ version 0.6.2:
12 12 - initial x86_64 target support
13 13 - initial APIC support
14 14 - MMX/SSE/SSE2/PNI support
  15 + - PC parallel port support (Mark Jonckheere)
15 16  
16 17 version 0.6.1:
17 18  
... ...
Makefile.target
... ... @@ -316,7 +316,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
316 316 # Hardware support
317 317 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
318 318 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
319   -VL_OBJS+= cirrus_vga.o mixeng.o apic.o
  319 +VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
320 320 endif
321 321 ifeq ($(TARGET_ARCH), ppc)
322 322 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
... ...
hw/parallel.c 0 → 100644
  1 +/*
  2 + * QEMU Parallel PORT emulation
  3 + *
  4 + * Copyright (c) 2003-2004 Fabrice Bellard
  5 + *
  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
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +//#define DEBUG_PARALLEL
  27 +
  28 +/*
  29 + * These are the definitions for the Printer Status Register
  30 + */
  31 +#define PARA_STS_BUSY 0x80 /* Busy complement */
  32 +#define PARA_STS_ACK 0x40 /* Acknowledge */
  33 +#define PARA_STS_PAPER 0x20 /* Out of paper */
  34 +#define PARA_STS_ONLINE 0x10 /* Online */
  35 +#define PARA_STS_ERROR 0x08 /* Error complement */
  36 +
  37 +/*
  38 + * These are the definitions for the Printer Control Register
  39 + */
  40 +#define PARA_CTR_INTEN 0x10 /* IRQ Enable */
  41 +#define PARA_CTR_SELECT 0x08 /* Select In complement */
  42 +#define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
  43 +#define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
  44 +#define PARA_CTR_STROBE 0x01 /* Strobe complement */
  45 +
  46 +struct ParallelState {
  47 + uint8_t data;
  48 + uint8_t status; /* read only register */
  49 + uint8_t control;
  50 + int irq;
  51 + int irq_pending;
  52 + CharDriverState *chr;
  53 +};
  54 +
  55 +static void parallel_update_irq(ParallelState *s)
  56 +{
  57 + if (s->irq_pending)
  58 + pic_set_irq(s->irq, 1);
  59 + else
  60 + pic_set_irq(s->irq, 0);
  61 +}
  62 +
  63 +static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  64 +{
  65 + ParallelState *s = opaque;
  66 +
  67 + addr &= 7;
  68 +#ifdef DEBUG_PARALLEL
  69 + printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
  70 +#endif
  71 + switch(addr) {
  72 + case 0:
  73 + s->data = val;
  74 + parallel_update_irq(s);
  75 + break;
  76 + 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;
  91 + }
  92 + }
  93 + }
  94 + parallel_update_irq(s);
  95 + s->control = val;
  96 + break;
  97 + }
  98 +}
  99 +
  100 +static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
  101 +{
  102 + ParallelState *s = opaque;
  103 + uint32_t ret = 0xff;
  104 +
  105 + addr &= 7;
  106 + switch(addr) {
  107 + case 0:
  108 + ret = s->data;
  109 + break;
  110 + 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;
  121 + }
  122 + }
  123 + parallel_update_irq(s);
  124 + break;
  125 + case 2:
  126 + ret = s->control;
  127 + break;
  128 + }
  129 +#ifdef DEBUG_PARALLEL
  130 + printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
  131 +#endif
  132 + return ret;
  133 +}
  134 +
  135 +static int parallel_can_receive(ParallelState *s)
  136 +{
  137 + return 0;
  138 +}
  139 +
  140 +static void parallel_receive_byte(ParallelState *s, int ch)
  141 +{
  142 +}
  143 +
  144 +static void parallel_receive_break(ParallelState *s)
  145 +{
  146 +}
  147 +
  148 +static int parallel_can_receive1(void *opaque)
  149 +{
  150 + ParallelState *s = opaque;
  151 + return parallel_can_receive(s);
  152 +}
  153 +
  154 +static void parallel_receive1(void *opaque, const uint8_t *buf, int size)
  155 +{
  156 + ParallelState *s = opaque;
  157 + parallel_receive_byte(s, buf[0]);
  158 +}
  159 +
  160 +static void parallel_event(void *opaque, int event)
  161 +{
  162 + ParallelState *s = opaque;
  163 +}
  164 +
  165 +/* If fd is zero, it means that the parallel device uses the console */
  166 +ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
  167 +{
  168 + ParallelState *s;
  169 +
  170 + s = qemu_mallocz(sizeof(ParallelState));
  171 + if (!s)
  172 + return NULL;
  173 + s->irq = irq;
  174 + s->data = 0;
  175 + s->status = PARA_STS_BUSY;
  176 + s->status |= PARA_STS_ACK;
  177 + s->status |= PARA_STS_ONLINE;
  178 + s->status |= PARA_STS_ERROR;
  179 + s->control = PARA_CTR_SELECT;
  180 + s->control |= PARA_CTR_INIT;
  181 +
  182 + register_ioport_write(base, 8, 1, parallel_ioport_write, s);
  183 + register_ioport_read(base, 8, 1, parallel_ioport_read, s);
  184 + s->chr = chr;
  185 + qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s);
  186 + qemu_chr_add_event_handler(chr, parallel_event);
  187 + return s;
  188 +}
... ...
... ... @@ -376,6 +376,9 @@ static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
376 376 static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
377 377 static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
378 378  
  379 +static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
  380 +static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
  381 +
379 382 /* PC hardware initialisation */
380 383 void pc_init(int ram_size, int vga_ram_size, int boot_device,
381 384 DisplayState *ds, const char **fd_filename, int snapshot,
... ... @@ -538,6 +541,12 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
538 541 }
539 542 }
540 543  
  544 + for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
  545 + if (parallel_hds[i]) {
  546 + parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
  547 + }
  548 + }
  549 +
541 550 if (pci_enabled) {
542 551 for(i = 0; i < nb_nics; i++) {
543 552 pci_ne2000_init(pci_bus, &nd_table[i]);
... ...
... ... @@ -136,6 +136,7 @@ int graphic_depth = 15;
136 136 int full_screen = 0;
137 137 TextConsole *vga_console;
138 138 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
  139 +CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
139 140  
140 141 /***********************************************************/
141 142 /* x86 ISA bus support */
... ... @@ -2750,6 +2751,7 @@ void help(void)
2750 2751 "Debug/Expert options:\n"
2751 2752 "-monitor dev redirect the monitor to char device 'dev'\n"
2752 2753 "-serial dev redirect the serial port to char device 'dev'\n"
  2754 + "-parallel dev redirect the parallel port to char device 'dev'\n"
2753 2755 "-pidfile file Write PID to 'file'\n"
2754 2756 "-S freeze CPU at startup (use 'c' to start execution)\n"
2755 2757 "-s wait gdb connection to port %d\n"
... ... @@ -2842,6 +2844,7 @@ enum {
2842 2844 QEMU_OPTION_std_vga,
2843 2845 QEMU_OPTION_monitor,
2844 2846 QEMU_OPTION_serial,
  2847 + QEMU_OPTION_parallel,
2845 2848 QEMU_OPTION_loadvm,
2846 2849 QEMU_OPTION_full_screen,
2847 2850 QEMU_OPTION_pidfile,
... ... @@ -2904,6 +2907,7 @@ const QEMUOption qemu_options[] = {
2904 2907 { "std-vga", 0, QEMU_OPTION_std_vga },
2905 2908 { "monitor", 1, QEMU_OPTION_monitor },
2906 2909 { "serial", 1, QEMU_OPTION_serial },
  2910 + { "parallel", 1, QEMU_OPTION_parallel },
2907 2911 { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
2908 2912 { "full-screen", 0, QEMU_OPTION_full_screen },
2909 2913 { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
... ... @@ -2986,6 +2990,8 @@ int main(int argc, char **argv)
2986 2990 char monitor_device[128];
2987 2991 char serial_devices[MAX_SERIAL_PORTS][128];
2988 2992 int serial_device_index;
  2993 + char parallel_devices[MAX_PARALLEL_PORTS][128];
  2994 + int parallel_device_index;
2989 2995 const char *loadvm = NULL;
2990 2996  
2991 2997 #if !defined(CONFIG_SOFTMMU)
... ... @@ -3019,6 +3025,11 @@ int main(int argc, char **argv)
3019 3025 serial_devices[i][0] = '\0';
3020 3026 serial_device_index = 0;
3021 3027  
  3028 + pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "vc");
  3029 + for(i = 1; i < MAX_PARALLEL_PORTS; i++)
  3030 + parallel_devices[i][0] = '\0';
  3031 + parallel_device_index = 0;
  3032 +
3022 3033 nb_tun_fds = 0;
3023 3034 net_if_type = -1;
3024 3035 nb_nics = 1;
... ... @@ -3115,6 +3126,7 @@ int main(int argc, char **argv)
3115 3126 case QEMU_OPTION_nographic:
3116 3127 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
3117 3128 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
  3129 + pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "stdio");
3118 3130 nographic = 1;
3119 3131 break;
3120 3132 case QEMU_OPTION_kernel:
... ... @@ -3329,6 +3341,15 @@ int main(int argc, char **argv)
3329 3341 sizeof(serial_devices[0]), optarg);
3330 3342 serial_device_index++;
3331 3343 break;
  3344 + case QEMU_OPTION_parallel:
  3345 + if (parallel_device_index >= MAX_PARALLEL_PORTS) {
  3346 + fprintf(stderr, "qemu: too many parallel ports\n");
  3347 + exit(1);
  3348 + }
  3349 + pstrcpy(parallel_devices[parallel_device_index],
  3350 + sizeof(parallel_devices[0]), optarg);
  3351 + parallel_device_index++;
  3352 + break;
3332 3353 case QEMU_OPTION_loadvm:
3333 3354 loadvm = optarg;
3334 3355 break;
... ... @@ -3552,6 +3573,19 @@ int main(int argc, char **argv)
3552 3573 }
3553 3574 }
3554 3575  
  3576 + for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
  3577 + if (parallel_devices[i][0] != '\0') {
  3578 + parallel_hds[i] = qemu_chr_open(parallel_devices[i]);
  3579 + if (!parallel_hds[i]) {
  3580 + fprintf(stderr, "qemu: could not open parallel device '%s'\n",
  3581 + parallel_devices[i]);
  3582 + exit(1);
  3583 + }
  3584 + if (!strcmp(parallel_devices[i], "vc"))
  3585 + qemu_chr_printf(parallel_hds[i], "parallel%d console\n", i);
  3586 + }
  3587 + }
  3588 +
3555 3589 /* setup cpu signal handlers for MMU / self modifying code handling */
3556 3590 #if !defined(CONFIG_SOFTMMU)
3557 3591  
... ...
... ... @@ -224,6 +224,12 @@ void console_select(unsigned int index);
224 224  
225 225 extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
226 226  
  227 +/* parallel ports */
  228 +
  229 +#define MAX_PARALLEL_PORTS 3
  230 +
  231 +extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
  232 +
227 233 /* network redirectors support */
228 234  
229 235 #define MAX_NICS 8
... ... @@ -632,6 +638,11 @@ void rtc_set_date(RTCState *s, const struct tm *tm);
632 638 typedef struct SerialState SerialState;
633 639 SerialState *serial_init(int base, int irq, CharDriverState *chr);
634 640  
  641 +/* parallel.c */
  642 +
  643 +typedef struct ParallelState ParallelState;
  644 +ParallelState *parallel_init(int base, int irq, CharDriverState *chr);
  645 +
635 646 /* i8259.c */
636 647  
637 648 void pic_set_irq(int irq, int level);
... ...