summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>1998-09-11 07:53:59 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>1998-09-11 07:53:59 +0000
commit84653f6d81c53fefc2b1e764149dd303ee17b3c3 (patch)
tree31189913070caf9e6e9e3d0fb5dbb5703524af5f
parentfbb2fdc115860d5370e6ba3c47655fc3b1739c66 (diff)
Added support for Intel 82365SL PCIC controllers and clones from NetBSD.
-rw-r--r--sys/dev/ic/i82365.c1151
-rw-r--r--sys/dev/ic/i82365reg.h547
-rw-r--r--sys/dev/ic/i82365var.h169
3 files changed, 1643 insertions, 224 deletions
diff --git a/sys/dev/ic/i82365.c b/sys/dev/ic/i82365.c
new file mode 100644
index 00000000000..2c5a75f9f09
--- /dev/null
+++ b/sys/dev/ic/i82365.c
@@ -0,0 +1,1151 @@
+/* $OpenBSD: i82365.c,v 1.1 1998/09/11 07:53:57 fgsch Exp $ */
+/* $NetBSD: i82365.c,v 1.10 1998/06/09 07:36:55 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1997 Marc Horowitz. 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 Marc Horowitz.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+
+#include <dev/ic/i82365reg.h>
+#include <dev/ic/i82365var.h>
+
+#ifdef PCICDEBUG
+int pcic_debug = 1;
+#define DPRINTF(arg) if (pcic_debug) printf arg;
+#else
+#define DPRINTF(arg)
+#endif
+
+#define PCIC_VENDOR_UNKNOWN 0
+#define PCIC_VENDOR_I82365SLR0 1
+#define PCIC_VENDOR_I82365SLR1 2
+#define PCIC_VENDOR_CIRRUS_PD6710 3
+#define PCIC_VENDOR_CIRRUS_PD672X 4
+
+/*
+ * Individual drivers will allocate their own memory and io regions. Memory
+ * regions must be a multiple of 4k, aligned on a 4k boundary.
+ */
+
+#define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE
+
+void pcic_attach_socket __P((struct pcic_handle *));
+void pcic_init_socket __P((struct pcic_handle *));
+
+int pcic_submatch __P((struct device *, void *, void *));
+int pcic_print __P((void *arg, const char *pnp));
+int pcic_intr_socket __P((struct pcic_handle *));
+
+void pcic_attach_card __P((struct pcic_handle *));
+void pcic_detach_card __P((struct pcic_handle *));
+
+void pcic_chip_do_mem_map __P((struct pcic_handle *, int));
+void pcic_chip_do_io_map __P((struct pcic_handle *, int));
+
+static void pcic_wait_ready __P((struct pcic_handle *));
+
+struct cfdriver pcic_cd = {
+ NULL, "pcic", DV_DULL
+};
+
+int
+pcic_ident_ok(ident)
+ int ident;
+{
+ /* this is very empirical and heuristic */
+
+ if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO))
+ return (0);
+
+ if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
+#ifdef DIAGNOSTIC
+ printf("pcic: does not support memory and I/O cards, "
+ "ignored (ident=%0x)\n", ident);
+#endif
+ return (0);
+ }
+ return (1);
+}
+
+int
+pcic_vendor(h)
+ struct pcic_handle *h;
+{
+ int reg;
+
+ /*
+ * the chip_id of the cirrus toggles between 11 and 00 after a write.
+ * weird.
+ */
+
+ pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
+ reg = pcic_read(h, -1);
+
+ if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
+ PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
+ reg = pcic_read(h, -1);
+ if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
+ if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
+ return (PCIC_VENDOR_CIRRUS_PD672X);
+ else
+ return (PCIC_VENDOR_CIRRUS_PD6710);
+ }
+ }
+ /* XXX how do I identify the GD6729? */
+
+ reg = pcic_read(h, PCIC_IDENT);
+
+ if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0)
+ return (PCIC_VENDOR_I82365SLR0);
+ else
+ return (PCIC_VENDOR_I82365SLR1);
+
+ return (PCIC_VENDOR_UNKNOWN);
+}
+
+char *
+pcic_vendor_to_string(vendor)
+ int vendor;
+{
+ switch (vendor) {
+ case PCIC_VENDOR_I82365SLR0:
+ return ("Intel 82365SL Revision 0");
+ case PCIC_VENDOR_I82365SLR1:
+ return ("Intel 82365SL Revision 1");
+ case PCIC_VENDOR_CIRRUS_PD6710:
+ return ("Cirrus PD6710");
+ case PCIC_VENDOR_CIRRUS_PD672X:
+ return ("Cirrus PD672X");
+ }
+
+ return ("Unknown controller");
+}
+
+void
+pcic_attach(sc)
+ struct pcic_softc *sc;
+{
+ int vendor, count, i, reg;
+
+ /* now check for each controller/socket */
+
+ /*
+ * this could be done with a loop, but it would violate the
+ * abstraction
+ */
+
+ count = 0;
+
+ DPRINTF(("pcic ident regs:"));
+
+ sc->handle[0].sc = sc;
+ sc->handle[0].sock = C0SA;
+ if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) {
+ sc->handle[0].flags = PCIC_FLAG_SOCKETP;
+ count++;
+ } else {
+ sc->handle[0].flags = 0;
+ }
+
+ DPRINTF((" 0x%02x", reg));
+
+ sc->handle[1].sc = sc;
+ sc->handle[1].sock = C0SB;
+ if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) {
+ sc->handle[1].flags = PCIC_FLAG_SOCKETP;
+ count++;
+ } else {
+ sc->handle[1].flags = 0;
+ }
+
+ DPRINTF((" 0x%02x", reg));
+
+ sc->handle[2].sc = sc;
+ sc->handle[2].sock = C1SA;
+ if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], PCIC_IDENT))) {
+ sc->handle[2].flags = PCIC_FLAG_SOCKETP;
+ count++;
+ } else {
+ sc->handle[2].flags = 0;
+ }
+
+ DPRINTF((" 0x%02x", reg));
+
+ sc->handle[3].sc = sc;
+ sc->handle[3].sock = C1SB;
+ if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], PCIC_IDENT))) {
+ sc->handle[3].flags = PCIC_FLAG_SOCKETP;
+ count++;
+ } else {
+ sc->handle[3].flags = 0;
+ }
+
+ DPRINTF((" 0x%02x\n", reg));
+
+ if (count == 0)
+ panic("pcic_attach: attach found no sockets");
+
+ /* establish the interrupt */
+
+ /* XXX block interrupts? */
+
+ for (i = 0; i < PCIC_NSLOTS; i++) {
+#if 0
+ /*
+ * this should work, but w/o it, setting tty flags hangs at
+ * boot time.
+ */
+ if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
+#endif
+ {
+ pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
+ pcic_read(&sc->handle[i], PCIC_CSC);
+ }
+ }
+
+ if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) ||
+ (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) {
+ vendor = pcic_vendor(&sc->handle[0]);
+
+ printf("%s: controller 0 (%s) has ", sc->dev.dv_xname,
+ pcic_vendor_to_string(vendor));
+
+ if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) &&
+ (sc->handle[1].flags & PCIC_FLAG_SOCKETP))
+ printf("sockets A and B\n");
+ else if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
+ printf("socket A only\n");
+ else
+ printf("socket B only\n");
+
+ if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
+ sc->handle[0].vendor = vendor;
+ if (sc->handle[1].flags & PCIC_FLAG_SOCKETP)
+ sc->handle[1].vendor = vendor;
+ }
+ if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) ||
+ (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) {
+ vendor = pcic_vendor(&sc->handle[2]);
+
+ printf("%s: controller 1 (%s) has ", sc->dev.dv_xname,
+ pcic_vendor_to_string(vendor));
+
+ if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) &&
+ (sc->handle[3].flags & PCIC_FLAG_SOCKETP))
+ printf("sockets A and B\n");
+ else if (sc->handle[2].flags & PCIC_FLAG_SOCKETP)
+ printf("socket A only\n");
+ else
+ printf("socket B only\n");
+
+ if (sc->handle[2].flags & PCIC_FLAG_SOCKETP)
+ sc->handle[2].vendor = vendor;
+ if (sc->handle[3].flags & PCIC_FLAG_SOCKETP)
+ sc->handle[3].vendor = vendor;
+ }
+}
+
+void
+pcic_attach_sockets(sc)
+ struct pcic_softc *sc;
+{
+ int i;
+
+ for (i = 0; i < PCIC_NSLOTS; i++)
+ if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
+ pcic_attach_socket(&sc->handle[i]);
+}
+
+void
+pcic_attach_socket(h)
+ struct pcic_handle *h;
+{
+ struct pcmciabus_attach_args paa;
+
+ /* initialize the rest of the handle */
+
+ h->memalloc = 0;
+ h->ioalloc = 0;
+ h->ih_irq = 0;
+
+ /* now, config one pcmcia device per socket */
+
+ paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
+ paa.pch = (pcmcia_chipset_handle_t) h;
+ paa.iobase = h->sc->iobase;
+ paa.iosize = h->sc->iosize;
+
+ h->pcmcia = config_found_sm(&h->sc->dev, &paa, pcic_print,
+ pcic_submatch);
+
+ /* if there's actually a pcmcia device attached, initialize the slot */
+
+ if (h->pcmcia)
+ pcic_init_socket(h);
+}
+
+void
+pcic_init_socket(h)
+ struct pcic_handle *h;
+{
+ int reg;
+
+ /* set up the card to interrupt on card detect */
+
+ pcic_write(h, PCIC_CSC_INTR, (h->sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
+ PCIC_CSC_INTR_CD_ENABLE);
+ pcic_write(h, PCIC_INTR, 0);
+ pcic_read(h, PCIC_CSC);
+
+ /* unsleep the cirrus controller */
+
+ if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
+ (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
+ reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
+ if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
+ DPRINTF(("%s: socket %02x was suspended\n",
+ h->sc->dev.dv_xname, h->sock));
+ reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
+ pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
+ }
+ }
+ /* if there's a card there, then attach it. */
+
+ reg = pcic_read(h, PCIC_IF_STATUS);
+
+ if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
+ PCIC_IF_STATUS_CARDDETECT_PRESENT)
+ pcic_attach_card(h);
+}
+
+int
+pcic_submatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct cfdata *cf = match;
+ struct pcmciabus_attach_args *paa = aux;
+ struct pcic_handle *h = (struct pcic_handle *) paa->pch;
+
+ switch (h->sock) {
+ case C0SA:
+ if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
+ -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
+ cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
+ return 0;
+ if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
+ -1 /* PCICCF_SOCKET_DEFAULT */ &&
+ cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
+ return 0;
+
+ break;
+ case C0SB:
+ if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
+ -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
+ cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
+ return 0;
+ if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
+ -1 /* PCICCF_SOCKET_DEFAULT */ &&
+ cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
+ return 0;
+
+ break;
+ case C1SA:
+ if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
+ -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
+ cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
+ return 0;
+ if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
+ -1 /* PCICCF_SOCKET_DEFAULT */ &&
+ cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
+ return 0;
+
+ break;
+ case C1SB:
+ if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
+ -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
+ cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
+ return 0;
+ if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
+ -1 /* PCICCF_SOCKET_DEFAULT */ &&
+ cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
+ return 0;
+
+ break;
+ default:
+ panic("unknown pcic socket");
+ }
+
+ return ((*cf->cf_attach->ca_match)(parent, cf, aux));
+}
+
+int
+pcic_print(arg, pnp)
+ void *arg;
+ const char *pnp;
+{
+ struct pcmciabus_attach_args *paa = arg;
+ struct pcic_handle *h = (struct pcic_handle *) paa->pch;
+
+ /* Only "pcmcia"s can attach to "pcic"s... easy. */
+ if (pnp)
+ printf("pcmcia at %s", pnp);
+
+ switch (h->sock) {
+ case C0SA:
+ printf(" controller 0 socket 0");
+ break;
+ case C0SB:
+ printf(" controller 0 socket 1");
+ break;
+ case C1SA:
+ printf(" controller 1 socket 0");
+ break;
+ case C1SB:
+ printf(" controller 1 socket 1");
+ break;
+ default:
+ panic("unknown pcic socket");
+ }
+
+ return (UNCONF);
+}
+
+int
+pcic_intr(arg)
+ void *arg;
+{
+ struct pcic_softc *sc = arg;
+ int i, ret = 0;
+
+ DPRINTF(("%s: intr\n", sc->dev.dv_xname));
+
+ for (i = 0; i < PCIC_NSLOTS; i++)
+ if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
+ ret += pcic_intr_socket(&sc->handle[i]);
+
+ return (ret ? 1 : 0);
+}
+
+int
+pcic_intr_socket(h)
+ struct pcic_handle *h;
+{
+ int cscreg;
+
+ cscreg = pcic_read(h, PCIC_CSC);
+
+ cscreg &= (PCIC_CSC_GPI |
+ PCIC_CSC_CD |
+ PCIC_CSC_READY |
+ PCIC_CSC_BATTWARN |
+ PCIC_CSC_BATTDEAD);
+
+ if (cscreg & PCIC_CSC_GPI) {
+ DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
+ }
+ if (cscreg & PCIC_CSC_CD) {
+ int statreg;
+
+ statreg = pcic_read(h, PCIC_IF_STATUS);
+
+ DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
+ statreg));
+
+ /*
+ * XXX This should probably schedule something to happen
+ * after the interrupt handler completes
+ */
+
+ if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
+ PCIC_IF_STATUS_CARDDETECT_PRESENT) {
+ if (!(h->flags & PCIC_FLAG_CARDP))
+ pcic_attach_card(h);
+ } else {
+ if (h->flags & PCIC_FLAG_CARDP)
+ pcic_detach_card(h);
+ }
+ }
+ if (cscreg & PCIC_CSC_READY) {
+ DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
+ /* shouldn't happen */
+ }
+ if (cscreg & PCIC_CSC_BATTWARN) {
+ DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
+ }
+ if (cscreg & PCIC_CSC_BATTDEAD) {
+ DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
+ }
+ return (cscreg ? 1 : 0);
+}
+
+void
+pcic_attach_card(h)
+ struct pcic_handle *h;
+{
+ if (h->flags & PCIC_FLAG_CARDP)
+ panic("pcic_attach_card: already attached");
+
+ /* call the MI attach function */
+
+ pcmcia_card_attach(h->pcmcia);
+
+ h->flags |= PCIC_FLAG_CARDP;
+}
+
+void
+pcic_detach_card(h)
+ struct pcic_handle *h;
+{
+ if (!(h->flags & PCIC_FLAG_CARDP))
+ panic("pcic_attach_card: already detached");
+
+ h->flags &= ~PCIC_FLAG_CARDP;
+
+ /* call the MI attach function */
+
+ pcmcia_card_detach(h->pcmcia);
+
+ /* disable card detect resume and configuration reset */
+
+ /* power down the socket */
+
+ pcic_write(h, PCIC_PWRCTL, 0);
+
+ /* reset the card */
+
+ pcic_write(h, PCIC_INTR, 0);
+}
+
+int
+pcic_chip_mem_alloc(pch, size, pcmhp)
+ pcmcia_chipset_handle_t pch;
+ bus_size_t size;
+ struct pcmcia_mem_handle *pcmhp;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ bus_space_handle_t memh;
+ bus_addr_t addr;
+ bus_size_t sizepg;
+ int i, mask, mhandle;
+
+ /* out of sc->memh, allocate as many pages as necessary */
+
+ /* convert size to PCIC pages */
+ sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
+
+ mask = (1 << sizepg) - 1;
+
+ addr = 0; /* XXX gcc -Wuninitialized */
+ mhandle = 0; /* XXX gcc -Wuninitialized */
+
+ for (i = 0; i < (PCIC_MEM_PAGES + 1 - sizepg); i++) {
+ if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
+ if (bus_space_subregion(h->sc->memt, h->sc->memh,
+ i * PCIC_MEM_PAGESIZE,
+ sizepg * PCIC_MEM_PAGESIZE, &memh))
+ return (1);
+ mhandle = mask << i;
+ addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE);
+ h->sc->subregionmask &= ~(mhandle);
+ break;
+ }
+ }
+
+ if (i == (PCIC_MEM_PAGES + 1 - size))
+ return (1);
+
+ DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long) addr,
+ (u_long) size));
+
+ pcmhp->memt = h->sc->memt;
+ pcmhp->memh = memh;
+ pcmhp->addr = addr;
+ pcmhp->size = size;
+ pcmhp->mhandle = mhandle;
+ pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
+
+ return (0);
+}
+
+void
+pcic_chip_mem_free(pch, pcmhp)
+ pcmcia_chipset_handle_t pch;
+ struct pcmcia_mem_handle *pcmhp;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+
+ h->sc->subregionmask |= pcmhp->mhandle;
+}
+
+static struct mem_map_index_st {
+ int sysmem_start_lsb;
+ int sysmem_start_msb;
+ int sysmem_stop_lsb;
+ int sysmem_stop_msb;
+ int cardmem_lsb;
+ int cardmem_msb;
+ int memenable;
+} mem_map_index[] = {
+ {
+ PCIC_SYSMEM_ADDR0_START_LSB,
+ PCIC_SYSMEM_ADDR0_START_MSB,
+ PCIC_SYSMEM_ADDR0_STOP_LSB,
+ PCIC_SYSMEM_ADDR0_STOP_MSB,
+ PCIC_CARDMEM_ADDR0_LSB,
+ PCIC_CARDMEM_ADDR0_MSB,
+ PCIC_ADDRWIN_ENABLE_MEM0,
+ },
+ {
+ PCIC_SYSMEM_ADDR1_START_LSB,
+ PCIC_SYSMEM_ADDR1_START_MSB,
+ PCIC_SYSMEM_ADDR1_STOP_LSB,
+ PCIC_SYSMEM_ADDR1_STOP_MSB,
+ PCIC_CARDMEM_ADDR1_LSB,
+ PCIC_CARDMEM_ADDR1_MSB,
+ PCIC_ADDRWIN_ENABLE_MEM1,
+ },
+ {
+ PCIC_SYSMEM_ADDR2_START_LSB,
+ PCIC_SYSMEM_ADDR2_START_MSB,
+ PCIC_SYSMEM_ADDR2_STOP_LSB,
+ PCIC_SYSMEM_ADDR2_STOP_MSB,
+ PCIC_CARDMEM_ADDR2_LSB,
+ PCIC_CARDMEM_ADDR2_MSB,
+ PCIC_ADDRWIN_ENABLE_MEM2,
+ },
+ {
+ PCIC_SYSMEM_ADDR3_START_LSB,
+ PCIC_SYSMEM_ADDR3_START_MSB,
+ PCIC_SYSMEM_ADDR3_STOP_LSB,
+ PCIC_SYSMEM_ADDR3_STOP_MSB,
+ PCIC_CARDMEM_ADDR3_LSB,
+ PCIC_CARDMEM_ADDR3_MSB,
+ PCIC_ADDRWIN_ENABLE_MEM3,
+ },
+ {
+ PCIC_SYSMEM_ADDR4_START_LSB,
+ PCIC_SYSMEM_ADDR4_START_MSB,
+ PCIC_SYSMEM_ADDR4_STOP_LSB,
+ PCIC_SYSMEM_ADDR4_STOP_MSB,
+ PCIC_CARDMEM_ADDR4_LSB,
+ PCIC_CARDMEM_ADDR4_MSB,
+ PCIC_ADDRWIN_ENABLE_MEM4,
+ },
+};
+
+void
+pcic_chip_do_mem_map(h, win)
+ struct pcic_handle *h;
+ int win;
+{
+ int reg;
+
+ pcic_write(h, mem_map_index[win].sysmem_start_lsb,
+ (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
+ pcic_write(h, mem_map_index[win].sysmem_start_msb,
+ ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
+ PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
+
+#if 0
+ /* XXX do I want 16 bit all the time? */
+ PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT;
+#endif
+
+ pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
+ ((h->mem[win].addr + h->mem[win].size) >>
+ PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
+ pcic_write(h, mem_map_index[win].sysmem_stop_msb,
+ (((h->mem[win].addr + h->mem[win].size) >>
+ (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
+ PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
+ PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
+
+ pcic_write(h, mem_map_index[win].cardmem_lsb,
+ (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
+ pcic_write(h, mem_map_index[win].cardmem_msb,
+ ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
+ PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
+ ((h->mem[win].kind == PCMCIA_MEM_ATTR) ?
+ PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
+
+ reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
+ reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16);
+ pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
+
+#ifdef PCICDEBUG
+ {
+ int r1, r2, r3, r4, r5, r6;
+
+ r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
+ r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
+ r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
+ r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
+ r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
+ r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
+
+ DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x "
+ "%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
+ }
+#endif
+}
+
+int
+pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
+ pcmcia_chipset_handle_t pch;
+ int kind;
+ bus_addr_t card_addr;
+ bus_size_t size;
+ struct pcmcia_mem_handle *pcmhp;
+ bus_addr_t *offsetp;
+ int *windowp;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ bus_addr_t busaddr;
+ long card_offset;
+ int i, win;
+
+ win = -1;
+ for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0]));
+ i++) {
+ if ((h->memalloc & (1 << i)) == 0) {
+ win = i;
+ h->memalloc |= (1 << i);
+ break;
+ }
+ }
+
+ if (win == -1)
+ return (1);
+
+ *windowp = win;
+
+ /* XXX this is pretty gross */
+
+ if (h->sc->memt != pcmhp->memt)
+ panic("pcic_chip_mem_map memt is bogus");
+
+ busaddr = pcmhp->addr;
+
+ /*
+ * compute the address offset to the pcmcia address space for the
+ * pcic. this is intentionally signed. The masks and shifts below
+ * will cause TRT to happen in the pcic registers. Deal with making
+ * sure the address is aligned, and return the alignment offset.
+ */
+
+ *offsetp = card_addr % PCIC_MEM_ALIGN;
+ card_addr -= *offsetp;
+
+ DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
+ "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
+ (u_long) card_addr));
+
+ /*
+ * include the offset in the size, and decrement size by one, since
+ * the hw wants start/stop
+ */
+ size += *offsetp - 1;
+
+ card_offset = (((long) card_addr) - ((long) busaddr));
+
+ h->mem[win].addr = busaddr;
+ h->mem[win].size = size;
+ h->mem[win].offset = card_offset;
+ h->mem[win].kind = kind;
+
+ pcic_chip_do_mem_map(h, win);
+
+ return (0);
+}
+
+void
+pcic_chip_mem_unmap(pch, window)
+ pcmcia_chipset_handle_t pch;
+ int window;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ int reg;
+
+ if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0])))
+ panic("pcic_chip_mem_unmap: window out of range");
+
+ reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
+ reg &= ~mem_map_index[window].memenable;
+ pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
+
+ h->memalloc &= ~(1 << window);
+}
+
+int
+pcic_chip_io_alloc(pch, start, size, align, pcihp)
+ pcmcia_chipset_handle_t pch;
+ bus_addr_t start;
+ bus_size_t size;
+ bus_size_t align;
+ struct pcmcia_io_handle *pcihp;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_addr_t ioaddr;
+ int flags = 0;
+
+ /*
+ * Allocate some arbitrary I/O space.
+ */
+
+ iot = h->sc->iot;
+
+ if (start) {
+ ioaddr = start;
+ if (bus_space_map(iot, start, size, 0, &ioh))
+ return (1);
+ DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
+ (u_long) ioaddr, (u_long) size));
+ } else {
+ flags |= PCMCIA_IO_ALLOCATED;
+ if (bus_space_alloc(iot, h->sc->iobase,
+ h->sc->iobase + h->sc->iosize, size, align, 0, 0,
+ &ioaddr, &ioh))
+ return (1);
+ DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
+ (u_long) ioaddr, (u_long) size));
+ }
+
+ pcihp->iot = iot;
+ pcihp->ioh = ioh;
+ pcihp->addr = ioaddr;
+ pcihp->size = size;
+ pcihp->flags = flags;
+
+ return (0);
+}
+
+void
+pcic_chip_io_free(pch, pcihp)
+ pcmcia_chipset_handle_t pch;
+ struct pcmcia_io_handle *pcihp;
+{
+ bus_space_tag_t iot = pcihp->iot;
+ bus_space_handle_t ioh = pcihp->ioh;
+ bus_size_t size = pcihp->size;
+
+ if (pcihp->flags & PCMCIA_IO_ALLOCATED)
+ bus_space_free(iot, ioh, size);
+ else
+ bus_space_unmap(iot, ioh, size);
+}
+
+
+static struct io_map_index_st {
+ int start_lsb;
+ int start_msb;
+ int stop_lsb;
+ int stop_msb;
+ int ioenable;
+ int ioctlmask;
+ int ioctlbits[3]; /* indexed by PCMCIA_WIDTH_* */
+} io_map_index[] = {
+ {
+ PCIC_IOADDR0_START_LSB,
+ PCIC_IOADDR0_START_MSB,
+ PCIC_IOADDR0_STOP_LSB,
+ PCIC_IOADDR0_STOP_MSB,
+ PCIC_ADDRWIN_ENABLE_IO0,
+ PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
+ PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
+ {
+ PCIC_IOCTL_IO0_IOCS16SRC_CARD,
+ PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
+ PCIC_IOCTL_IO0_DATASIZE_8BIT,
+ PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
+ PCIC_IOCTL_IO0_DATASIZE_16BIT,
+ },
+ },
+ {
+ PCIC_IOADDR1_START_LSB,
+ PCIC_IOADDR1_START_MSB,
+ PCIC_IOADDR1_STOP_LSB,
+ PCIC_IOADDR1_STOP_MSB,
+ PCIC_ADDRWIN_ENABLE_IO1,
+ PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
+ PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
+ {
+ PCIC_IOCTL_IO1_IOCS16SRC_CARD,
+ PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
+ PCIC_IOCTL_IO1_DATASIZE_8BIT,
+ PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
+ PCIC_IOCTL_IO1_DATASIZE_16BIT,
+ },
+ },
+};
+
+void
+pcic_chip_do_io_map(h, win)
+ struct pcic_handle *h;
+ int win;
+{
+ int reg;
+
+ DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
+ win, (long) h->io[win].addr, (long) h->io[win].size,
+ h->io[win].width * 8));
+
+ pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff);
+ pcic_write(h, io_map_index[win].start_msb,
+ (h->io[win].addr >> 8) & 0xff);
+
+ pcic_write(h, io_map_index[win].stop_lsb,
+ (h->io[win].addr + h->io[win].size - 1) & 0xff);
+ pcic_write(h, io_map_index[win].stop_msb,
+ ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff);
+
+ reg = pcic_read(h, PCIC_IOCTL);
+ reg &= ~io_map_index[win].ioctlmask;
+ reg |= io_map_index[win].ioctlbits[h->io[win].width];
+ pcic_write(h, PCIC_IOCTL, reg);
+
+ reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
+ reg |= io_map_index[win].ioenable;
+ pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
+}
+
+int
+pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
+ pcmcia_chipset_handle_t pch;
+ int width;
+ bus_addr_t offset;
+ bus_size_t size;
+ struct pcmcia_io_handle *pcihp;
+ int *windowp;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ bus_addr_t ioaddr = pcihp->addr + offset;
+ int i, win;
+#ifdef PCICDEBUG
+ static char *width_names[] = { "auto", "io8", "io16" };
+#endif
+
+ /* XXX Sanity check offset/size. */
+
+ win = -1;
+ for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) {
+ if ((h->ioalloc & (1 << i)) == 0) {
+ win = i;
+ h->ioalloc |= (1 << i);
+ break;
+ }
+ }
+
+ if (win == -1)
+ return (1);
+
+ *windowp = win;
+
+ /* XXX this is pretty gross */
+
+ if (h->sc->iot != pcihp->iot)
+ panic("pcic_chip_io_map iot is bogus");
+
+ DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
+ win, width_names[width], (u_long) ioaddr, (u_long) size));
+
+ /* XXX wtf is this doing here? */
+
+ printf(" port 0x%lx", (u_long) ioaddr);
+ if (size > 1)
+ printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
+
+ h->io[win].addr = ioaddr;
+ h->io[win].size = size;
+ h->io[win].width = width;
+
+ pcic_chip_do_io_map(h, win);
+
+ return (0);
+}
+
+void
+pcic_chip_io_unmap(pch, window)
+ pcmcia_chipset_handle_t pch;
+ int window;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ int reg;
+
+ if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0])))
+ panic("pcic_chip_io_unmap: window out of range");
+
+ reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
+ reg &= ~io_map_index[window].ioenable;
+ pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
+
+ h->ioalloc &= ~(1 << window);
+}
+
+static void
+pcic_wait_ready(h)
+ struct pcic_handle *h;
+{
+ int i;
+
+ for (i = 0; i < 10000; i++) {
+ if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
+ return;
+ delay(500);
+#ifdef PCICDEBUG
+ if (pcic_debug) {
+ if ((i>5000) && (i%100 == 99))
+ printf(".");
+ }
+#endif
+ }
+
+#ifdef DIAGNOSTIC
+ printf("pcic_wait_ready ready never happened\n");
+#endif
+}
+
+void
+pcic_chip_socket_enable(pch)
+ pcmcia_chipset_handle_t pch;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+ int cardtype, reg, win;
+
+ /* this bit is mostly stolen from pcic_attach_card */
+
+ /* power down the socket to reset it, clear the card reset pin */
+
+ pcic_write(h, PCIC_PWRCTL, 0);
+
+ /*
+ * wait 300ms until power fails (Tpf). Then, wait 100ms since
+ * we are changing Vcc (Toff).
+ */
+ delay((300 + 100) * 1000);
+
+ /* power up the socket */
+
+ pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE);
+
+ /*
+ * wait 100ms until power raise (Tpr) and 20ms to become
+ * stable (Tsu(Vcc)).
+ */
+ delay((100 + 20) * 1000);
+
+ pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_OE);
+
+#if 0
+ /*
+ * hold RESET at least 10us.
+ */
+ delay(10);
+#else
+ /*
+ * at least one card i've tested needs this. -fgsch
+ */
+ delay(250 * 1000);
+#endif
+
+ /* clear the reset flag */
+
+ pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
+
+ /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
+
+ delay(20000);
+
+ /* wait for the chip to finish initializing */
+
+ pcic_wait_ready(h);
+
+ /* zero out the address windows */
+
+ pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
+
+ /* set the card type */
+
+ cardtype = pcmcia_card_gettype(h->pcmcia);
+
+ reg = pcic_read(h, PCIC_INTR);
+ reg &= ~PCIC_INTR_CARDTYPE_MASK;
+ reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
+ PCIC_INTR_CARDTYPE_IO :
+ PCIC_INTR_CARDTYPE_MEM);
+ reg |= h->ih_irq;
+ pcic_write(h, PCIC_INTR, reg);
+
+ DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
+ h->sc->dev.dv_xname, h->sock,
+ ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
+
+ /* reinstall all the memory and io mappings */
+
+ for (win = 0; win < PCIC_MEM_WINS; win++)
+ if (h->memalloc & (1 << win))
+ pcic_chip_do_mem_map(h, win);
+
+ for (win = 0; win < PCIC_IO_WINS; win++)
+ if (h->ioalloc & (1 << win))
+ pcic_chip_do_io_map(h, win);
+}
+
+void
+pcic_chip_socket_disable(pch)
+ pcmcia_chipset_handle_t pch;
+{
+ struct pcic_handle *h = (struct pcic_handle *) pch;
+
+ DPRINTF(("pcic_chip_socket_disable\n"));
+
+ /* power down the socket */
+
+ pcic_write(h, PCIC_PWRCTL, 0);
+
+ /*
+ * wait 300ms until power fails (Tpf).
+ */
+ delay(300 * 1000);
+}
diff --git a/sys/dev/ic/i82365reg.h b/sys/dev/ic/i82365reg.h
index d574d332d8d..e9daa79c6a2 100644
--- a/sys/dev/ic/i82365reg.h
+++ b/sys/dev/ic/i82365reg.h
@@ -1,234 +1,333 @@
-/* $OpenBSD: i82365reg.h,v 1.4 1996/10/31 01:01:31 niklas Exp $ */
+/* $OpenBSD: i82365reg.h,v 1.5 1998/09/11 07:53:57 fgsch Exp $ */
+/* $NetBSD: i82365reg.h,v 1.2 1997/10/16 23:18:18 thorpej Exp $ */
-#ifndef __82365_H__
-#define __82365_H__
-
-/***********************************************************************
- * 82365.h -- information necessary for direct manipulation of PCMCIA
- * cards and controllers
+/*
+ * Copyright (c) 1997 Marc Horowitz. All rights reserved.
*
- * Support is included for Intel 82365SL PCIC controllers and clones
- * thereof.
+ * 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 Marc Horowitz.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- ***********************************************************************/
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
/*
- * data structures used to store information about PCIC sockets and
- * PCMCIA cards, and functions to manipulate them
+ * All information is from the intel 82365sl PC Card Interface Controller
+ * (PCIC) data sheet, marked "preliminary". Order number 290423-002, January
+ * 1993.
*/
-#define MAX_CONFIGS 12 /* config table entries */
-#define MAX_IOADDRS 2 /* i/o port ranges */
-#define MAX_MEMS 4 /* memory ranges */
-#define MAX_SOCKS 8 /* pcic sockets */
+
+#define PCIC_IOSIZE 2
+
+#define PCIC_REG_INDEX 0
+#define PCIC_REG_DATA 1
/*
- * PCIC Registers
- * Each register is given a name, and most of the bits are named too.
- * I should really name them all.
- *
- * Finally, since the banks can be addressed with a regular syntax,
- * some macros are provided for that purpose.
+ * The PCIC allows two chips to share the same address. In order not to run
+ * afoul of the netbsd device model, this driver will treat those chips as
+ * the same device.
*/
-#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */
-#define PCIC_NPORTS 2 /* pcic takes 2 ports */
-
-/* First, all the registers */
-#define PCIC_ID_REV 0x00 /* Identification and Revision */
-#define PCIC_STATUS 0x01 /* Interface Status */
-#define PCIC_POWER 0x02 /* Power and RESETDRV control */
-#define PCIC_INT_GEN 0x03 /* Interrupt and General Control */
-#define PCIC_STAT_CHG 0x04 /* Card Status Change */
-#define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */
-#define PCIC_ADDRWINE 0x06 /* Address Window Enable */
-#define PCIC_IOCTL 0x07 /* I/O Control */
-#define PCIC_IO0_STL 0x08 /* I/O Address 0 Start Low Byte */
-#define PCIC_IO0_STH 0x09 /* I/O Address 0 Start High Byte */
-#define PCIC_IO0_SPL 0x0a /* I/O Address 0 Stop Low Byte */
-#define PCIC_IO0_SPH 0x0b /* I/O Address 0 Stop High Byte */
-#define PCIC_IO1_STL 0x0c /* I/O Address 1 Start Low Byte */
-#define PCIC_IO1_STH 0x0d /* I/O Address 1 Start High Byte */
-#define PCIC_IO1_SPL 0x0e /* I/O Address 1 Stop Low Byte */
-#define PCIC_IO1_SPH 0x0f /* I/O Address 1 Stop High Byte */
-#define PCIC_SM0_STL 0x10 /* System Memory Address 0 Mapping Start Low Byte */
-#define PCIC_SM0_STH 0x11 /* System Memory Address 0 Mapping Start High Byte */
-#define PCIC_SM0_SPL 0x12 /* System Memory Address 0 Mapping Stop Low Byte */
-#define PCIC_SM0_SPH 0x13 /* System Memory Address 0 Mapping Stop High Byte */
-#define PCIC_CM0_L 0x14 /* Card Memory Offset Address 0 Low Byte */
-#define PCIC_CM0_H 0x15 /* Card Memory Offset Address 0 High Byte */
-#define PCIC_CDGC 0x16 /* Card Detect and General Control */
-#define PCIC_RES17 0x17 /* Reserved */
-#define PCIC_SM1_STL 0x18 /* System Memory Address 1 Mapping Start Low Byte */
-#define PCIC_SM1_STH 0x19 /* System Memory Address 1 Mapping Start High Byte */
-#define PCIC_SM1_SPL 0x1a /* System Memory Address 1 Mapping Stop Low Byte */
-#define PCIC_SM1_SPH 0x1b /* System Memory Address 1 Mapping Stop High Byte */
-#define PCIC_CM1_L 0x1c /* Card Memory Offset Address 1 Low Byte */
-#define PCIC_CM1_H 0x1d /* Card Memory Offset Address 1 High Byte */
-#define PCIC_RES1E 0x1e /* Reserved */
-#define PCIC_RES1F 0x1f /* Reserved */
-#define PCIC_SM2_STL 0x20 /* System Memory Address 2 Mapping Start Low Byte */
-#define PCIC_SM2_STH 0x21 /* System Memory Address 2 Mapping Start High Byte */
-#define PCIC_SM2_SPL 0x22 /* System Memory Address 2 Mapping Stop Low Byte */
-#define PCIC_SM2_SPH 0x23 /* System Memory Address 2 Mapping Stop High Byte */
-#define PCIC_CM2_L 0x24 /* Card Memory Offset Address 2 Low Byte */
-#define PCIC_CM2_H 0x25 /* Card Memory Offset Address 2 High Byte */
-#define PCIC_RES26 0x26 /* Reserved */
-#define PCIC_RES27 0x27 /* Reserved */
-#define PCIC_SM3_STL 0x28 /* System Memory Address 3 Mapping Start Low Byte */
-#define PCIC_SM3_STH 0x29 /* System Memory Address 3 Mapping Start High Byte */
-#define PCIC_SM3_SPL 0x2a /* System Memory Address 3 Mapping Stop Low Byte */
-#define PCIC_SM3_SPH 0x2b /* System Memory Address 3 Mapping Stop High Byte */
-#define PCIC_CM3_L 0x2c /* Card Memory Offset Address 3 Low Byte */
-#define PCIC_CM3_H 0x2d /* Card Memory Offset Address 3 High Byte */
-#define PCIC_RES2E 0x2e /* Reserved */
-#define PCIC_RES2F 0x2f /* Reserved */
-#define PCIC_SM4_STL 0x30 /* System Memory Address 4 Mapping Start Low Byte */
-#define PCIC_SM4_STH 0x31 /* System Memory Address 4 Mapping Start High Byte */
-#define PCIC_SM4_SPL 0x32 /* System Memory Address 4 Mapping Stop Low Byte */
-#define PCIC_SM4_SPH 0x33 /* System Memory Address 4 Mapping Stop High Byte */
-#define PCIC_CM4_L 0x34 /* Card Memory Offset Address 4 Low Byte */
-#define PCIC_CM4_H 0x35 /* Card Memory Offset Address 4 High Byte */
-#define PCIC_RES36 0x36 /* Reserved */
-#define PCIC_RES37 0x37 /* Reserved */
-#define PCIC_RES38 0x38 /* Reserved */
-#define PCIC_RES39 0x39 /* Reserved */
-#define PCIC_RES3A 0x3a /* Reserved */
-#define PCIC_RES3B 0x3b /* Reserved */
-#define PCIC_RES3C 0x3c /* Reserved */
-#define PCIC_RES3D 0x3d /* Reserved */
-#define PCIC_RES3E 0x3e /* Reserved */
-#define PCIC_RES3F 0x3f /* Reserved */
-
-#define PCIC_STATUSBITS \
- "\020\010VPP\07POWER\06READY\05WPROT\04DET1\03DET2\02VOL1\01VOL2"
-
-/* Now register bits, ordered by reg # */
-
-/* For Identification and Revision (PCIC_ID_REV) */
-#define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */
-#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */
-#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */
-#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */
-#define PCIC_146FC6 0x84 /* VL82C146FC6; Both Memory and I/O */
-#define PCIC_146FC7 0x85 /* VL82C146FC7; Both Memory and I/O */
-
-/* For Interface Status register (PCIC_STATUS) */
-#define PCIC_VPPV 0x80 /* Vpp_valid */
-#define PCIC_POW 0x40 /* PC Card power active */
-#define PCIC_READY 0x20 /* Ready/~Busy */
-#define PCIC_MWP 0x10 /* Memory Write Protect */
-#define PCIC_CD 0x0C /* Both card detect bits */
-#define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */
-
-/* For the Power and RESETDRV register (PCIC_POWER) */
-#define PCIC_OUTENA 0x80 /* Output Enable */
-#define PCIC_DISRST 0x40 /* Disable RESETDRV */
-#define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */
-#define PCIC_VCC5V 0x10 /* PC Card Power 5V Enable */
-#define PCIC_VCC3V 0x08 /* PC Card Power 3V Enable */
-#define PCIC_VPP12V 0x02 /* PC Card Power VPP 12V Enable */
-#define PCIC_VPP5V 0x01 /* PC Card Power VPP 5V Enable */
-
-/* For the Interrupt and General Control register (PCIC_INT_GEN) */
-#define PCIC_INT_MASK 0x0f
-#define PCIC_INT_FLAGMASK 0x0f
-#define PCIC_INTR_ENA 0x10 /* clr bit means CSC interrupt goes via IRQ */
-#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */
-#define PCIC_IOCARD 0x20
-#define PCIC_MEMCARD 0x00
-#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */
-#define PCIC_RINGIND 0x80
-
-/* For the Card Status Change register (PCIC_STAT_CHG) */
-#define PCIC_GPICH 0x10 /* General Purpose Input (GPI) Change */
-#define PCIC_CDTCH 0x08 /* Card Detect Change */
-#define PCIC_RDYCH 0x04 /* Ready Change */
-#define PCIC_BATWRN 0x02 /* Battery Warning */
-#define PCIC_BATDED 0x01 /* Battery Dead */
-#define PCIC_STCH 0x01 /* Status Change */
-
-/* For the Card Status Change interrupt config register (PCIC_STAT_INT) */
-#define PCIC_CDT_ENA 0x08 /* Card Detect Enable */
-#define PCIC_RDY_ENA 0x04 /* Ready Enable */
-#define PCIC_BATWRN_ENA 0x02 /* Battery Warning */
-#define PCIC_BATDED_ENA 0x01 /* Battery Dead */
-#define PCIC_ST_ENA 0x01 /* Status Change */
-
-/* For the Address Window Enable Register (PCIC_ADDRWINE) */
-#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */
-#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */
-#define PCIC_SM2_EN 0x04 /* Memory Window 2 Enable */
-#define PCIC_SM3_EN 0x08 /* Memory Window 3 Enable */
-#define PCIC_SM4_EN 0x10 /* Memory Window 4 Enable */
-#define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */
-#define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */
-#define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */
-
-/* For the I/O Control Register (PCIC_IOCTL) */
-#define PCIC_IO0_16BIT 0x01 /* I/O to this segment is 16 bit */
-#define PCIC_IO0_CS16 0x02 /* I/O cs16 source is the card */
-#define PCIC_IO0_0WS 0x04 /* zero wait states added on 8 bit cycles */
-#define PCIC_IO0_WS 0x08 /* Wait states added for 16 bit cycles */
-#define PCIC_IO1_16BIT 0x10 /* I/O to this segment is 16 bit */
-#define PCIC_IO1_CS16 0x20 /* I/O cs16 source is the card */
-#define PCIC_IO1_0WS 0x40 /* zero wait states added on 8 bit cycles */
-#define PCIC_IO1_WS 0x80 /* Wait states added for 16 bit cycles */
-
-/* For the various I/O and Memory windows */
-#define PCIC_ADDR_LOW 0
-#define PCIC_ADDR_HIGH 1
-#define PCIC_START 0x00 /* Start of mapping region */
-#define PCIC_END 0x02 /* End of mapping region */
-#define PCIC_MOFF 0x04 /* Card Memory Mapping region offset */
-#define PCIC_IO0 0x08 /* I/O Address 0 */
-#define PCIC_IO1 0x0c /* I/O Address 1 */
-#define PCIC_SM0 0x10 /* System Memory Address 0 Mapping */
-#define PCIC_SM1 0x18 /* System Memory Address 1 Mapping */
-#define PCIC_SM2 0x20 /* System Memory Address 2 Mapping */
-#define PCIC_SM3 0x28 /* System Memory Address 3 Mapping */
-#define PCIC_SM4 0x30 /* System Memory Address 4 Mapping */
-
-/* For System Memory Window start registers
- (PCIC_SMx|PCIC_START|PCIC_ADDR_HIGH) */
-#define PCIC_ZEROWS 0x40 /* Zero wait states */
-#define PCIC_DATA16 0x80 /* Data width is 16 bits */
-
-/* For System Memory Window stop registers
- (PCIC_SMx|PCIC_END|PCIC_ADDR_HIGH) */
-#define PCIC_MW0 0x40 /* Wait state bit 0 */
-#define PCIC_MW1 0x80 /* Wait state bit 1 */
-
-/* For System Memory Window offset registers
- (PCIC_SMx|PCIC_MOFF|PCIC_ADDR_HIGH) */
-#define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */
-#define PCIC_WP 0x80 /* Write-protect this window */
-
-/* For Card Detect and General Control register (PCIC_CDGC) */
-#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */
-#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */
-#define PCIC_GPI_EN 0x04 /* General Purpose Input (GPI) Enable */
-#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */
-#define PCIC_CDRES_EN 0x10 /* card detect resume enable */
-#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */
-
-/* structure for ioctl */
-struct pcic_register {
- u_char addr;
- u_char val;
-};
-struct pcic_regs {
- u_short chip_vers;
-#define PCMICA_CHIP_82365_0 1
-#define PCMICA_CHIP_82365_1 2
-#define PCMICA_CHIP_IBM_1 3
-#define PCMICA_CHIP_IBM_2 4
-#define PCMICA_CHIP_146FC6 5
-#define PCMICA_CHIP_146FC7 6
- u_short cnt;
- struct pcic_register reg[128];
-};
-/* DON'T ADD ANYTHING AFTER THIS #endif */
-#endif /* __82365_H__ */
-#ifndef __82365_H__
-#define __82365_H__
-#endif
+#define PCIC_CHIP0_BASE 0x00
+#define PCIC_CHIP1_BASE 0x80
+
+/* Each PCIC chip can drive two sockets */
+
+#define PCIC_SOCKETA_INDEX 0x00
+#define PCIC_SOCKETB_INDEX 0x40
+
+/* general setup registers */
+
+#define PCIC_IDENT 0x00 /* RO */
+#define PCIC_IDENT_IFTYPE_MASK 0xC0
+#define PCIC_IDENT_IFTYPE_IO_ONLY 0x00
+#define PCIC_IDENT_IFTYPE_MEM_ONLY 0x40
+#define PCIC_IDENT_IFTYPE_MEM_AND_IO 0x80
+#define PCIC_IDENT_IFTYPE_RESERVED 0xC0
+#define PCIC_IDENT_ZERO 0x30
+#define PCIC_IDENT_REV_MASK 0x0F
+#define PCIC_IDENT_REV_I82365SLR0 0x02
+#define PCIC_IDENT_REV_I82365SLR1 0x03
+
+#define PCIC_IF_STATUS 0x01 /* RO */
+#define PCIC_IF_STATUS_GPI 0x80 /* General Purpose Input */
+#define PCIC_IF_STATUS_POWERACTIVE 0x40
+#define PCIC_IF_STATUS_READY 0x20 /* really READY/!BUSY */
+#define PCIC_IF_STATUS_MEM_WP 0x10
+#define PCIC_IF_STATUS_CARDDETECT_MASK 0x0C
+#define PCIC_IF_STATUS_CARDDETECT_PRESENT 0x0C
+#define PCIC_IF_STATUS_BATTERY_MASK 0x03
+#define PCIC_IF_STATUS_BATTERY_DEAD1 0x00
+#define PCIC_IF_STATUS_BATTERY_DEAD2 0x01
+#define PCIC_IF_STATUS_BATTERY_WARNING 0x02
+#define PCIC_IF_STATUS_BATTERY_GOOD 0x03
+
+#define PCIC_PWRCTL 0x02 /* RW */
+#define PCIC_PWRCTL_OE 0x80 /* output enable */
+#define PCIC_PWRCTL_DISABLE_RESETDRV 0x40
+#define PCIC_PWRCTL_AUTOSWITCH_ENABLE 0x20
+#define PCIC_PWRCTL_PWR_ENABLE 0x10
+#define PCIC_PWRCTL_VPP2_MASK 0x0C
+/* XXX these are a little unclear from the data sheet */
+#define PCIC_PWRCTL_VPP2_RESERVED 0x0C
+#define PCIC_PWRCTL_VPP2_EN1 0x08
+#define PCIC_PWRCTL_VPP2_EN0 0x04
+#define PCIC_PWRCTL_VPP2_ENX 0x00
+#define PCIC_PWRCTL_VPP1_MASK 0x03
+/* XXX these are a little unclear from the data sheet */
+#define PCIC_PWRCTL_VPP1_RESERVED 0x03
+#define PCIC_PWRCTL_VPP1_EN1 0x02
+#define PCIC_PWRCTL_VPP1_EN0 0x01
+#define PCIC_PWRCTL_VPP1_ENX 0x00
+
+#define PCIC_CSC 0x04 /* RW */
+#define PCIC_CSC_ZERO 0xE0
+#define PCIC_CSC_GPI 0x10
+#define PCIC_CSC_CD 0x08 /* Card Detect Change */
+#define PCIC_CSC_READY 0x04
+#define PCIC_CSC_BATTWARN 0x02
+#define PCIC_CSC_BATTDEAD 0x01 /* for memory cards */
+#define PCIC_CSC_RI 0x01 /* for i/o cards */
+
+#define PCIC_ADDRWIN_ENABLE 0x06 /* RW */
+#define PCIC_ADDRWIN_ENABLE_IO1 0x80
+#define PCIC_ADDRWIN_ENABLE_IO0 0x40
+#define PCIC_ADDRWIN_ENABLE_MEMCS16 0x20 /* rtfds if you care */
+#define PCIC_ADDRWIN_ENABLE_MEM4 0x10
+#define PCIC_ADDRWIN_ENABLE_MEM3 0x08
+#define PCIC_ADDRWIN_ENABLE_MEM2 0x04
+#define PCIC_ADDRWIN_ENABLE_MEM1 0x02
+#define PCIC_ADDRWIN_ENABLE_MEM0 0x01
+
+#define PCIC_CARD_DETECT 0x16 /* RW */
+#define PCIC_CARD_DETECT_RESERVED 0xC0
+#define PCIC_CARD_DETECT_SW_INTR 0x20
+#define PCIC_CARD_DETECT_RESUME_ENABLE 0x10
+#define PCIC_CARD_DETECT_GPI_TRANSCTL 0x08
+#define PCIC_CARD_DETECT_GPI_ENABLE 0x04
+#define PCIC_CARD_DETECT_CFGRST_ENABLE 0x02
+#define PCIC_CARD_DETECT_MEMDLY_INHIBIT 0x01
+
+/* interrupt registers */
+
+#define PCIC_INTR 0x03 /* RW */
+#define PCIC_INTR_RI_ENABLE 0x80
+#define PCIC_INTR_RESET 0x40 /* active low (zero) */
+#define PCIC_INTR_CARDTYPE_MASK 0x20
+#define PCIC_INTR_CARDTYPE_IO 0x20
+#define PCIC_INTR_CARDTYPE_MEM 0x00
+#define PCIC_INTR_ENABLE 0x10
+#define PCIC_INTR_IRQ_MASK 0x0F
+#define PCIC_INTR_IRQ_SHIFT 0
+#define PCIC_INTR_IRQ_NONE 0x00
+#define PCIC_INTR_IRQ_RESERVED1 0x01
+#define PCIC_INTR_IRQ_RESERVED2 0x02
+#define PCIC_INTR_IRQ3 0x03
+#define PCIC_INTR_IRQ4 0x04
+#define PCIC_INTR_IRQ5 0x05
+#define PCIC_INTR_IRQ_RESERVED6 0x06
+#define PCIC_INTR_IRQ7 0x07
+#define PCIC_INTR_IRQ_RESERVED8 0x08
+#define PCIC_INTR_IRQ9 0x09
+#define PCIC_INTR_IRQ10 0x0A
+#define PCIC_INTR_IRQ11 0x0B
+#define PCIC_INTR_IRQ12 0x0C
+#define PCIC_INTR_IRQ_RESERVED13 0x0D
+#define PCIC_INTR_IRQ14 0x0E
+#define PCIC_INTR_IRQ15 0x0F
+
+#define PCIC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */
+
+#define PCIC_CSC_INTR 0x05 /* RW */
+#define PCIC_CSC_INTR_IRQ_MASK 0xF0
+#define PCIC_CSC_INTR_IRQ_SHIFT 4
+#define PCIC_CSC_INTR_IRQ_NONE 0x00
+#define PCIC_CSC_INTR_IRQ_RESERVED1 0x10
+#define PCIC_CSC_INTR_IRQ_RESERVED2 0x20
+#define PCIC_CSC_INTR_IRQ3 0x30
+#define PCIC_CSC_INTR_IRQ4 0x40
+#define PCIC_CSC_INTR_IRQ5 0x50
+#define PCIC_CSC_INTR_IRQ_RESERVED6 0x60
+#define PCIC_CSC_INTR_IRQ7 0x70
+#define PCIC_CSC_INTR_IRQ_RESERVED8 0x80
+#define PCIC_CSC_INTR_IRQ9 0x90
+#define PCIC_CSC_INTR_IRQ10 0xA0
+#define PCIC_CSC_INTR_IRQ11 0xB0
+#define PCIC_CSC_INTR_IRQ12 0xC0
+#define PCIC_CSC_INTR_IRQ_RESERVED13 0xD0
+#define PCIC_CSC_INTR_IRQ14 0xE0
+#define PCIC_CSC_INTR_IRQ15 0xF0
+#define PCIC_CSC_INTR_CD_ENABLE 0x08
+#define PCIC_CSC_INTR_READY_ENABLE 0x04
+#define PCIC_CSC_INTR_BATTWARN_ENABLE 0x02
+#define PCIC_CSC_INTR_BATTDEAD_ENABLE 0x01 /* for memory cards */
+#define PCIC_CSC_INTR_RI_ENABLE 0x01 /* for I/O cards */
+
+#define PCIC_CSC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */
+
+/* I/O registers */
+
+#define PCIC_IO_WINS 2
+
+#define PCIC_IOCTL 0x07 /* RW */
+#define PCIC_IOCTL_IO1_WAITSTATE 0x80
+#define PCIC_IOCTL_IO1_ZEROWAIT 0x40
+#define PCIC_IOCTL_IO1_IOCS16SRC_MASK 0x20
+#define PCIC_IOCTL_IO1_IOCS16SRC_CARD 0x20
+#define PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE 0x00
+#define PCIC_IOCTL_IO1_DATASIZE_MASK 0x10
+#define PCIC_IOCTL_IO1_DATASIZE_16BIT 0x10
+#define PCIC_IOCTL_IO1_DATASIZE_8BIT 0x00
+#define PCIC_IOCTL_IO0_WAITSTATE 0x08
+#define PCIC_IOCTL_IO0_ZEROWAIT 0x04
+#define PCIC_IOCTL_IO0_IOCS16SRC_MASK 0x02
+#define PCIC_IOCTL_IO0_IOCS16SRC_CARD 0x02
+#define PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE 0x00
+#define PCIC_IOCTL_IO0_DATASIZE_MASK 0x01
+#define PCIC_IOCTL_IO0_DATASIZE_16BIT 0x01
+#define PCIC_IOCTL_IO0_DATASIZE_8BIT 0x00
+
+#define PCIC_IOADDR0_START_LSB 0x08
+#define PCIC_IOADDR0_START_MSB 0x09
+#define PCIC_IOADDR0_STOP_LSB 0x0A
+#define PCIC_IOADDR0_STOP_MSB 0x0B
+#define PCIC_IOADDR1_START_LSB 0x0C
+#define PCIC_IOADDR1_START_MSB 0x0D
+#define PCIC_IOADDR1_STOP_LSB 0x0E
+#define PCIC_IOADDR1_STOP_MSB 0x0F
+
+/* memory registers */
+
+/*
+ * memory window addresses refer to bits A23-A12 of the ISA system memory
+ * address. This is a shift of 12 bits. The LSB contains A19-A12, and the
+ * MSB contains A23-A20, plus some other bits.
+ */
+
+#define PCIC_MEM_WINS 5
+
+#define PCIC_MEM_SHIFT 12
+#define PCIC_MEM_PAGESIZE (1<<PCIC_MEM_SHIFT)
+
+#define PCIC_SYSMEM_ADDRX_SHIFT PCIC_MEM_SHIFT
+#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_MASK 0x80
+#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT 0x80
+#define PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_8BIT 0x00
+#define PCIC_SYSMEM_ADDRX_START_MSB_ZEROWAIT 0x40
+#define PCIC_SYSMEM_ADDRX_START_MSB_SCRATCH_MASK 0x30
+#define PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK 0x0F
+
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT_MASK 0xC0
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT0 0x00
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT1 0x40
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2 0x80
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT3 0xC0
+#define PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK 0x0F
+
+/*
+ * The card side of a memory mapping consists of bits A19-A12 of the card
+ * memory address in the LSB, and A25-A20 plus some other bits in the MSB.
+ * Again, the shift is 12 bits.
+ */
+
+#define PCIC_CARDMEM_ADDRX_SHIFT PCIC_MEM_SHIFT
+#define PCIC_CARDMEM_ADDRX_MSB_WP 0x80
+#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_MASK 0x40
+#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR 0x40
+#define PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_COMMON 0x00
+#define PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK 0x3F
+
+#define PCIC_SYSMEM_ADDR0_START_LSB 0x10
+#define PCIC_SYSMEM_ADDR0_START_MSB 0x11
+#define PCIC_SYSMEM_ADDR0_STOP_LSB 0x12
+#define PCIC_SYSMEM_ADDR0_STOP_MSB 0x13
+
+#define PCIC_CARDMEM_ADDR0_LSB 0x14
+#define PCIC_CARDMEM_ADDR0_MSB 0x15
+
+/* #define PCIC_RESERVED 0x17 */
+
+#define PCIC_SYSMEM_ADDR1_START_LSB 0x18
+#define PCIC_SYSMEM_ADDR1_START_MSB 0x19
+#define PCIC_SYSMEM_ADDR1_STOP_LSB 0x1A
+#define PCIC_SYSMEM_ADDR1_STOP_MSB 0x1B
+
+#define PCIC_CARDMEM_ADDR1_LSB 0x1C
+#define PCIC_CARDMEM_ADDR1_MSB 0x1D
+
+#define PCIC_SYSMEM_ADDR2_START_LSB 0x20
+#define PCIC_SYSMEM_ADDR2_START_MSB 0x21
+#define PCIC_SYSMEM_ADDR2_STOP_LSB 0x22
+#define PCIC_SYSMEM_ADDR2_STOP_MSB 0x23
+
+#define PCIC_CARDMEM_ADDR2_LSB 0x24
+#define PCIC_CARDMEM_ADDR2_MSB 0x25
+
+/* #define PCIC_RESERVED 0x26 */
+/* #define PCIC_RESERVED 0x27 */
+
+#define PCIC_SYSMEM_ADDR3_START_LSB 0x28
+#define PCIC_SYSMEM_ADDR3_START_MSB 0x29
+#define PCIC_SYSMEM_ADDR3_STOP_LSB 0x2A
+#define PCIC_SYSMEM_ADDR3_STOP_MSB 0x2B
+
+#define PCIC_CARDMEM_ADDR3_LSB 0x2C
+#define PCIC_CARDMEM_ADDR3_MSB 0x2D
+
+/* #define PCIC_RESERVED 0x2E */
+/* #define PCIC_RESERVED 0x2F */
+
+#define PCIC_SYSMEM_ADDR4_START_LSB 0x30
+#define PCIC_SYSMEM_ADDR4_START_MSB 0x31
+#define PCIC_SYSMEM_ADDR4_STOP_LSB 0x32
+#define PCIC_SYSMEM_ADDR4_STOP_MSB 0x33
+
+#define PCIC_CARDMEM_ADDR4_LSB 0x34
+#define PCIC_CARDMEM_ADDR4_MSB 0x35
+
+/* #define PCIC_RESERVED 0x36 */
+/* #define PCIC_RESERVED 0x37 */
+/* #define PCIC_RESERVED 0x38 */
+/* #define PCIC_RESERVED 0x39 */
+/* #define PCIC_RESERVED 0x3A */
+/* #define PCIC_RESERVED 0x3B */
+/* #define PCIC_RESERVED 0x3C */
+/* #define PCIC_RESERVED 0x3D */
+/* #define PCIC_RESERVED 0x3E */
+/* #define PCIC_RESERVED 0x3F */
+
+/* vendor-specific registers */
+
+#define PCIC_INTEL_GLOBAL_CTL 0x1E /* RW */
+#define PCIC_INTEL_GLOBAL_CTL_RESERVED 0xF0
+#define PCIC_INTEL_GLOBAL_CTL_IRQ14PULSE_ENABLE 0x08
+#define PCIC_INTEL_GLOBAL_CTL_EXPLICIT_CSC_ACK 0x04
+#define PCIC_INTEL_GLOBAL_CTL_IRQLEVEL_ENABLE 0x02
+#define PCIC_INTEL_GLOBAL_CTL_POWERDOWN 0x01
+
+#define PCIC_CIRRUS_MISC_CTL_2 0x1E
+#define PCIC_CIRRUS_MISC_CTL_2_SUSPEND 0x04
+
+#define PCIC_CIRRUS_CHIP_INFO 0x1F
+#define PCIC_CIRRUS_CHIP_INFO_CHIP_ID 0xC0
+#define PCIC_CIRRUS_CHIP_INFO_SLOTS 0x20
+#define PCIC_CIRRUS_CHIP_INFO_REV 0x1F
diff --git a/sys/dev/ic/i82365var.h b/sys/dev/ic/i82365var.h
new file mode 100644
index 00000000000..7c96d40f90a
--- /dev/null
+++ b/sys/dev/ic/i82365var.h
@@ -0,0 +1,169 @@
+/* $OpenBSD: i82365var.h,v 1.1 1998/09/11 07:53:58 fgsch Exp $ */
+/* $NetBSD: i82365var.h,v 1.4 1998/05/23 18:32:29 matt Exp $ */
+
+/*
+ * Copyright (c) 1997 Marc Horowitz. 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 Marc Horowitz.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/device.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciachip.h>
+
+#include <dev/ic/i82365reg.h>
+
+struct pcic_handle {
+ struct pcic_softc *sc;
+ int vendor;
+ int sock;
+ int flags;
+ int memalloc;
+ struct {
+ bus_addr_t addr;
+ bus_size_t size;
+ long offset;
+ int kind;
+ } mem[PCIC_MEM_WINS];
+ int ioalloc;
+ struct {
+ bus_addr_t addr;
+ bus_size_t size;
+ int width;
+ } io[PCIC_IO_WINS];
+ int ih_irq;
+ struct device *pcmcia;
+};
+
+#define PCIC_FLAG_SOCKETP 0x0001
+#define PCIC_FLAG_CARDP 0x0002
+
+#define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX
+#define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX
+#define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX
+#define C1SB PCIC_CHIP1_BASE+PCIC_SOCKETB_INDEX
+
+/*
+ * This is sort of arbitrary. It merely needs to be "enough". It can be
+ * overridden in the conf file, anyway.
+ */
+
+#define PCIC_MEM_PAGES 4
+#define PCIC_MEMSIZE PCIC_MEM_PAGES*PCIC_MEM_PAGESIZE
+
+#define PCIC_NSLOTS 4
+
+struct pcic_softc {
+ struct device dev;
+
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+
+ /* XXX isa_chipset_tag_t, pci_chipset_tag_t, etc. */
+ void *intr_est;
+
+ pcmcia_chipset_tag_t pct;
+
+ /* this needs to be large enough to hold PCIC_MEM_PAGES bits */
+ int subregionmask;
+
+ /* used by memory window mapping functions */
+ bus_addr_t membase;
+
+ /*
+ * used by io window mapping functions. These can actually overlap
+ * with another pcic, since the underlying extent mapper will deal
+ * with individual allocations. This is here to deal with the fact
+ * that different busses have different real widths (different pc
+ * hardware seems to use 10 or 12 bits for the I/O bus).
+ */
+ bus_addr_t iobase;
+ bus_addr_t iosize;
+
+ int irq;
+ void *ih;
+
+ struct pcic_handle handle[PCIC_NSLOTS];
+};
+
+
+int pcic_ident_ok __P((int));
+int pcic_vendor __P((struct pcic_handle *));
+char *pcic_vendor_to_string __P((int));
+
+void pcic_attach __P((struct pcic_softc *));
+void pcic_attach_sockets __P((struct pcic_softc *));
+int pcic_intr __P((void *arg));
+
+static inline int pcic_read __P((struct pcic_handle *, int));
+static inline void pcic_write __P((struct pcic_handle *, int, int));
+
+int pcic_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t,
+ struct pcmcia_mem_handle *));
+void pcic_chip_mem_free __P((pcmcia_chipset_handle_t,
+ struct pcmcia_mem_handle *));
+int pcic_chip_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_mem_handle *, bus_addr_t *, int *));
+void pcic_chip_mem_unmap __P((pcmcia_chipset_handle_t, int));
+
+int pcic_chip_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t,
+ bus_size_t, bus_size_t, struct pcmcia_io_handle *));
+void pcic_chip_io_free __P((pcmcia_chipset_handle_t,
+ struct pcmcia_io_handle *));
+int pcic_chip_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_io_handle *, int *));
+void pcic_chip_io_unmap __P((pcmcia_chipset_handle_t, int));
+
+void pcic_chip_socket_enable __P((pcmcia_chipset_handle_t));
+void pcic_chip_socket_disable __P((pcmcia_chipset_handle_t));
+
+static __inline int pcic_read __P((struct pcic_handle *, int));
+static __inline int
+pcic_read(h, idx)
+ struct pcic_handle *h;
+ int idx;
+{
+ if (idx != -1)
+ bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX,
+ h->sock + idx);
+ return (bus_space_read_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA));
+}
+
+static __inline void pcic_write __P((struct pcic_handle *, int, int));
+static __inline void
+pcic_write(h, idx, data)
+ struct pcic_handle *h;
+ int idx;
+ int data;
+{
+ if (idx != -1)
+ bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX,
+ h->sock + idx);
+ bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA, (data));
+}