summaryrefslogtreecommitdiff
path: root/sys/dev/isa
diff options
context:
space:
mode:
authorshawn <shawn@cvs.openbsd.org>1996-08-14 14:36:18 +0000
committershawn <shawn@cvs.openbsd.org>1996-08-14 14:36:18 +0000
commit50875c762a1e05d68dbff7bad1c348f7b166492f (patch)
tree9b92cfeed7b3226c3580314960b098fc9c71de35 /sys/dev/isa
parent87ed205c76c2e0b7a7409f1aed484310b5ba7bae (diff)
rudimentary plug-and-play support, see pnp(4)
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/files.isa12
-rw-r--r--sys/dev/isa/isa.c29
-rw-r--r--sys/dev/isa/isapnp.c1037
-rw-r--r--sys/dev/isa/isapnpreg.h93
-rw-r--r--sys/dev/isa/isapnpvar.h98
-rw-r--r--sys/dev/isa/isavar.h27
6 files changed, 1291 insertions, 5 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index f98467cb3f3..56b28effd36 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.26 1996/07/27 07:20:06 deraadt Exp $
+# $OpenBSD: files.isa,v 1.27 1996/08/14 14:36:14 shawn Exp $
# $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
@@ -11,7 +11,8 @@
device isa {[port = -1], [size = 0],
[iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1]}
+ [irq = -1], [drq = -1],
+ [pnpid = -1]}
attach isa at isabus
file dev/isa/isa.c isa needs-flag
@@ -23,6 +24,13 @@ device isadma
attach isadma at isa: isa_dma
#
+# ISA PnP capability
+#
+device isapnp
+attach isapnp at isa
+file dev/isa/isapnp.c isapnp needs-flag
+
+#
# 8250/16[45]50-based multi-port serial boards
#
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 73e4607cb77..c3c92971110 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa.c,v 1.11 1996/07/02 22:21:15 deraadt Exp $ */
+/* $OpenBSD: isa.c,v 1.12 1996/08/14 14:36:15 shawn Exp $ */
/* $NetBSD: isa.c,v 1.85 1996/05/14 00:31:04 thorpej Exp $ */
/*-
@@ -36,12 +36,15 @@
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <sys/extent.h>
#include <machine/intr.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
+#include "isapnp.h"
+
int isamatch __P((struct device *, void *, void *));
void isaattach __P((struct device *, struct device *, void *));
int isaprint __P((void *, char *));
@@ -77,6 +80,9 @@ isaattach(parent, self, aux)
{
struct isa_softc *sc = (struct isa_softc *)self;
struct isabus_attach_args *iba = aux;
+#if NISAPNP > 0
+ void postisapnpattach(struct device *, struct device *, void *);
+#endif /* NISAPNP > 0 */
isa_attach_hook(parent, self, iba);
printf("\n");
@@ -93,6 +99,10 @@ isaattach(parent, self, aux)
TAILQ_INIT(&sc->sc_subdevs);
config_scan(isascan, self);
+
+#if NISAPNP > 0
+ postisapnpattach(parent, self, aux);
+#endif /* NISAPNP > 0 */
}
int
@@ -126,6 +136,12 @@ isascan(parent, match)
struct device *dev = match;
struct cfdata *cf = dev->dv_cfdata;
struct isa_attach_args ia;
+ struct emap *io_map, *mem_map, *irq_map, *drq_map;
+
+ io_map = find_emap("io");
+ mem_map = find_emap("mem");
+ irq_map = find_emap("irq");
+ drq_map = find_emap("drq");
ia.ia_bc = sc->sc_bc;
ia.ia_ic = sc->sc_ic;
@@ -141,6 +157,10 @@ isascan(parent, match)
struct isa_attach_args ia2 = ia;
while ((*cf->cf_attach->ca_match)(parent, dev, &ia2) > 0) {
+ add_extent(io_map, ia.ia_iobase, ia.ia_iosize);
+ add_extent(mem_map, ia.ia_maddr, ia.ia_msize);
+ add_extent(irq_map, ia.ia_irq, 1);
+ add_extent(drq_map, ia.ia_drq, 1);
config_attach(parent, dev, &ia2, isaprint);
dev = config_make_softc(parent, cf);
ia2 = ia;
@@ -149,8 +169,13 @@ isascan(parent, match)
return;
}
- if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0)
+ if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0) {
+ add_extent(io_map, ia.ia_iobase, ia.ia_iosize);
+ add_extent(mem_map, ia.ia_maddr, ia.ia_msize);
+ add_extent(irq_map, ia.ia_irq, 1);
+ add_extent(drq_map, ia.ia_drq, 1);
config_attach(parent, dev, &ia, isaprint);
+ }
else
free(dev, M_DEVBUF);
}
diff --git a/sys/dev/isa/isapnp.c b/sys/dev/isa/isapnp.c
new file mode 100644
index 00000000000..b3b727812b7
--- /dev/null
+++ b/sys/dev/isa/isapnp.c
@@ -0,0 +1,1037 @@
+/* $OpenBSD: isapnp.c,v 1.1 1996/08/14 14:36:15 shawn Exp $ */
+
+/*
+ * Copyright (c) 1996, Shawn Hsiao <shawn@alpha.secc.fju.edu.tw>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Note: Most of the basic code was originally written by Sujal M. Patel,
+ * plus some code takes from his pnpinfo(8).
+ */
+/*
+ * Copyright (c) 1996, Sujal M. Patel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/extent.h>
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+
+#include "isapnpreg.h"
+#include "isapnpvar.h"
+
+#define SEND(d, r) { bus_io_write_1(sc->bc, sc->addrh, 0, d); \
+ bus_io_write_1(sc->bc, sc->wdh, 0, r); }
+
+int isapnpmatch __P((struct device *, void *, void *));
+void isapnpattach __P((struct device *, struct device *, void *));
+int isapnpprint __P((void *aux, char *pnp));
+int isapnpsubmatch __P((struct device *parent, void *match, void *aux));
+
+struct isapnp_softc {
+ struct device sc_dev;
+ struct device *parent;
+
+ bus_chipset_tag_t bc;
+ bus_io_handle_t addrh;
+ bus_io_handle_t wdh;
+ bus_io_handle_t rdh;
+ int rd_offset;
+
+ int rd_port;
+
+ TAILQ_HEAD(, cardinfo) q_card;
+};
+
+struct cfattach isapnp_ca = {
+ sizeof(struct isapnp_softc), isapnpmatch, isapnpattach
+};
+
+struct cfdriver isapnp_cd = {
+ NULL, "isapnp", DV_DULL, 1
+};
+
+static int isapnpquery __P((struct isapnp_softc *sc,
+ u_int32_t dev_id, struct isa_attach_args *ia));
+static void send_Initiation_LFSR __P((struct isapnp_softc *sc));
+static int get_serial __P((struct isapnp_softc *sc, unsigned char *data));
+static int isolation_protocol __P((struct isapnp_softc *sc));
+static void read_config __P((struct isapnp_softc *sc,
+ struct cardinfo *card, int csn));
+static int get_resource_info __P((struct isapnp_softc *sc,
+ char *buffer, int len));
+static void config_device __P((struct isapnp_softc *sc,
+ struct isa_attach_args *data));
+static int find_free_irq __P((int irq_mask));
+static int find_free_drq __P((int drq_mask));
+static int find_free_io __P((struct isapnp_softc *sc, int desc,
+ int min_addr, int max_addr, int size,
+ int alignment, int range_check));
+
+int
+isapnpmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+
+ /* sure we exist */
+ ia->ia_iosize = 0;
+ return(1);
+}
+
+void
+isapnpattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isa_softc *isc = (void *)parent;
+ struct isapnp_softc *sc = (void *)self;
+ struct isa_attach_args *ia = aux;
+ struct cardinfo *card;
+ int iobase;
+ int num_pnp_devs;
+
+ /*
+ * a reference to corresponding isapnp_softc
+ */
+ isc->pnpsc = sc;
+
+ sc->bc = ia->ia_bc;
+ sc->parent = parent;
+ TAILQ_INIT(&sc->q_card);
+
+ /*
+ * WRITE_DATA port is located at fixed offset (0x0800)
+ * from ADDRESS port,
+ * and valid READ_DATA ports are from 0x203 to 0x3ff.
+ */
+ if (bus_io_map(sc->bc, ADDRESS, 1, &(sc->addrh)) ||
+ bus_io_map(sc->bc, ADDRESS+0x0800, 1, &(sc->wdh)) ||
+ bus_io_map(sc->bc, 0x0200, 0x200, &(sc->rdh)))
+ panic("isapnpattach: io mapping failed");
+
+ printf("\n%s: Checking for ISA Plug-n-Play devices... ",
+ sc->sc_dev.dv_xname);
+
+ /* Try various READ_DATA ports from 0x203-0x3ff */
+ for (sc->rd_port = 0x80; (sc->rd_port < 0xff); sc->rd_port += 0x10) {
+ num_pnp_devs = isolation_protocol(sc);
+ if (num_pnp_devs) {
+ printf("\n%s: Plug-n-Play Read_Port at 0x%x, ",
+ sc->sc_dev.dv_xname,
+ (sc->rd_port << 2) | 0x3);
+ printf("%d devices were found\n", num_pnp_devs);
+ break;
+ }
+ }
+ if (!num_pnp_devs) {
+ printf("\n%s: No Plug-n-Play devices were found\n",
+ sc->sc_dev.dv_xname);
+ return;
+ }
+}
+
+void
+postisapnpattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct isa_softc *isc = (struct isa_softc *)self;
+ struct isapnp_softc *sc = (struct isapnp_softc *)isc->pnpsc;
+ struct isabus_attach_args *iba = aux;
+ struct cardinfo *card;
+ struct devinfo *dev;
+
+ for (card = sc->q_card.tqh_first; card;
+ card = card->card_link.tqe_next) {
+ for (dev = card->q_dev.tqh_first;
+ dev;
+ dev = dev->dev_link.tqe_next) {
+ struct isa_attach_args ia;
+
+ memset(&ia, 0, sizeof(ia));
+ ia.ia_bc = iba->iba_bc;
+ ia.ia_ic = iba->iba_ic;
+ ia.id = dev->id;
+ ia.csn = card->csn;
+ ia.ldn = dev->ldn;
+ isapnpquery(sc, ia.id, &ia);
+ if (!config_found_sm(self, &ia, isapnpprint,
+ isapnpsubmatch)) {
+ /*
+ * supplied configuration fails,
+ * disable the device.
+ */
+ SEND(WAKE, ia.csn);
+ SEND(SET_LDN, ia.ldn);
+ SEND(ACTIVATE, 0);
+ }
+ }
+ }
+}
+
+int
+isapnpprint(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+ register struct isa_attach_args *ia = aux;
+ unsigned char info[4];
+ struct emap *io_map, *mem_map, *irq_map, *drq_map;
+
+ io_map = find_emap("io");
+ mem_map = find_emap("mem");
+ irq_map = find_emap("irq");
+ drq_map = find_emap("drq");
+
+ bcopy(&ia->id, info, 4);
+ if (pnp) {
+ printf("device <%c%c%c%02x%02x> at %s",
+ ((info[0] & 0x7c) >> 2) + 64,
+ (((info[0] & 0x03) << 3) |
+ ((info[1] & 0xe0) >> 5)) + 64,
+ (info[1] & 0x1f) + 64,
+ info[2], info[3], pnp);
+ }
+ if (!pnp) {
+ if (ia->ia_iosize)
+ printf(" port 0x%x", ia->ia_iobase);
+ if (ia->ia_iosize > 1) {
+ printf("-0x%x",
+ ia->ia_iobase + ia->ia_iosize - 1);
+ add_extent(io_map, ia->ia_iobase, ia->ia_iosize);
+ }
+ if (ia->ia_msize)
+ printf(" iomem 0x%x", ia->ia_maddr);
+ if (ia->ia_msize > 1) {
+ printf("-0x%x",
+ ia->ia_maddr + ia->ia_msize - 1);
+ add_extent(mem_map, ia->ia_maddr, ia->ia_msize);
+ }
+ if (ia->ia_irq != IRQUNK) {
+ printf(" irq %d", ia->ia_irq);
+ add_extent(irq_map, ia->ia_irq, 1);
+ }
+ if (ia->ia_drq != DRQUNK) {
+ printf(" drq %d", ia->ia_drq);
+ add_extent(drq_map, ia->ia_drq, 1);
+ }
+ }
+ return(UNCONF);
+}
+
+int
+isapnpsubmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct device *dev = match;
+ struct cfdata *cf = dev->dv_cfdata;
+ struct isa_attach_args *ia = aux;
+ int ret;
+
+ if (cf->cf_pnpid == ia->id) {
+ ret = (*cf->cf_attach->ca_match)(parent, match, aux);
+ return(ret);
+ }
+
+ return(0);
+}
+
+/*
+ * given the logical device ID, return 1 if found and configured.
+ */
+int
+isapnpquery(sc, dev_id, ipa)
+ struct isapnp_softc *sc;
+ u_int32_t dev_id;
+ struct isa_attach_args *ipa;
+{
+ struct cardinfo *card;
+ struct devinfo *dev;
+ struct confinfo *conf;
+ struct isa_attach_args *tmp;
+ int irq, drq, iobase, mbase;
+ int c, i, j, fail, success;
+
+ for (card = sc->q_card.tqh_first; card;
+ card = card->card_link.tqe_next) {
+ for (dev = card->q_dev.tqh_first; dev;
+ dev = dev->dev_link.tqe_next) {
+ if (dev_id == dev->id ||
+ dev_id == dev->comp_id) {
+ tmp = malloc(sizeof(struct isa_attach_args), M_DEVBUF, M_WAITOK);
+ memset(tmp, 0, sizeof(struct isa_attach_args));
+ SEND(WAKE, card->csn);
+ SEND(SET_LDN, dev->ldn);
+
+ for (conf = dev->q_conf.tqh_first; conf;
+ conf = conf->conf_link.tqe_next) {
+ /*
+ * BASIC CONFIGURATION
+ */
+ if (conf->prio == BASIC_CONFIGURATION) {
+ if (conf->irq[0]) {
+ for (c = 0; conf->irq[c] && c < 2; c++) {
+ i = conf->irq[c]->num;
+ j = find_free_irq(i);
+ if (j) {
+ ipa->irq[c].num = j;
+ /*
+ * if the interrupt can not be configured as
+ * low true level-triggered,
+ * then set it to high true edge-triggered.
+ * XXX needs rework
+ */
+ if (conf->irq[c]->info & 0x08) {
+ ipa->irq[c].type = 0x01;
+ }
+ else {
+ ipa->irq[c].type = 0x10;
+ }
+ }
+ }
+ }
+ if (conf->dma[0]) {
+ for (c = 0; conf->dma[c] && c < 2; c++) {
+ i = conf->dma[c]->channel;
+ j = find_free_drq(i);
+ if (j) {
+ ipa->drq[c] = j;
+ }
+ }
+ }
+ if (conf->io[0]){
+ for (c = 0; conf->io[c] && c < 8; c++) {
+ ipa->port[c] = find_free_io(sc, c,
+ conf->io[c]->min_base,
+ conf->io[c]->max_base,
+ conf->io[c]->size,
+ conf->io[c]->alignment,
+ dev->io_range_check);
+ }
+ }
+ /* XXX mem */
+ if (conf->mem[0]) {
+ for (c = 0; conf->mem[c] && c < 4; c++) {
+ ipa->mem[c].base = conf->mem[c]->min_base;
+ ipa->mem[c].range = conf->mem[c]->size;
+ }
+ }
+ }
+
+ /*
+ * DEPENDENT FUNCTION
+ */
+ fail = 0; success = 1;
+ if (conf->irq[0]) {
+ for (c = 0; conf->irq[c] && c < 2; c++) {
+ i = conf->irq[c]->num;
+ j = find_free_irq(i);
+ if (j) {
+ tmp->irq[c].num = j;
+ /*
+ * if the interrupt can not be
+ * low true level-triggered,
+ * then set it to high true edge-triggered.
+ * XXX rework
+ */
+ if (conf->irq[c]->info & 0x08) {
+ tmp->irq[c].type = 0x01;
+ }
+ else {
+ tmp->irq[c].type = 0x10;
+ }
+ }
+ else {
+ fail = 1;
+ success = 0;
+ break;
+ }
+ }
+ }
+ if (conf->dma[0]) {
+ for (c = 0; conf->dma[c] && c < 2; c++) {
+ i = conf->dma[c]->channel;
+ j = find_free_drq(i);
+ if (j) {
+ tmp->drq[c] = j;
+ }
+ else {
+ fail = 1;
+ success = 0;
+ break;
+ }
+ }
+ }
+ if (conf->io[0]) {
+ for (c = 0; conf->io[c] && c < 8; c++) {
+ tmp->port[c] = find_free_io(sc, c,
+ conf->io[c]->min_base,
+ conf->io[c]->max_base,
+ conf->io[c]->size,
+ conf->io[c]->alignment,
+ dev->io_range_check);
+ if (!tmp->port[c]) {
+ fail = 1;
+ success = 0;
+ break;
+ }
+ }
+ }
+ if (conf->mem[0]) {
+ for (c = 0; conf->mem[c] && c < 4; c++) {
+ tmp->mem[c].base = conf->mem[c]->min_base;
+ tmp->mem[c].range = conf->mem[c]->size;
+
+ if (!tmp->mem[c].base) {
+ fail = 1;
+ success = 0;
+ break;
+ }
+ }
+ }
+
+ if (fail) {
+ continue;
+ }
+ }
+
+ if (!success) {
+ return(0);
+ }
+
+ for (c = 0; c < 2; c++) {
+ if (tmp->irq[c].num) {
+ ipa->irq[c].num = tmp->irq[c].num;
+ ipa->irq[c].type = tmp->irq[c].type;
+ }
+ }
+ for (c = 0; c < 8; c++) {
+ if (tmp->port[c]) {
+ ipa->port[c] = tmp->port[c];
+ }
+ }
+ for (c = 0; c < 4; c++) {
+ if (tmp->mem[c].base) {
+ ipa->mem[c].base = tmp->mem[c].base;
+ }
+ }
+ config_device(sc, ipa);
+ ipa->ia_iobase = ipa->port[0];
+ ipa->ia_irq = ipa->irq[0].num;
+ ipa->ia_drq = ipa->drq[0];
+ free(tmp, M_DEVBUF);
+ return(1);
+ }
+ }
+ }
+ return(0);
+}
+
+/*
+ * Send Initiation LFSR as described in "Plug and Play ISA Specification,
+ * Intel May 94."
+ */
+static void
+send_Initiation_LFSR(sc)
+ struct isapnp_softc *sc;
+{
+ bus_chipset_tag_t bc = sc->bc;
+ bus_io_handle_t addrh = sc->addrh;
+ int cur, i;
+
+ /* Reset the LSFR */
+ bus_io_write_1(bc, addrh, 0, 0);
+ bus_io_write_1(bc, addrh, 0, 0);
+
+ cur = 0x6a;
+ bus_io_write_1(bc, addrh, 0, cur);
+
+ for (i = 1; i < 32; i++) {
+ cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff);
+ bus_io_write_1(bc, addrh, 0, cur);
+ }
+}
+
+/*
+ * Get the device's serial number. Returns 1 if the serial is valid.
+ */
+static int
+get_serial(sc, data)
+ struct isapnp_softc *sc;
+ unsigned char *data;
+{
+ bus_chipset_tag_t bc = sc->bc;
+ bus_io_handle_t rdh = sc->rdh;
+
+ int i, bit, valid = 0, sum = 0x6a;
+
+ bzero(data, sizeof(char) * 9);
+
+ sc->rd_offset = ((sc->rd_port - 0x80) << 2) | 0x3;
+
+ for (i = 0; i < 72; i++) {
+ bit = bus_io_read_1(bc, rdh, sc->rd_offset) == 0x55;
+ delay(250); /* Delay 250 usec */
+
+ /* Can't Short Circuit the next evaluation, so 'and' is last */
+ bit = (bus_io_read_1(bc, rdh, sc->rd_offset) == 0xaa) && bit;
+ delay(250); /* Delay 250 usec */
+
+ valid = valid || bit;
+
+ if (i < 64)
+ sum = (sum >> 1) |
+ (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff);
+
+ data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0);
+ }
+
+ valid = valid && (data[8] == sum);
+
+ return valid;
+}
+
+static int
+get_resource_info(sc, buffer, len)
+ struct isapnp_softc *sc;
+ char *buffer;
+ int len;
+{
+ int i, j;
+
+ for (i = 0; i < len; i++) {
+ bus_io_write_1(sc->bc, sc->addrh, 0, STATUS);
+ for (j = 0; j < 100; j++) {
+ if ((bus_io_read_1(sc->bc, sc->rdh, sc->rd_offset))
+ & 0x1)
+ break;
+ delay(1);
+ }
+ if (j == 100) {
+ printf("%s: failed to report resource data\n",
+ sc->sc_dev.dv_xname);
+ return 0;
+ }
+ bus_io_write_1(sc->bc, sc->addrh, 0, RESOURCE_DATA);
+ buffer[i] = bus_io_read_1(sc->bc, sc->rdh, sc->rd_offset);
+ }
+ return 1;
+}
+
+/*
+ * Small Resource Tag Handler
+ *
+ * Returns 1 if checksum was valid (and an END_TAG was received).
+ * Returns -1 if checksum was invalid (and an END_TAG was received).
+ * Returns 0 for other tags.
+ *
+ * XXX checksum is ignored now ...
+ */
+static int
+handle_small_res(resinfo, item, len, card)
+ unsigned char *resinfo;
+ int item, len;
+ struct cardinfo *card;
+{
+ int i;
+
+ switch (item) {
+ case PNP_VERSION:
+ memcpy(card->pnp_version, resinfo, 2);
+ break;
+ case LOG_DEVICE_ID:
+ card->dev = malloc(sizeof(struct devinfo), M_DEVBUF, M_WAITOK);
+ bzero(card->dev, sizeof(struct devinfo));
+ TAILQ_INSERT_TAIL(&card->q_dev, card->dev, dev_link);
+ card->dev->id = *(u_int32_t *)resinfo;
+ card->dev->ldn = card->num_ld;
+ card->dev->io_range_check = resinfo[4] & 0x2 ? 1 : 0;
+ TAILQ_INIT(&card->dev->q_conf);
+
+ /*
+ * if the resource data is not enclosed in a START_DEPEND_FUNC and
+ * a END_DEPEND_FUNC, it's the basic configuration.
+ *
+ * we simple treat is as a special case.
+ */
+ card->dev->basic = malloc(sizeof(struct confinfo), M_DEVBUF, M_WAITOK);
+ TAILQ_INSERT_TAIL(&card->dev->q_conf, card->dev->basic, conf_link);
+ card->dev->basic->prio = BASIC_CONFIGURATION;
+ bzero(card->dev->basic->irq, 2*sizeof(void *));
+ bzero(card->dev->basic->dma, 2*sizeof(void *));
+ bzero(card->dev->basic->io, 8*sizeof(void *));
+ bzero(card->dev->basic->mem, 4*sizeof(void *));
+ card->dev->conf = card->dev->basic;
+
+ card->num_ld++;
+ break;
+ case COMP_DEVICE_ID:
+ card->dev->comp_id = *(u_int32_t *)resinfo;
+ break;
+ case IRQ_FORMAT:
+ for (i = 0; card->dev->conf->irq[i]; i++) ;
+ card->dev->conf->irq[i] = malloc(sizeof(struct irq_format),
+ M_DEVBUF, M_WAITOK);
+ card->dev->conf->irq[i]->num = resinfo[0] | resinfo[1] << 8;
+ if (len == 3) {
+ card->dev->conf->irq[i]->info = resinfo[2];
+ }
+ else {
+ card->dev->conf->irq[i]->info = 0;
+ }
+ break;
+ case DMA_FORMAT:
+ for (i = 0; card->dev->conf->dma[i]; i++) ;
+ card->dev->conf->dma[i] = malloc(sizeof(struct dma_format),
+ M_DEVBUF, M_WAITOK);
+ card->dev->conf->dma[i]->channel = resinfo[0];
+ card->dev->conf->dma[i]->info = resinfo[1];
+ break;
+ case START_DEPEND_FUNC:
+ card->dev->conf = malloc(sizeof(struct confinfo),
+ M_DEVBUF, M_WAITOK);
+ TAILQ_INSERT_TAIL(&card->dev->q_conf, card->dev->conf,
+ conf_link);
+ card->dev->conf->prio = ACCEPTABLE_CONFIGURATION;
+ bzero(card->dev->conf->irq, 2*sizeof(void *));
+ bzero(card->dev->conf->dma, 2*sizeof(void *));
+ bzero(card->dev->conf->io, 8*sizeof(void *));
+ bzero(card->dev->conf->mem, 4*sizeof(void *));
+
+ if (len == 1) {
+ switch (resinfo[0]) {
+ case GOOD_CONFIGURATION:
+ card->dev->conf->prio =
+ GOOD_CONFIGURATION;
+ break;
+ case ACCEPTABLE_CONFIGURATION:
+ card->dev->conf->prio =
+ ACCEPTABLE_CONFIGURATION;
+ break;
+ case SUBOPTIMAL_CONFIGURATION:
+ card->dev->conf->prio =
+ SUBOPTIMAL_CONFIGURATION;
+ break;
+ default:
+ card->dev->conf->prio =
+ RESERVED_CONFIGURATION;
+ break;
+ }
+ }
+ break;
+ case END_DEPEND_FUNC:
+ break;
+ case IO_PORT_DESC:
+ for (i = 0; card->dev->conf->io[i]; i++) ;
+ card->dev->conf->io[i] = malloc(sizeof(struct io_descriptor),
+ M_DEVBUF, M_WAITOK);
+ card->dev->conf->io[i]->type = 0; /* 0 for normal I/O desc. */
+ card->dev->conf->io[i]->info = resinfo[0];
+ card->dev->conf->io[i]->min_base =
+ resinfo[1] | resinfo[2] << 8;
+ card->dev->conf->io[i]->max_base =
+ resinfo[3] | resinfo[4] << 8;
+ card->dev->conf->io[i]->alignment = resinfo[5];
+ card->dev->conf->io[i]->size = resinfo[6];
+ break;
+ case FIXED_IO_PORT_DESC:
+ for (i = 0; card->dev->conf->io[i]; i++) ;
+ card->dev->conf->io[i] = malloc(sizeof(struct io_descriptor),
+ M_DEVBUF, M_WAITOK);
+ card->dev->conf->io[i]->type = 1; /* 1 for fixed I/O desc. */
+ card->dev->conf->io[i]->info = 0;
+ card->dev->conf->io[i]->min_base =
+ resinfo[0] | (resinfo[1] & 0x3) << 8;
+ card->dev->conf->io[i]->max_base =
+ card->dev->conf->io[i]->min_base;
+ card->dev->conf->io[i]->alignment = 0;
+ card->dev->conf->io[i]->size = resinfo[2];
+ break;
+ case END_TAG:
+ /*
+ * XXX checksum is ignored
+ */
+ return(1);
+ }
+
+ return(0);
+}
+
+static void
+handle_large_res(resinfo, item, len, card)
+ unsigned char *resinfo;
+ int item, len;
+ struct cardinfo *card;
+{
+ int i;
+
+ switch (item) {
+ case MEMORY_RANGE_DESC:
+ for (i = 0; card->dev->conf->mem[i]; i++) ;
+ card->dev->conf->mem[i] = malloc(sizeof(struct mem_descriptor),
+ M_DEVBUF, M_WAITOK);
+ card->dev->conf->mem[i]->type = 0; /* 0 for 24bit mem desc. */
+ card->dev->conf->mem[i]->info = resinfo[0];
+ card->dev->conf->mem[i]->min_base =
+ (resinfo[1] | resinfo[2] << 8) << 8;
+ card->dev->conf->mem[i]->max_base =
+ (resinfo[3] | resinfo[4] << 8) << 8;
+ card->dev->conf->mem[i]->alignment =
+ (resinfo[5] | resinfo[6] << 8);
+ if (!card->dev->conf->mem[i]->alignment)
+ card->dev->conf->mem[i]->alignment = 1 << 16;
+ card->dev->conf->mem[i]->size =
+ (resinfo[7] | resinfo[8] << 8) << 8;
+ break;
+ case ID_STRING_ANSI:
+ if (card->dev) {
+ card->dev->id_string =
+ (char *)malloc(len+1, M_DEVBUF, M_WAITOK);
+ strncpy(card->dev->id_string, resinfo, len+1);
+ card->dev->id_string[len] = '\0';
+ } else {
+ card->id_string =
+ (char *)malloc(len+1, M_DEVBUF, M_WAITOK);
+ strncpy(card->id_string, resinfo, len+1);
+ card->id_string[len] = '\0';
+ }
+ break;
+ case ID_STRING_UNICODE:
+ break;
+ case LG_VENDOR_DEFINED:
+ break;
+ case _32BIT_MEM_RANGE_DESC:
+ break;
+ case _32BIT_FIXED_LOC_DESC:
+ break;
+ case LG_RES_RESERVED:
+ break;
+ }
+}
+
+static void
+read_config(sc, card, csn)
+ struct isapnp_softc *sc;
+ struct cardinfo *card;
+ int csn;
+{
+ u_char serial[9], tag, *resinfo;
+ int i, large_len;
+
+ /*
+ * set card with csn to Config state
+ */
+ SEND(SET_CSN, csn);
+
+ /*
+ * since we are in the card isolation process, so ther's no reason
+ * to rewind and skip the first 9 bytes
+ */
+
+ /*
+ * allow up to 1KB of resource info, should be plenty */
+ for (i = 0; i < 1024; i++) {
+ if (!get_resource_info(sc, &tag, 1))
+ return;
+
+#define TYPE (tag >> 7)
+#define S_ITEM (tag >> 3)
+#define S_LEN (tag & 0x7)
+#define L_ITEM (tag & 0x7f)
+
+ if (TYPE == 0) {
+ resinfo = malloc(S_LEN, M_TEMP, M_WAITOK);
+ if (!get_resource_info(sc, resinfo, S_LEN))
+ return;
+
+ if (handle_small_res(resinfo, S_ITEM, S_LEN, card) == 1)
+ return;
+ free(resinfo, M_TEMP);
+ } else {
+ large_len = 0;
+ if (!get_resource_info(sc, (char *)&large_len, 2))
+ return;
+
+ resinfo = malloc(large_len, M_TEMP, M_WAITOK);
+ if (!get_resource_info(sc, resinfo, large_len))
+ return;
+
+ handle_large_res(resinfo, L_ITEM, large_len, card);
+ free(resinfo, M_TEMP);
+ }
+ }
+}
+
+/*
+ * Run the isolaion protocol. Use rd_port as the READ_DATA port value (caller
+ * should try multiple READ_DATA locations before giving up). Upon exiting,
+ * all cards are aware that they should use rd_port as the READ_DATA port;
+ */
+static int
+isolation_protocol(sc)
+ struct isapnp_softc *sc;
+{
+ int csn;
+ unsigned char data[9];
+
+ /* Reset CSN for All Cards */
+ SEND(CONFIG_CONTROL, 0x05);
+
+ send_Initiation_LFSR(sc);
+
+ for (csn = 1; (csn < MAX_CARDS); csn++) {
+ /* Wake up cards without a CSN */
+ SEND(WAKE, 0);
+ SEND(SET_RD_DATA, sc->rd_port);
+ bus_io_write_1(sc->bc, sc->addrh, 0, SERIAL_ISOLATION);
+ delay(1000); /* Delay 1 msec */
+
+ if (get_serial(sc, data)) {
+ struct cardinfo *card;
+
+ SEND(SET_CSN, csn);
+ card = malloc(sizeof(struct cardinfo),
+ M_DEVBUF, M_WAITOK);
+ bzero(card, sizeof(struct cardinfo));
+ TAILQ_INSERT_TAIL(&sc->q_card, card, card_link);
+ memcpy(card->serial, data, 9);
+ card->csn = csn;
+ TAILQ_INIT(&card->q_dev);
+ /*
+ * read card's resource data
+ */
+ read_config(sc, card, csn);
+ }
+ else
+ break;
+ }
+ return csn - 1;
+}
+
+/*
+ * Configure PnP devices, given a set of configuration data
+ */
+static void
+config_device(sc, data)
+ struct isapnp_softc *sc;
+ struct isa_attach_args *data;
+{
+ int i;
+
+ if (data->csn <= 0) {
+ return;
+ }
+
+#if 0
+ printf ("%s: Configuring CSN %x (Logical Device %x)\n",
+ sc->sc_dev.dv_xname,
+ data->csn,
+ data->ldn != -1 ? data->ldn : 0);
+#endif
+
+ SEND(WAKE, data->csn);
+ if (data->ldn > 0)
+ SEND (SET_LDN, data->ldn);
+
+ for (i = 0; i < 8; i++)
+ if (data->port[i] > 0) {
+ SEND (IO_CONFIG_BASE + i * 2,
+ data->port[i] >> 8);
+ SEND (IO_CONFIG_BASE + i * 2 + 1,
+ data->port[i] & 0xff);
+ }
+
+ for (i = 0; i < 2; i++)
+ if (data->irq[i].num > 0) {
+ SEND (IRQ_CONFIG + i * 2, data->irq[i].num);
+ if (data->irq[i].type >= 0)
+ SEND (IRQ_CONFIG + i * 2 + 1, data->irq[i].type);
+ }
+
+ for (i = 0; i < 2; i++)
+ if (data->drq[i] > 0) {
+ SEND (DRQ_CONFIG + i, data->drq[i]);
+ }
+
+ for (i = 0; i < 4; i++)
+ if (data->mem[i].base > 0) {
+ SEND (MEM_CONFIG + i * 8,
+ data->mem[i].base >> 16);
+ SEND (MEM_CONFIG + i * 8 + 1,
+ (data->mem[i].base >> 8) &
+ 0xff);
+ /*
+ * This needs to be handled better for
+ * the user's sake. XXX
+ */
+ if (data->mem[i].control >= 0) {
+ SEND (MEM_CONFIG + i * 8 + 2,
+ data->mem[i].control);
+ }
+ SEND (MEM_CONFIG + i * 8 + 3,
+ data->mem[i].range >> 16);
+ SEND (MEM_CONFIG + i * 8 + 4,
+ (data->mem[i].range >> 8) &
+ 0xff);
+ }
+ SEND (IO_RANGE_CHECK, 0);
+ SEND (ACTIVATE, 1);
+}
+
+static int
+find_free_irq(irq_mask)
+ int irq_mask;
+{
+ int i, j;
+ struct emap *irq_map;
+
+ irq_map = find_emap("irq");
+ i = irq_mask;
+
+ while (1) {
+ j = ffs(i);
+ if (!j) {
+ return(0);
+ }
+ /*
+ * irq_mask is starting from 0
+ */
+ j --;
+ if (!probe_extent(irq_map, j, 1)) {
+ return(j);
+ }
+ i &= ~(0x1 << j);
+ }
+}
+
+int
+find_free_drq(drq_mask)
+ int drq_mask;
+{
+ int i, j;
+ struct emap *drq_map;
+
+ drq_map = find_emap("drq");
+ i = drq_mask;
+
+ while (1) {
+ j = ffs(i);
+ if (!j) {
+ return(0);
+ }
+ /*
+ * drq_mask is starting from 0
+ */
+ j --;
+ if (!probe_extent(drq_map, j, 1)) {
+ return(j);
+ }
+ i &= ~(0x1 << j);
+ }
+}
+
+/*
+ * find free I/O space.
+ * if device is capable of doing I/O range check, then use it.
+ * else, try to find free region from extent map.
+ *
+ * assume caller has set csn and ldn properly.
+ */
+static int
+find_free_io(sc, desc, min_addr, max_addr, size, alignment, range_check)
+ struct isapnp_softc *sc;
+ int desc, min_addr, max_addr, size, alignment, range_check;
+{
+ int addr, i, success = 0;
+ bus_io_handle_t data;
+ struct emap *io_map;
+
+ if (range_check) {
+ for (addr = min_addr; addr <= max_addr; addr += alignment) {
+ SEND(ACTIVATE, 0);
+ SEND(IO_CONFIG_BASE + desc * 2, addr >> 8);
+ SEND(IO_CONFIG_BASE + desc * 2 + 1, addr & 0xff);
+ SEND(IO_RANGE_CHECK, 0x2);
+ bus_io_map(sc->bc, addr, size, &data);
+ i = 0;
+ for (i = 0; i < size; i++) {
+ if (bus_io_read_1(sc->bc, data, i) != 0xAA) {
+ bus_io_unmap(sc->bc, data, size);
+ break;
+ }
+ }
+ if (i == size) {
+ success = 1;
+ bus_io_unmap(sc->bc, data, size);
+ break;
+ }
+ }
+
+ if (success) {
+ return(addr);
+ }
+ else {
+ return(0);
+ }
+ }
+ else {
+ io_map = find_emap("io");
+ addr = min_addr;
+ if (!probe_extent(io_map, addr, size)) {
+ return(addr);
+ }
+ return(0);
+ }
+}
diff --git a/sys/dev/isa/isapnpreg.h b/sys/dev/isa/isapnpreg.h
new file mode 100644
index 00000000000..b93f2beab66
--- /dev/null
+++ b/sys/dev/isa/isapnpreg.h
@@ -0,0 +1,93 @@
+/* $OpenBSD: isapnpreg.h,v 1.1 1996/08/14 14:36:16 shawn Exp $ */
+
+/*
+ * Copyright (c) 1996, Sujal M. Patel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Sujal M. Patel
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ISA_ISAPNPREG_H_
+#define _DEV_ISA_ISAPNPREG_H_
+
+/* Maximum Number of PnP Devices. 8 should be plenty */
+#define MAX_CARDS 8
+
+
+/* Static ports */
+#define ADDRESS 0x279
+#define WRITE_DATA 0xa79
+
+
+/* PnP Registers. Write to ADDRESS and then use WRITE/READ_DATA */
+#define SET_RD_DATA 0x00
+#define SERIAL_ISOLATION 0x01
+#define CONFIG_CONTROL 0x02
+#define WAKE 0x03
+#define RESOURCE_DATA 0x04
+#define STATUS 0x05
+#define SET_CSN 0x06
+#define SET_LDN 0x07
+#define ACTIVATE 0x30
+#define IO_RANGE_CHECK 0x31
+#define MEM_CONFIG 0x40
+#define IO_CONFIG_BASE 0x60
+#define IRQ_CONFIG 0x70
+#define DRQ_CONFIG 0x74
+
+/* Small Resource Item names */
+#define PNP_VERSION 0x1
+#define LOG_DEVICE_ID 0x2
+#define COMP_DEVICE_ID 0x3
+#define IRQ_FORMAT 0x4
+#define DMA_FORMAT 0x5
+#define START_DEPEND_FUNC 0x6
+#define END_DEPEND_FUNC 0x7
+#define IO_PORT_DESC 0x8
+#define FIXED_IO_PORT_DESC 0x9
+#define SM_RES_RESERVED 0xa-0xd
+#define SM_VENDOR_DEFINED 0xe
+#define END_TAG 0xf
+
+/* Large Resource Item names */
+#define MEMORY_RANGE_DESC 0x1
+#define ID_STRING_ANSI 0x2
+#define ID_STRING_UNICODE 0x3
+#define LG_VENDOR_DEFINED 0x4
+#define _32BIT_MEM_RANGE_DESC 0x5
+#define _32BIT_FIXED_LOC_DESC 0x6
+#define LG_RES_RESERVED 0x7-0x7f
+
+/* Priority for Resource Group */
+#define BASIC_CONFIGURATION -1
+#define GOOD_CONFIGURATION 0x0
+#define ACCEPTABLE_CONFIGURATION 0x1
+#define SUBOPTIMAL_CONFIGURATION 0x2
+#define RESERVED_CONFIGURATION 0x3
+
+#endif /* !_DEV_ISA_ISAPNPREG_H_ */
diff --git a/sys/dev/isa/isapnpvar.h b/sys/dev/isa/isapnpvar.h
new file mode 100644
index 00000000000..49f5da5f5d0
--- /dev/null
+++ b/sys/dev/isa/isapnpvar.h
@@ -0,0 +1,98 @@
+/* $OpenBSD: isapnpvar.h,v 1.1 1996/08/14 14:36:16 shawn Exp $ */
+
+/*
+ * Copyright (c) 1996, Shawn Hsiao <shawn@alpha.secc.fju.edu.tw>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ISA_ISAPNPVAR_H_
+#define _DEV_ISA_ISAPNPVAR_H_
+
+struct irq_format {
+ int num; /* IRQ number */
+ int info; /* IRQ type */
+};
+
+struct dma_format {
+ int channel; /* DMA channel */
+ int info; /* DMA type */
+};
+
+struct io_descriptor {
+ int type; /* normal or fixed I/O descriptor */
+ int info; /* decoding information */
+ int min_base; /* minimum base I/O address */
+ int max_base; /* maximum base I/O address */
+ int alignment; /* alignment for base address */
+ int size; /* number of contiguous ports */
+};
+
+struct mem_descriptor {
+ int type; /* 24 or 32bit memory descriptor */
+ int info; /* misc. memory information */
+ int min_base; /* minimum base mem address */
+ int max_base; /* maximum base mem address */
+ int alignment; /* aligment for base address */
+ int size; /* number of memory range length */
+};
+
+struct confinfo {
+ int prio;
+ struct irq_format *irq[2];
+ struct dma_format *dma[2];
+ struct io_descriptor *io[8];
+ struct mem_descriptor *mem[4];
+
+ TAILQ_ENTRY(confinfo) conf_link;
+};
+
+struct devinfo {
+ u_int32_t id;
+ u_int32_t comp_id;
+ char *id_string;
+
+ int ldn;
+ int io_range_check;
+
+ TAILQ_HEAD(, confinfo) q_conf;
+ struct confinfo *conf;
+ struct confinfo *basic;
+
+ TAILQ_ENTRY(devinfo) dev_link;
+};
+
+struct cardinfo {
+ char serial[9];
+ char pnp_version[2];
+ int csn;
+ char *id_string;
+
+ int num_ld;
+
+ TAILQ_HEAD(, devinfo) q_dev;
+ struct devinfo *dev;
+ TAILQ_ENTRY(cardinfo) card_link;
+};
+
+#endif /* !_DEV_ISA_ISAPNPVAR_H_ */
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index f0459ea98d2..849c40ead19 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isavar.h,v 1.13 1996/06/22 23:18:43 pefo Exp $ */
+/* $OpenBSD: isavar.h,v 1.14 1996/08/14 14:36:17 shawn Exp $ */
/* $NetBSD: isavar.h,v 1.23 1996/05/08 23:32:31 thorpej Exp $ */
/*
@@ -96,6 +96,24 @@ struct isa_attach_args {
void *ia_aux; /* driver specific */
bus_io_handle_t ia_delayioh; /* i/o handle for `delay port' */
+
+ /* XXX need fixes, some are duplicated */
+ /* begin isapnp section */
+ int id; /* logical device ID */
+ int csn; /* card selection number */
+ int ldn; /* logical device number */
+ struct {
+ int num;
+ int type;
+ } irq[2];
+ int drq[2];
+ int port[8];
+ struct {
+ int base;
+ int control;
+ int range;
+ } mem[4];
+ /* end isapnp stuff */
};
#define IOBASEUNK -1 /* i/o address is unknown */
@@ -130,6 +148,12 @@ struct isa_softc {
* via isa_attach_args.
*/
bus_io_handle_t sc_delayioh;
+
+ /*
+ * This points to the isapnp_softc structure that holds
+ * information of PnP devices on the ISA bus.
+ */
+ void *pnpsc;
};
#define cf_iobase cf_loc[0]
@@ -138,6 +162,7 @@ struct isa_softc {
#define cf_msize cf_loc[3]
#define cf_irq cf_loc[4]
#define cf_drq cf_loc[5]
+#define cf_pnpid cf_loc[6]
/*
* ISA interrupt handler manipulation.