3 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
10 #include <hw/cpu/cpu.h>
11 #include <hw/dos/dos.h>
12 #include <hw/8250/8250.h>
13 #include <hw/isapnp/isapnp.h>
14 #include <hw/parport/parport.h>
16 static unsigned char devnode_raw[4096];
18 int is_parport_or_compat_pnp_device(struct isa_pnp_device_node far *devn) {
19 if (devn->type_code[0] == 7 && devn->type_code[1] == 1)
25 void pnp_parport_scan() {
26 /* most of the time the serial ports are BIOS controlled and on the motherboard.
27 * they usually don't even show up in a PnP isolation scan. so we have to use
28 * the "get device nodes" functions of the PnP BIOS. */
30 struct isa_pnp_device_node far *devn;
31 unsigned int ret_ax,nodesize=0xFFFF;
32 unsigned char numnodes=0xFF;
33 struct isapnp_tag tag;
36 printf("Enumerating PnP system device nodes...\n");
38 ret_ax = isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize);
39 if (ret_ax == 0 && numnodes != 0xFF && nodesize < sizeof(devnode_raw)) {
40 /* NTS: How nodes are enumerated in the PnP BIOS: set node = 0, pass address of node
41 * to BIOS. BIOS, if it returns node information, will also overwrite node with
42 * the node number of the next node, or with 0xFF if this is the last one.
43 * On the last one, stop enumerating. */
44 for (node=0;node != 0xFF;) {
45 unsigned char far *rsc;
46 int eport = -1; /* ECP port */
54 /* apparently, start with 0. call updates node to
55 * next node number, or 0xFF to signify end */
56 ret_ax = isa_pnp_bios_get_sysdev_node(&node,devnode_raw,
57 ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW);
62 devn = (struct isa_pnp_device_node far*)devnode_raw;
63 if (!is_parport_or_compat_pnp_device(devn))
66 /* there are three config blocks, one after the other.
70 * since we're not a configuration utility, we only care about the first one */
71 rsc = devnode_raw + sizeof(*devn);
72 if (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)) {
74 if (tag.tag == ISAPNP_TAG_END) /* end tag */
78 /* NTS: This code will NOT match I/O ports if they are above 0x400 because some BIOSes
79 * have ECP compliant ports and announce both the base I/O and the ECP (+0x400) I/O.
80 * We only want the base I/O */
81 /*---------------------------------------------------------------------------------*/
82 case ISAPNP_TAG_IRQ_FORMAT: {
83 struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data;
85 for (i=0;i < 16 && irq < 0;i++) {
86 if (x->irq_mask & (1U << (unsigned int)i))
90 case ISAPNP_TAG_IO_PORT: {
91 struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data;
103 case ISAPNP_TAG_FIXED_IO_PORT: {
104 struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data;
105 if (x->length >= 3) {
110 else if (eport < 0) {
116 case ISAPNP_TAG_DMA_FORMAT: {
117 struct isapnp_tag_dma_format far *x = (struct isapnp_tag_dma_format far*)tag.data;
119 for (i=0;i < 8;i++) {
120 if (x->dma_mask & (1U << (unsigned int)i))
124 /*---------------------------------------------------------------------------------*/
126 } while (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag));
135 x = port; port = eport; eport = x;
136 x = plen; plen = eplen; eplen = x;
141 if ((port+0x400) == eport)
145 /* ECP ports use a DMA channel */
149 if (plen >= 8) { /* if the I/O range is 8 long, then it might be EPP */
150 if (type == PARPORT_ECP)
151 type = PARPORT_ECP_AND_EPP;
156 if (add_pnp_parport(port,irq,dma,type))
157 printf("Found PnP port @ 0x%03x IRQ %d DMA %d assume '%s'\n",port,irq,dma,type >= 0 ? parport_type_str[type] : "?");