summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>1998-09-11 10:47:16 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>1998-09-11 10:47:16 +0000
commit4cccaf7b6e534b99f6c07b76048acfa90e4d8495 (patch)
tree9485f874b3237996416ecf4fa4d21e3a5c93c57c
parent27d7305f5dcc8a0f7154c2543c83537e60e654a9 (diff)
PCMCIA code ported from NetBSD.
Support for aic, ep, pccom and sm.
-rw-r--r--sys/dev/pcmcia/Makefile10
-rw-r--r--sys/dev/pcmcia/Makefile.pcmciadevs8
-rw-r--r--sys/dev/pcmcia/aic_pcmcia.c160
-rw-r--r--sys/dev/pcmcia/com_pcmcia.c673
-rw-r--r--sys/dev/pcmcia/devlist2h.awk193
-rw-r--r--sys/dev/pcmcia/files.pcmcia63
-rw-r--r--sys/dev/pcmcia/if_ep_pcmcia.c422
-rw-r--r--sys/dev/pcmcia/if_sm_pcmcia.c357
-rw-r--r--sys/dev/pcmcia/pcmcia.c1780
-rw-r--r--sys/dev/pcmcia/pcmcia_cis.c1196
-rw-r--r--sys/dev/pcmcia/pcmciachip.h145
-rw-r--r--sys/dev/pcmcia/pcmciadevs129
-rw-r--r--sys/dev/pcmcia/pcmciadevs.h206
-rw-r--r--sys/dev/pcmcia/pcmciadevs_data.h443
-rw-r--r--sys/dev/pcmcia/pcmciareg.h365
-rw-r--r--sys/dev/pcmcia/pcmciavar.h479
16 files changed, 4645 insertions, 1984 deletions
diff --git a/sys/dev/pcmcia/Makefile b/sys/dev/pcmcia/Makefile
new file mode 100644
index 00000000000..27986481a40
--- /dev/null
+++ b/sys/dev/pcmcia/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 1998/09/11 10:47:13 fgsch Exp $
+# $NetBSD: Makefile,v 1.2 1998/07/19 17:28:15 christos Exp $
+
+# use 'make -f Makefile.pcmciadevs' to make pcmciadevs.h and pcmciadevs_data.h
+
+INCSDIR= /usr/include/dev/pcmcia
+
+INCS= pcmciachip.h pcmciareg.h pcmciavar.h
+
+.include <bsd.kinc.mk>
diff --git a/sys/dev/pcmcia/Makefile.pcmciadevs b/sys/dev/pcmcia/Makefile.pcmciadevs
new file mode 100644
index 00000000000..6b76864c0c4
--- /dev/null
+++ b/sys/dev/pcmcia/Makefile.pcmciadevs
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile.pcmciadevs,v 1.1 1998/09/11 10:47:14 fgsch Exp $
+# $NetBSD: Makefile.pcmciadevs,v 1.1 1998/07/19 17:28:15 christos Exp $
+
+AWK= awk
+
+pcmciadevs.h pcmciadevs_data.h: pcmciadevs devlist2h.awk
+ /bin/rm -f pcmciadevs.h pcmciadevs_data.h
+ ${AWK} -f devlist2h.awk pcmciadevs
diff --git a/sys/dev/pcmcia/aic_pcmcia.c b/sys/dev/pcmcia/aic_pcmcia.c
new file mode 100644
index 00000000000..2831f1d84b1
--- /dev/null
+++ b/sys/dev/pcmcia/aic_pcmcia.c
@@ -0,0 +1,160 @@
+/* $OpenBSD: aic_pcmcia.c,v 1.1 1998/09/11 10:47:14 fgsch Exp $ */
+/* $NetBSD: aic_pcmcia.c,v 1.6 1998/07/19 17:28:15 christos 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/param.h>
+#include <sys/systm.h>
+#include <sys/select.h>
+#include <sys/device.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/isa/isavar.h>
+
+#include <dev/ic/aic6360var.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+int aic_pcmcia_match __P((struct device *, void *, void *));
+void aic_pcmcia_attach __P((struct device *, struct device *, void *));
+
+struct aic_pcmcia_softc {
+ struct aic_softc sc_aic; /* real "aic" softc */
+
+ /* PCMCIA-specific goo. */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+ void *sc_ih; /* interrupt handler */
+};
+
+struct cfattach aic_pcmcia_ca = {
+ sizeof(struct aic_pcmcia_softc), aic_pcmcia_match, aic_pcmcia_attach
+};
+
+int
+aic_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct pcmcia_attach_args *pa = aux;
+
+ if (pa->manufacturer == PCMCIA_VENDOR_ADAPTEC) {
+ switch (pa->product) {
+ case PCMCIA_PRODUCT_ADAPTEC_APA1460_1:
+ case PCMCIA_PRODUCT_ADAPTEC_APA1460_2:
+ if (pa->pf->number == 0)
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+void
+aic_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct aic_pcmcia_softc *psc = (void *)self;
+ struct aic_softc *sc = &psc->sc_aic;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ struct pcmcia_function *pf = pa->pf;
+ const char *s;
+
+ psc->sc_pf = pf;
+
+ for (cfe = SIMPLEQ_FIRST(&pf->cfe_head); cfe != NULL;
+ cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
+ if (cfe->num_memspace != 0 ||
+ cfe->num_iospace != 1)
+ continue;
+
+ if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
+ cfe->iospace[0].length, 0, &psc->sc_pcioh) == 0)
+ break;
+ }
+
+ if (cfe == 0) {
+ printf(": can't alloc i/o space\n");
+ return;
+ }
+
+ sc->sc_iot = psc->sc_pcioh.iot;
+ sc->sc_ioh = psc->sc_pcioh.ioh;
+
+ /* Enable the card. */
+ pcmcia_function_init(pf, cfe);
+ if (pcmcia_function_enable(pf)) {
+ printf(": function enable failed\n");
+ return;
+ }
+
+ /* Map in the io space */
+ if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0, psc->sc_pcioh.size,
+ &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ if (!aic_find(sc->sc_iot, sc->sc_ioh))
+ printf(": coundn't find aic\n%s", sc->sc_dev.dv_xname);
+
+ switch (pa->product) {
+ case PCMCIA_PRODUCT_ADAPTEC_APA1460_1:
+ s = PCMCIA_STR_ADAPTEC_APA1460_1;
+ break;
+ case PCMCIA_PRODUCT_ADAPTEC_APA1460_2:
+ s = PCMCIA_STR_ADAPTEC_APA1460_2;
+ break;
+ default:
+ s = "Unknown APA1460";
+ break;
+ }
+
+ printf(": %s\n", s);
+
+ aicattach(sc);
+
+ /* Establish the interrupt handler. */
+ psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_BIO, aicintr, sc);
+ if (psc->sc_ih == NULL)
+ printf("%s: couldn't establish interrupt\n",
+ sc->sc_dev.dv_xname);
+}
diff --git a/sys/dev/pcmcia/com_pcmcia.c b/sys/dev/pcmcia/com_pcmcia.c
index cbbe287caa6..02576518c8d 100644
--- a/sys/dev/pcmcia/com_pcmcia.c
+++ b/sys/dev/pcmcia/com_pcmcia.c
@@ -1,9 +1,43 @@
-/* $OpenBSD: com_pcmcia.c,v 1.3 1998/03/05 14:39:38 niklas Exp $ */
-/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
+/* $OpenBSD: com_pcmcia.c,v 1.4 1998/09/11 10:47:14 fgsch Exp $ */
+/* $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
/*-
- * Copyright (c) 1993, 1994, 1995, 1996
- * Charles M. Hannum. All rights reserved.
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
@@ -34,334 +68,451 @@
* 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.
+ *
+ * @(#)com.c 7.5 (Berkeley) 5/16/91
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/types.h>
+#include <sys/device.h>
-#include <machine/bus.h>
#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciadevs.h>
#include <dev/isa/isavar.h>
#include <dev/ic/comreg.h>
+#ifdef i386
+#include <i386/isa/pccomvar.h>
+#else
#include <dev/ic/comvar.h>
+#endif
#include <dev/ic/ns16550reg.h>
-#include <dev/pcmcia/pcmciavar.h>
+#include <dev/isa/isareg.h>
-/* Macros to clear/set/test flags. */
+#define com_lcr com_cfcr
#define SET(t, f) (t) |= (f)
-#define CLR(t, f) (t) &= ~(f)
-#define ISSET(t, f) ((t) & (f))
-int com_pcmcia_match __P((struct device *, void *, void *));
-void com_pcmcia_attach __P((struct device *, struct device *, void *));
-int com_pcmcia_detach __P((struct device *));
+struct com_dev {
+ char *name;
+ char *cis1_info[4];
+};
+
+/* Devices that we need to match by CIS strings */
+static struct com_dev com_devs[] = {
+ { PCMCIA_STR_MEGAHERTZ_XJ2288,
+ PCMCIA_CIS_MEGAHERTZ_XJ2288 },
+};
+
+
+static int com_devs_size = sizeof(com_devs) / sizeof(com_devs[0]);
+static struct com_dev *com_dev_match __P((struct pcmcia_card *));
+
+int com_pcmcia_match __P((struct device *, void *, void *));
+void com_pcmcia_attach __P((struct device *, struct device *, void *));
+void com_pcmcia_cleanup __P((void *));
-int com_pcmcia_mod __P((struct pcmcia_link *pc_link, struct device *self,
- struct pcmcia_conf *pc_cf, struct cfdata *cf));
-int com_pcmcia_isa_attach __P((struct device *, void *, void *,
- struct pcmcia_link *));
-int com_pcmcia_remove __P((struct pcmcia_link *, struct device *));
-int com_pcmcia_probe __P((struct device *, void *, void *));
+int com_pcmcia_enable __P((struct com_softc *));
+void com_pcmcia_disable __P((struct com_softc *));
+int com_pcmcia_enable1 __P((struct com_softc *));
+void com_pcmcia_disable1 __P((struct com_softc *));
+
+void com_attach __P((struct com_softc *));
+
+struct com_pcmcia_softc {
+ struct com_softc sc_com; /* real "com" softc */
+
+ /* PCMCIA-specific goo */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+ void *sc_ih; /* interrupt handler */
+};
struct cfattach com_pcmcia_ca = {
- sizeof(struct com_softc), com_pcmcia_match, com_pcmcia_attach,
- com_pcmcia_detach
+ sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach
};
-/* additional setup needed for pcmcia devices */
-/* modify config entry */
-int
-com_pcmcia_mod(pc_link, self, pc_cf, cf)
- struct pcmcia_link *pc_link;
- struct device *self;
- struct pcmcia_conf *pc_cf;
- struct cfdata *cf;
-{
- int err;
-
- if (!(err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self,
- pc_cf, cf))) {
- pc_cf->memwin = 0;
- if (pc_cf->cfgtype == 0)
- pc_cf->cfgtype = CFGENTRYID; /* determine from ioaddr */
+/* Look for pcmcia cards with particular CIS strings */
+static struct com_dev *
+com_dev_match(card)
+ struct pcmcia_card *card;
+{
+ int i, j;
+
+ for (i = 0; i < com_devs_size; i++) {
+ for (j = 0; j < 4; j++)
+ if (com_devs[i].cis1_info[j] &&
+ strcmp(com_devs[i].cis1_info[j],
+ card->cis1_info[j]))
+ break;
+ if (j == 4)
+ return &com_devs[i];
}
- return err;
+
+ return NULL;
}
-static struct pcmcia_com {
- struct pcmcia_device pcd;
-} pcmcia_com = {
- {"PCMCIA Modem card", com_pcmcia_mod, com_pcmcia_isa_attach,
- NULL, com_pcmcia_remove}
-};
-
-
-struct pcmciadevs pcmcia_com_devs[] = {
- { "com", 0,
- NULL, "*MODEM*", NULL, NULL,
- NULL, (void *)&pcmcia_com
- },
- { "com", 0,
- NULL, NULL, "*MODEM*", NULL,
- NULL, (void *)&pcmcia_com
- },
- { "com", 0,
- NULL, NULL, NULL, "*MODEM*",
- NULL, (void *)&pcmcia_com
- },
- {NULL}
-};
-#define ncom_pcmcia_devs sizeof(pcmcia_com_devs)/sizeof(pcmcia_com_devs[0])
int
com_pcmcia_match(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- return pcmcia_slave_match(parent, match, aux, pcmcia_com_devs,
- ncom_pcmcia_devs);
+ int comportmask;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+
+ /* 1. Does it claim to be a serial device? */
+ if (pa->pf->function == PCMCIA_FUNCTION_SERIAL)
+ return 1;
+
+ /* 2. Does it have all four 'standard' port ranges? */
+ comportmask = 0;
+ for (cfe = pa->pf->cfe_head.sqh_first; cfe;
+ cfe = cfe->cfe_list.sqe_next) {
+ switch (cfe->iospace[0].start) {
+ case IO_COM1:
+ comportmask |= 1;
+ break;
+ case IO_COM2:
+ comportmask |= 2;
+ break;
+ case IO_COM3:
+ comportmask |= 4;
+ break;
+ case IO_COM4:
+ comportmask |= 8;
+ break;
+ }
+ }
+
+ if (comportmask == 15)
+ return 1;
+
+ /* 3. Is this a card we know about? */
+ if (com_dev_match(pa->card) != NULL)
+ return 1;
+
+ return 0;
}
-int
-com_pcmcia_isa_attach(parent, match, aux, pc_link)
- struct device *parent;
- void *match;
+void
+com_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
void *aux;
- struct pcmcia_link *pc_link;
{
- struct isa_attach_args *ia = aux;
- struct com_softc *sc = match;
- int rval;
-
- if ((rval = com_pcmcia_probe(parent, sc->sc_dev.dv_cfdata, ia))) {
- if (ISSET(pc_link->flags, PCMCIA_REATTACH)) {
-#ifdef COM_DEBUG
- printf("comreattach, hwflags=%x\n", sc->sc_hwflags);
+ struct com_pcmcia_softc *psc = (void *) self;
+ struct com_softc *sc = &psc->sc_com;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ int autoalloc = 0;
+
+ psc->sc_pf = pa->pf;
+
+retry:
+ /* find a cfe we can use */
+
+ for (cfe = pa->pf->cfe_head.sqh_first; cfe;
+ cfe = cfe->cfe_list.sqe_next) {
+#if 0
+ /*
+ * Some modem cards (e.g. Xircom CM33) also have
+ * mem space. Don't bother with this check.
+ */
+ if (cfe->num_memspace != 0)
+ continue;
#endif
- sc->sc_hwflags = COM_HW_REATTACH | (sc->sc_hwflags &
- (COM_HW_ABSENT_PENDING|COM_HW_CONSOLE));
- } else
- sc->sc_hwflags = 0;
- sc->sc_ic = ia->ia_ic;
+
+ if (cfe->num_iospace != 1)
+ continue;
+
+ if (autoalloc == 1) {
+ if (cfe->iomask == 3) {
+ if (!pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length,
+ &psc->sc_pcioh)) {
+ goto found;
+ }
+ }
+ } else {
+ if (!pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
+ cfe->iospace[0].length, 0, &psc->sc_pcioh)) {
+ goto found;
+ }
+ }
+ }
+ if (autoalloc == 0) {
+ autoalloc = 1;
+ goto retry;
+ } else if (!cfe) {
+ printf(": can't allocate i/o space\n");
+ return;
}
- return rval;
-}
+found:
+ sc->sc_iot = psc->sc_pcioh.iot;
+ sc->sc_ioh = psc->sc_pcioh.ioh;
-/*
- * Called by config_detach attempts, shortly after com_pcmcia_remove
- * was called.
- */
-int
-com_pcmcia_detach(self)
- struct device *self;
-{
- struct com_softc *sc = (void *)self;
+ /* Enable the card. */
+ pcmcia_function_init(pa->pf, cfe);
+ if (com_pcmcia_enable1(sc))
+ printf(": function enable failed\n");
+
+#ifdef notyet
+ sc->enabled = 1;
+#endif
- if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
- /* don't let it really be detached, it is still open */
- return EBUSY;
+ /* map in the io space */
+
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size,
+ &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return;
}
- return 0; /* OK! */
+
+ sc->sc_iobase = -1;
+#ifdef notyet
+ sc->sc_frequency = COM_FREQ;
+
+ sc->enable = com_pcmcia_enable;
+ sc->disable = com_pcmcia_disable;
+#endif
+
+ printf(": serial device");
+
+#ifdef notyet
+ com_attach_subr(sc);
+#endif
+ com_attach(sc);
+
+ /* establish the interrupt. */
+ psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, comintr, sc);
+ if (psc->sc_ih == NULL)
+ printf("%s: couldn't establish interrupt\n",
+ sc->sc_dev.dv_xname);
+
+#ifdef notyet
+ sc->enabled = 0;
+
+ com_pcmcia_disable1(sc);
+#endif
}
-/*
- * called by pcmcia framework to accept/reject remove attempts.
- * If we return 0, then the detach will proceed.
- */
int
-com_pcmcia_remove(pc_link, self)
- struct pcmcia_link *pc_link;
- struct device *self;
+com_pcmcia_enable(sc)
+ struct com_softc *sc;
{
- struct com_softc *sc = (void *)self;
- struct tty *tp;
- int s;
-
- if (!sc->sc_tty)
- goto ok;
- tp = sc->sc_tty;
-
- /* not in use ? if so, return "OK" */
- if (!ISSET(tp->t_state, TS_ISOPEN) &&
- !ISSET(tp->t_state, TS_WOPEN)) {
- ttyfree(sc->sc_tty);
- sc->sc_tty = NULL;
- ok:
- isa_intr_disestablish(sc->sc_ic, sc->sc_ih);
- sc->sc_ih = NULL;
- SET(sc->sc_hwflags, COM_HW_ABSENT);
- return 0; /* OK! */
+ struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
+ struct pcmcia_function *pf = psc->sc_pf;
+
+ /* establish the interrupt. */
+ psc->sc_ih = pcmcia_intr_establish(pf, IPL_TTY, comintr, sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt\n",
+ sc->sc_dev.dv_xname);
+ return (1);
}
- /*
- * Not easily removed. Put device into a dead state, clean state
- * as best we can. notify all waiters.
- */
- SET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING);
-#ifdef COM_DEBUG
- printf("pending detach flags %x\n", sc->sc_hwflags);
-#endif
+ return com_pcmcia_enable1(sc);
+}
- s = spltty();
- com_absent_notify(sc);
- splx(s);
+int
+com_pcmcia_enable1(sc)
+ struct com_softc *sc;
+{
+ struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
+ struct pcmcia_function *pf = psc->sc_pf;
+ int ret;
- return 0;
+ if ((ret = pcmcia_function_enable(pf)))
+ return(ret);
+
+ if (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) {
+ int reg;
+
+ /* turn off the ethernet-disable bit */
+
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
+ if (reg & 0x08) {
+ reg &= ~0x08;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
+ }
+ }
+
+ return(ret);
}
-#if 0
void
-com_pcmcia_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+com_pcmcia_disable(sc)
+ struct com_softc *sc;
{
- struct pcmcia_attach_args *paa = aux;
-
- printf("com_pcmcia_attach %p %p %p\n", parent, self, aux);
- delay(2000000);
- if (!pcmcia_configure(parent, self, paa->paa_link)) {
- struct com_softc *sc = (void *)self;
- sc->sc_hwflags |= COM_HW_ABSENT;
- printf(": not attached\n");
- }
+ struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
+
+ com_pcmcia_disable1(sc);
+ pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
}
-#endif
-int
-com_pcmcia_probe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+void
+com_pcmcia_disable1(sc)
+ struct com_softc *sc;
{
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- int iobase, needioh;
- int rv = 1;
- struct isa_attach_args *ia = aux;
-
- iot = ia->ia_iot;
- iobase = ia->ia_iobase;
- needioh = 1;
-
- /* if it's in use as console, it's there. */
- if (iobase == comconsaddr && !comconsattached)
- goto out;
-
- if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
- rv = 0;
- goto out;
- }
- rv = comprobe1(iot, ioh);
- if (needioh)
- bus_space_unmap(iot, ioh, COM_NPORTS);
-
-out:
- ia->ia_iosize = COM_NPORTS;
- ia->ia_msize = 0;
- return (rv);
+ struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
+
+ pcmcia_function_disable(psc->sc_pf);
}
+/*
+ * XXX This should be handled by a generic attach
+ */
void
-com_pcmcia_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+com_attach(sc)
+ struct com_softc *sc;
{
- struct com_softc *sc = (void *)self;
- int iobase, irq;
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- struct isa_attach_args *ia = aux;
-
- if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
- int s;
- s = spltty();
- com_absent_notify(sc);
- splx(s);
- } else
- sc->sc_hwflags = 0;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
+ u_int8_t lcr;
+
+ sc->sc_hwflags = 0;
sc->sc_swflags = 0;
/*
- * We're living on an isa.
+ * Probe for all known forms of UART.
*/
- iobase = ia->ia_iobase;
- iot = ia->ia_iot;
- if (iobase != comconsaddr) {
- if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
- panic("comattach: io mapping failed");
- } else
- ioh = comconsioh;
- irq = ia->ia_irq;
-
- sc->sc_iot = iot;
- sc->sc_ioh = ioh;
- sc->sc_iobase = iobase;
-
- if (iobase == comconsaddr) {
- comconsattached = 1;
-
- /*
- * Need to reset baud rate, etc. of next print so reset
- * comconsinit. Also make sure console is always "hardwired".
- */
- delay(1000); /* wait for output to finish */
- comconsinit = 0;
- SET(sc->sc_hwflags, COM_HW_CONSOLE);
- SET(sc->sc_swflags, COM_SW_SOFTCAR);
- }
+ lcr = bus_space_read_1(iot, ioh, com_lcr);
- /* look for a NS 16550AF UART with FIFOs */
- bus_space_write_1(iot, ioh, com_fifo,
- FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
- delay(100);
- if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK) ==
- IIR_FIFO_MASK) {
- if (ISSET(bus_space_read_1(iot, ioh, com_fifo),
- FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
- SET(sc->sc_hwflags, COM_HW_FIFO);
- printf(": ns16550a, working fifo\n");
- } else
- printf(": ns16550, broken fifo\n");
- } else
- printf(": ns8250 or ns16450, no fifo\n");
- bus_space_write_1(iot, ioh, com_fifo, 0);
+ bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
+ bus_space_write_1(iot, ioh, com_efr, 0);
+ bus_space_write_1(iot, ioh, com_lcr, 0);
- /* disable interrupts */
- bus_space_write_1(iot, ioh, com_ier, 0);
- bus_space_write_1(iot, ioh, com_mcr, 0);
+ bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
+ delay(100);
- if (irq != IRQUNK) {
- struct isa_attach_args *ia = aux;
+ switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {
+ case 0:
+ sc->sc_uarttype = COM_UART_16450;
+ break;
+ case 2:
+ sc->sc_uarttype = COM_UART_16550;
+ break;
+ case 3:
+ sc->sc_uarttype = COM_UART_16550A;
+ break;
+ default:
+ sc->sc_uarttype = COM_UART_UNKNOWN;
+ break;
+ }
- sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
- IST_EDGE, IPL_TTY, comintr, sc, sc->sc_dev.dv_xname);
+ if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */
+ bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
+ if (bus_space_read_1(iot, ioh, com_efr) == 0) {
+ sc->sc_uarttype = COM_UART_ST16650;
+ } else {
+ bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
+ if (bus_space_read_1(iot, ioh, com_efr) == 0)
+ sc->sc_uarttype = COM_UART_ST16650V2;
+ }
}
-#ifdef KGDB
- if (kgdb_dev == makedev(commajor, unit)) {
- if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
- kgdb_dev = -1; /* can't debug over console port */
- else {
- cominit(iot, ioh, kgdb_rate);
- if (kgdb_debug_init) {
- /*
- * Print prefix of device name,
- * let kgdb_connect print the rest.
- */
- printf("%s: ", sc->sc_dev.dv_xname);
- kgdb_connect(1);
- } else
- printf("%s: kgdb enabled\n",
- sc->sc_dev.dv_xname);
+#ifdef i386
+ if (sc->sc_uarttype == COM_UART_ST16650V2) { /* Probe for XR16850s */
+ u_int8_t dlbl, dlbh;
+
+ /* Enable latch access and get the current values. */
+ bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
+ dlbl = bus_space_read_1(iot, ioh, com_dlbl);
+ dlbh = bus_space_read_1(iot, ioh, com_dlbh);
+
+ /* Zero out the latch divisors */
+ bus_space_write_1(iot, ioh, com_dlbl, 0);
+ bus_space_write_1(iot, ioh, com_dlbh, 0);
+
+ if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) {
+ sc->sc_uarttype = COM_UART_XR16850;
+ sc->sc_uartrev = bus_space_read_1(iot, ioh, com_dlbl);
}
+
+ /* Reset to original. */
+ bus_space_write_1(iot, ioh, com_dlbl, dlbl);
+ bus_space_write_1(iot, ioh, com_dlbh, dlbh);
}
#endif
+
+ /* Reset the LCR (latch access is probably enabled). */
+ bus_space_write_1(iot, ioh, com_lcr, lcr);
+ if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */
+ u_int8_t scr0, scr1, scr2;
+
+ scr0 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, 0xa5);
+ scr1 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, 0x5a);
+ scr2 = bus_space_read_1(iot, ioh, com_scratch);
+ bus_space_write_1(iot, ioh, com_scratch, scr0);
+
+ if ((scr1 != 0xa5) || (scr2 != 0x5a))
+ sc->sc_uarttype = COM_UART_8250;
+ }
- /* XXX maybe move up some? */
- if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
- printf("%s: console\n", sc->sc_dev.dv_xname);
+ /*
+ * Print UART type and initialize ourself.
+ */
+ sc->sc_fifolen = 1; /* default */
+ switch (sc->sc_uarttype) {
+ case COM_UART_UNKNOWN:
+ printf(": unknown uart\n");
+ break;
+ case COM_UART_8250:
+ printf(": ns8250, no fifo\n");
+ break;
+ case COM_UART_16450:
+ printf(": ns16450, no fifo\n");
+ break;
+ case COM_UART_16550:
+ printf(": ns16550, no working fifo\n");
+ break;
+ case COM_UART_16550A:
+ printf(": ns16550a, 16 byte fifo\n");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 16;
+ break;
+ case COM_UART_ST16650:
+ printf(": st16650, no working fifo\n");
+ break;
+ case COM_UART_ST16650V2:
+ printf(": st16650, 32 byte fifo\n");
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 32;
+ break;
+#ifdef i386
+ case COM_UART_XR16850:
+ printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
+ SET(sc->sc_hwflags, COM_HW_FIFO);
+ sc->sc_fifolen = 128;
+ break;
+#endif
+ default:
+ panic("comattach: bad fifo type\n");
+ }
+
+ /* clear and disable fifo */
+ bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
+ (void)bus_space_read_1(iot, ioh, com_data);
+ bus_space_write_1(iot, ioh, com_fifo, 0);
}
diff --git a/sys/dev/pcmcia/devlist2h.awk b/sys/dev/pcmcia/devlist2h.awk
new file mode 100644
index 00000000000..c077fce7736
--- /dev/null
+++ b/sys/dev/pcmcia/devlist2h.awk
@@ -0,0 +1,193 @@
+#! /usr/bin/awk -f
+# $OpenBSD: devlist2h.awk,v 1.1 1998/09/11 10:47:14 fgsch Exp $
+# $NetBSD: devlist2h.awk,v 1.2 1998/07/22 11:47:13 christos Exp $
+#
+# Copyright (c) 1998, Christos Zoulas
+# Copyright (c) 1995, 1996 Christopher G. Demetriou
+# 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 Christopher G. Demetriou.
+# This product includes software developed by Christos Zoulas
+# 4. The name of the author(s) 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.
+#
+function collectline(f, line) {
+ oparen = 0
+ line = ""
+ while (f <= NF) {
+ if ($f == "#") {
+ line = line "("
+ oparen = 1
+ f++
+ continue
+ }
+ if (oparen) {
+ line = line $f
+ if (f < NF)
+ line = line " "
+ f++
+ continue
+ }
+ line = line $f
+ if (f < NF)
+ line = line " "
+ f++
+ }
+ if (oparen)
+ line = line ")"
+ return line
+}
+BEGIN {
+ nproducts = nvendors = 0
+ dfile="pcmciadevs_data.h"
+ hfile="pcmciadevs.h"
+}
+NR == 1 {
+ VERSION = $0
+ gsub("\\$", "", VERSION)
+
+ printf("/*\t\$OpenBSD\$\t*/\n\n") > dfile
+ printf("/*\n") > dfile
+ printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
+ > dfile
+ printf(" *\n") > dfile
+ printf(" * generated from:\n") > dfile
+ printf(" *\t%s\n", VERSION) > dfile
+ printf(" */\n") > dfile
+
+ printf("/*\t\$OpenBSD\$\t*/\n\n") > hfile
+ printf("/*\n") > hfile
+ printf(" * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
+ > hfile
+ printf(" *\n") > hfile
+ printf(" * generated from:\n") > hfile
+ printf(" *\t%s\n", VERSION) > hfile
+ printf(" */\n") > hfile
+
+ next
+}
+$1 == "vendor" {
+ nvendors++
+
+ vendorindex[$2] = nvendors; # record index for this name, for later.
+ vendors[nvendors, 1] = $2; # name
+ vendors[nvendors, 2] = $3; # id
+ printf("#define\tPCMCIA_VENDOR_%s\t%s\t", vendors[nvendors, 1],
+ vendors[nvendors, 2]) > hfile
+ vendors[nvendors, 3] = collectline(4, line)
+ printf("/* %s */\n", vendors[nvendors, 3]) > hfile
+ next
+}
+$1 == "product" {
+ nproducts++
+
+ products[nproducts, 1] = $2; # vendor name
+ products[nproducts, 2] = $3; # product id
+ products[nproducts, 3] = $4; # id
+
+ f = 5;
+
+ if ($4 == "{") {
+ products[nproducts, 3] = -1
+ z = "{ "
+ for (i = 0; i < 4; i++) {
+ if (f <= NF) {
+ gsub("&sp", " ", $f)
+ gsub("&tab", "\t", $f)
+ gsub("&nl", "\n", $f)
+ z = z $f " "
+ f++
+ }
+ else {
+ if (i == 3)
+ z = z "NULL "
+ else
+ z = z "NULL, "
+ }
+ }
+ products[nproducts, 4] = z $f
+ f++
+ }
+ else {
+ products[nproducts, 4] = "{ NULL, NULL, NULL, NULL }"
+ }
+ printf("#define\tPCMCIA_CIS_%s_%s\t%s\n",
+ products[nproducts, 1], products[nproducts, 2],
+ products[nproducts, 4]) > hfile
+ printf("#define\tPCMCIA_PRODUCT_%s_%s\t%s\n", products[nproducts, 1],
+ products[nproducts, 2], products[nproducts, 3]) > hfile
+
+ products[nproducts, 5] = collectline(f, line)
+
+ printf("#define\tPCMCIA_STR_%s_%s\t\"%s\"\n",
+ products[nproducts, 1], products[nproducts, 2],
+ products[nproducts, 5]) > hfile
+
+ next
+}
+{
+ if ($0 == "")
+ blanklines++
+ print $0 > hfile
+ if (blanklines < 2)
+ print $0 > dfile
+}
+END {
+ # print out the match tables
+
+ printf("\n") > dfile
+
+ printf("struct pcmcia_knowndev pcmcia_knowndevs[] = {\n") > dfile
+ for (i = 1; i <= nproducts; i++) {
+ printf("\t{\n") > dfile
+ if (products[i, 3] == -1) {
+ printf("\t PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_%s_%s,\n",
+ products[i, 1], products[i, 2]) > dfile
+ } else {
+ printf("\t PCMCIA_VENDOR_%s, PCMCIA_PRODUCT_%s_%s,\n",
+ products[i, 1], products[i, 1], products[i, 2]) > dfile
+ }
+ printf("\t PCMCIA_CIS_%s_%s,\n",
+ products[i, 1], products[i, 2]) > dfile
+ printf("\t ") > dfile
+ printf("0") > dfile
+ printf(",\n") > dfile
+
+ vendi = vendorindex[products[i, 1]];
+ printf("\t \"%s\",\n", vendors[vendi, 3]) > dfile
+ printf("\t \"%s\"\t},\n", products[i, 5]) > dfile
+ printf("\t},\n") > dfile
+ }
+ for (i = 1; i <= nvendors; i++) {
+ printf("\t{\n") > dfile
+ printf("\t PCMCIA_VENDOR_%s, 0,\n", vendors[i, 1]) > dfile
+ printf("\t PCMCIA_KNOWNDEV_NOPROD,\n") > dfile
+ printf("\t PCMCIA_CIS_INVALID,\n") > dfile
+ printf("\t \"%s\",\n", vendors[i, 3]) > dfile
+ printf("\t NULL,\n") > dfile
+ printf("\t},\n") > dfile
+ }
+ printf("\t{ 0, 0, { NULL, NULL, NULL, NULL }, 0, NULL, NULL, }\n") > dfile
+ printf("};\n") > dfile
+}
diff --git a/sys/dev/pcmcia/files.pcmcia b/sys/dev/pcmcia/files.pcmcia
index 63ea15a0192..b4fdf62187d 100644
--- a/sys/dev/pcmcia/files.pcmcia
+++ b/sys/dev/pcmcia/files.pcmcia
@@ -1,33 +1,50 @@
-# $OpenBSD: files.pcmcia,v 1.8 1997/08/20 17:09:10 angelos Exp $
-# $Id: files.pcmcia,v 1.8 1997/08/20 17:09:10 angelos Exp $
+# $OpenBSD: files.pcmcia,v 1.9 1998/09/11 10:47:14 fgsch Exp $
+# $NetBSD: files.pcmcia,v 1.9 1998/06/21 18:45:41 christos Exp $
#
# Config.new file and device description for machine-independent PCMCIA code.
# Included by ports that need it.
-# XXX Does this comment hold?
-# ports should define their own "device pcmcia" line (like the one below,
-# but with the correct bus attachment).
+device pcmcia {[function = -1], [irq = -1]}
+file dev/pcmcia/pcmcia.c pcmcia
+file dev/pcmcia/pcmcia_cis.c pcmcia
-#
-# needs all the parameters available on isa, so devices can attach here.
-#
+# device declaration in sys/conf/files
+attach pcmcia at pcic
-device pcmcia {[port = -1], [size = 0],
- [iomem = -1], [iosiz = 0],
- [irq = -1], [drq = -1], [slot = -1]}
-attach pcmcia at pcmciabus
+# 3Com 3c589 Ethernet and 3c562 multifunction Ethernet controllers
+# device declaration in sys/conf/files
+attach ep at pcmcia with ep_pcmcia
+file dev/pcmcia/if_ep_pcmcia.c ep_pcmcia
-file dev/pcmcia/pcmcia.c pcmcia needs-flag
-file dev/pcmcia/pcmcia_conf.c pcmcia
+# National Semiconductor DS8390/WD83C690-based boards
+# (NE[12]000, and clones)
+#attach ne at pcmcia with ne_pcmcia
+#file dev/pcmcia/if_ne_pcmcia.c ne_pcmcia
-# 8250/16[45]50-based "com" ports
-attach com at pcmcia with com_pcmcia
-file dev/pcmcia/com_pcmcia.c com_pcmcia
+# Adaptec APA-1460 SCSI Host Adapter
+attach aic at pcmcia with aic_pcmcia
+file dev/pcmcia/aic_pcmcia.c aic_pcmcia
-# 3Com 3c589 Ethernet controllers
-# device declaration in sys/conf/files
-attach ep at pcmcia with ep_pcmcia
-file dev/pcmcia/if_ep_pcmcia.c ep_pcmcia
+attach pccom at pcmcia with com_pcmcia
+file dev/pcmcia/com_pcmcia.c com_pcmcia
+
+# Digital RoamAbout / Lucent WaveLAN PCMCIA card
+#device wl: arp, ether, ifnet
+#attach wl at pcmcia with wl_pcmcia
+#file dev/pcmcia/if_wl_pcmcia.c wl_pcmcia
+
+# PCMCIA IDE controller
+#attach wdc at pcmcia with wdc_pcmcia
+#file dev/pcmcia/wdc_pcmcia.c wdc_pcmcia
+
+# SMC91Cxx Ethernet Controllers (i.e. Megahertz X-Jack)
+attach sm at pcmcia with sm_pcmcia
+file dev/pcmcia/if_sm_pcmcia.c sm_pcmcia
+
+# MB8696x Ethernet Controllers (i.e. TDK LAK CD021BX)
+#attach mbe at pcmcia with mbe_pcmcia
+#file dev/pcmcia/if_mbe_pcmcia.c mbe_pcmcia
-#attach wlp at pcmcia with wlp_pcmcia
-#file dev/pcmcia/if_wlp_pcmcia.c wlp_pcmcia
+# PCMCIA Floppy controller
+#attach fdc at pcmcia with fdc_pcmcia
+#file dev/pcmcia/fdc_pcmcia.c fdc_pcmcia
diff --git a/sys/dev/pcmcia/if_ep_pcmcia.c b/sys/dev/pcmcia/if_ep_pcmcia.c
index aeaa0937ad3..2f43037a872 100644
--- a/sys/dev/pcmcia/if_ep_pcmcia.c
+++ b/sys/dev/pcmcia/if_ep_pcmcia.c
@@ -1,9 +1,14 @@
-/* $OpenBSD: if_ep_pcmcia.c,v 1.8 1998/03/17 00:00:57 deraadt Exp $ */
+/* $OpenBSD: if_ep_pcmcia.c,v 1.9 1998/09/11 10:47:14 fgsch Exp $ */
+/* $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $ */
-/*
- * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -14,8 +19,40 @@
* 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 Herb Peyerl.
- * 4. The name of Herb Peyerl may not be used to endorse or promote products
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * 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
@@ -33,6 +70,7 @@
#include "bpfilter.h"
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
@@ -40,10 +78,8 @@
#include <sys/syslog.h>
#include <sys/select.h>
#include <sys/device.h>
-#include <sys/systm.h>
#include <net/if.h>
-#include <net/netisr.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/netisr.h>
@@ -56,6 +92,11 @@
#include <netinet/if_ether.h>
#endif
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
@@ -63,164 +104,289 @@
#include <machine/cpu.h>
#include <machine/bus.h>
+#include <machine/intr.h>
#include <dev/ic/elink3var.h>
#include <dev/ic/elink3reg.h>
-#include <dev/isa/isavar.h> /*XXX*/
+#include <dev/pcmcia/pcmciareg.h>
#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+int ep_pcmcia_match __P((struct device *, void *, void *));
+void ep_pcmcia_attach __P((struct device *, struct device *, void *));
-int ep_pcmcia_match __P((struct device *, void *, void *));
-void ep_pcmcia_attach __P((struct device *, struct device *, void *));
-int ep_pcmcia_detach __P((struct device *));
+int ep_pcmcia_get_enaddr __P((struct pcmcia_tuple *, void *));
+int ep_pcmcia_enable __P((struct ep_softc *));
+void ep_pcmcia_disable __P((struct ep_softc *));
-int ep_pcmcia_isasetup __P((struct device *, void *, void *,
- struct pcmcia_link *));
-int epmod __P((struct pcmcia_link *, struct device *, struct pcmcia_conf *,
- struct cfdata *));
-int ep_remove __P((struct pcmcia_link *, struct device *));
+int ep_pcmcia_enable1 __P((struct ep_softc *));
+void ep_pcmcia_disable1 __P((struct ep_softc *));
+
+struct ep_pcmcia_softc {
+ struct ep_softc sc_ep; /* real "ep" softc */
+
+ /* PCMCIA-specific goo */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+};
struct cfattach ep_pcmcia_ca = {
- sizeof(struct ep_softc), ep_pcmcia_match, ep_pcmcia_attach,
- ep_pcmcia_detach
+ sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach
+};
+
+struct ep_pcmcia_product {
+ u_int32_t epp_product; /* PCMCIA product ID */
+ u_short epp_chipset; /* 3Com chipset used */
+ int epp_flags; /* initial softc flags */
+ int epp_expfunc; /* expected function */
+ const char *epp_name; /* device name */
+} ep_pcmcia_products[] = {
+ { PCMCIA_PRODUCT_3COM_3C562, EP_CHIPSET_3C509,
+ 0, 0,
+ PCMCIA_STR_3COM_3C562 },
+ { PCMCIA_PRODUCT_3COM_3C589, EP_CHIPSET_3C509,
+ 0, 0,
+ PCMCIA_STR_3COM_3C589 },
+
+ { PCMCIA_PRODUCT_3COM_3C574, EP_CHIPSET_BOOMERANG,
+ EP_FLAGS_MII, 0,
+ PCMCIA_STR_3COM_3C574 },
+
+ { 0, 0,
+ 0, 0,
+ NULL },
};
-/* additional setup needed for pcmcia devices */
+struct ep_pcmcia_product *ep_pcmcia_lookup __P((struct pcmcia_attach_args *));
+
+struct ep_pcmcia_product *
+ep_pcmcia_lookup(pa)
+ struct pcmcia_attach_args *pa;
+{
+ struct ep_pcmcia_product *epp;
+
+ for (epp = ep_pcmcia_products; epp->epp_name != NULL; epp++)
+ if (pa->product == epp->epp_product &&
+ pa->pf->number == epp->epp_expfunc)
+ return (epp);
+
+ return (NULL);
+}
+
int
-ep_pcmcia_isasetup(parent, match, aux, pc_link)
- struct device *parent;
- void *match;
- void *aux;
- struct pcmcia_link *pc_link;
+ep_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
{
- struct ep_softc *sc = (void *) match;
- struct isa_attach_args *ia = aux;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- bus_space_tag_t iot = sc->sc_iot;
- bus_space_handle_t ioh = sc->sc_ioh;
- extern int ifqmaxlen;
-
- bus_space_write_2(iot, ioh, EP_COMMAND, WINDOW_SELECT | 0);
- bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
- bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
-
- /*
- * ok til here. Now try to figure out which link we have.
- * try coax first...
- */
-#ifdef EP_COAX_DEFAULT
- bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, 0xC000);
-#else
- /* COAX as default is reported to be a problem */
- bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, 0x0000);
-#endif
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ struct pcmcia_attach_args *pa = aux;
+
+ if (pa->manufacturer != PCMCIA_VENDOR_3COM)
+ return (0);
- ia->ia_iosize = 0x10;
- ia->ia_msize = 0;
+ if (ep_pcmcia_lookup(pa) != NULL)
+ return (1);
- sc->bustype = EP_BUS_PCMCIA;
- sc->pcmcia_flags = (pc_link->flags & PCMCIA_REATTACH) ? EP_REATTACH:0;
- return 1;
+ return (0);
}
-/* modify config entry */
int
-epmod(pc_link, self, pc_cf, cf)
- struct pcmcia_link *pc_link;
- struct device *self;
- struct pcmcia_conf *pc_cf;
- struct cfdata *cf;
+ep_pcmcia_enable(sc)
+ struct ep_softc *sc;
{
- int err;
-/* struct pcmciadevs *dev = pc_link->device;*/
-/* struct ep_softc *sc = (void *) self;*/
-
- if ((err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self, pc_cf,
- cf)) != 0) {
- printf("bus_config failed %d\n", err);
- return err;
- }
+ struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
+ struct pcmcia_function *pf = psc->sc_pf;
- if (pc_cf->io[0].len > 0x10)
- pc_cf->io[0].len = 0x10;
-#if 0
- pc_cf->cfgtype = DOSRESET;
-#endif
- pc_cf->cfgtype = 1;
+ /* establish the interrupt. */
+ sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, epintr, sc);
+ if (sc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt\n",
+ sc->sc_dev.dv_xname);
+ return (1);
+ }
- return 0;
+ return (ep_pcmcia_enable1(sc));
}
int
-ep_remove(pc_link, self)
- struct pcmcia_link *pc_link;
- struct device *self;
+ep_pcmcia_enable1(sc)
+ struct ep_softc *sc;
{
- struct ep_softc *sc = (void *) self;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
-
- if_down(ifp);
- epstop(sc);
- ifp->if_flags &= ~(IFF_RUNNING | IFF_UP);
- sc->pcmcia_flags = EP_ABSENT;
- return PCMCIA_BUS_UNCONFIG(pc_link->adapter, pc_link);
+ struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
+ struct pcmcia_function *pf = psc->sc_pf;
+ int ret;
+
+ if ((ret = pcmcia_function_enable(pf)))
+ return (ret);
+
+ if (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) {
+ int reg;
+
+ /* turn off the serial-disable bit */
+
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
+ if (reg & 0x08) {
+ reg &= ~0x08;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
+ }
+
+ }
+
+ return (ret);
}
-static struct pcmcia_3com {
- struct pcmcia_device pcd;
-} pcmcia_3com = {
- {
- "PCMCIA 3COM 3C589", epmod,
- ep_pcmcia_isasetup, NULL, ep_remove
- },
-};
+void
+ep_pcmcia_disable(sc)
+ struct ep_softc *sc;
+{
+ struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
-struct pcmciadevs pcmcia_ep_devs[] = {
- {
- "ep", 0, "3Com Corporation", "3C589",
- NULL, NULL,
- (void *) -1, (void *) &pcmcia_3com
- },
-};
+ ep_pcmcia_disable1(sc);
+ pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
+}
-int
-ep_pcmcia_match(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+void
+ep_pcmcia_disable1(sc)
+ struct ep_softc *sc;
{
- return pcmcia_slave_match(parent, match, aux, pcmcia_ep_devs,
- sizeof(pcmcia_ep_devs)/sizeof(pcmcia_ep_devs[0]));
+ struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
+
+ pcmcia_function_disable(psc->sc_pf);
}
void
ep_pcmcia_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+ struct device *parent, *self;
+ void *aux;
{
- struct ep_softc *sc = (void *)self;
- struct isa_attach_args *ia = aux;
- bus_space_tag_t iot = ia->ia_iot;
- bus_space_handle_t ioh;
-
- if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
- panic("ep_isa_attach: can't map i/o space");
-
- sc->sc_iot = iot;
- sc->sc_ioh = ioh;
-
- epconfig(sc, EP_CHIPSET_3C509);
- sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq,
- IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname);
+ struct ep_pcmcia_softc *psc = (void *) self;
+ struct ep_softc *sc = &psc->sc_ep;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ struct ep_pcmcia_product *epp;
+ u_int8_t myla[ETHER_ADDR_LEN];
+ u_int8_t *enaddr = NULL;
+ int i;
+
+ psc->sc_pf = pa->pf;
+ cfe = pa->pf->cfe_head.sqh_first;
+
+ /* Enable the card. */
+ pcmcia_function_init(pa->pf, cfe);
+ if (ep_pcmcia_enable1(sc))
+ printf(": function enable failed\n");
+
+#ifdef notyet
+ sc->enabled = 1;
+#endif
+
+ if (cfe->num_memspace != 0)
+ printf(": unexpected number of memory spaces %d should be 0\n",
+ cfe->num_memspace);
+
+ if (cfe->num_iospace != 1)
+ printf(": unexpected number of I/O spaces %d should be 1\n",
+ cfe->num_iospace);
+
+ if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
+ bus_addr_t maxaddr = (pa->pf->sc->iobase + pa->pf->sc->iosize);
+
+ for (i = pa->pf->sc->iobase; i < maxaddr; i += 0x10) {
+ /*
+ * the 3c562 can only use 0x??00-0x??7f
+ * according to the Linux driver
+ */
+ if (i & 0x80)
+ continue;
+ if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
+ 0, &psc->sc_pcioh) == 0)
+ break;
+ }
+ if (i >= maxaddr) {
+ printf(": can't allocate i/o space\n");
+ return;
+ }
+ } else {
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh))
+ printf(": can't allocate i/o space\n");
+ }
+
+ sc->sc_iot = psc->sc_pcioh.iot;
+ sc->sc_ioh = psc->sc_pcioh.ioh;
+
+ if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, cfe->iospace[0].length,
+ &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ switch (pa->product) {
+ case PCMCIA_PRODUCT_3COM_3C562:
+ /*
+ * 3c562a-c use this; 3c562d does it in the regular way.
+ * we might want to check the revision and produce a warning
+ * in the future.
+ */
+ /* FALLTHROUGH */
+ case PCMCIA_PRODUCT_3COM_3C574:
+ /*
+ * Apparently, some 3c574s do it this way, as well.
+ */
+ if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla))
+ enaddr = myla;
+ break;
+ }
+
+ sc->bustype = EP_BUS_PCMCIA;
+
+ epp = ep_pcmcia_lookup(pa);
+ if (epp == NULL)
+ panic("ep_pcmcia_attach: impossible");
+
+ printf(": %s\n", epp->epp_name);
+
+#ifdef notyet
+ sc->enable = ep_pcmcia_enable;
+ sc->disable = ep_pcmcia_disable;
+#endif
+
+ epconfig(sc, epp->epp_chipset, enaddr);
+
+ /* establish the interrupt. */
+ sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, epintr, sc);
+ if (sc->sc_ih == NULL)
+ printf("%s: couldn't establish interrupt\n",
+ sc->sc_dev.dv_xname);
+
+#ifdef notyet
+ sc->enabled = 0;
+
+ ep_pcmcia_disable1(sc);
+#endif
}
-/*
- * No detach; network devices are too well linked into the rest of the
- * kernel.
- */
int
-ep_pcmcia_detach(self)
- struct device *self;
+ep_pcmcia_get_enaddr(tuple, arg)
+ struct pcmcia_tuple *tuple;
+ void *arg;
{
- return EBUSY;
+ u_int8_t *myla = arg;
+ int i;
+
+ /* this is 3c562a-c magic */
+ if (tuple->code == 0x88) {
+ if (tuple->length < ETHER_ADDR_LEN)
+ return (0);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
+ myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
+ myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
+ }
+
+ return (1);
+ }
+ return (0);
}
diff --git a/sys/dev/pcmcia/if_sm_pcmcia.c b/sys/dev/pcmcia/if_sm_pcmcia.c
new file mode 100644
index 00000000000..b789eef3c51
--- /dev/null
+++ b/sys/dev/pcmcia/if_sm_pcmcia.c
@@ -0,0 +1,357 @@
+/* $OpenBSD: if_sm_pcmcia.c,v 1.1 1998/09/11 10:47:14 fgsch Exp $ */
+/* $NetBSD: if_sm_pcmcia.c,v 1.11 1998/08/15 20:47:32 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/select.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#endif
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#ifdef __NetBSD__
+#include <netinet/if_inarp.h>
+#else
+#include <netinet/if_ether.h>
+#endif
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/ic/smc91cxxreg.h>
+#include <dev/ic/smc91cxxvar.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciadevs.h>
+
+int sm_pcmcia_match __P((struct device *, void *, void *));
+void sm_pcmcia_attach __P((struct device *, struct device *, void *));
+
+struct sm_pcmcia_softc {
+ struct smc91cxx_softc sc_smc; /* real "smc" softc */
+
+ /* PCMCIA-specific goo. */
+ struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
+ int sc_io_window; /* our i/o window */
+ void *sc_ih; /* interrupt cookie */
+ struct pcmcia_function *sc_pf; /* our PCMCIA function */
+};
+
+struct cfattach sm_pcmcia_ca = {
+ sizeof(struct sm_pcmcia_softc), sm_pcmcia_match, sm_pcmcia_attach
+};
+
+int sm_pcmcia_enable __P((struct smc91cxx_softc *));
+void sm_pcmcia_disable __P((struct smc91cxx_softc *));
+
+int sm_pcmcia_ascii_enaddr __P((const char *, u_int8_t *));
+int sm_pcmcia_funce_enaddr __P((struct device *, u_int8_t *));
+
+int sm_pcmcia_lannid_ciscallback __P((struct pcmcia_tuple *, void *));
+
+struct sm_pcmcia_product {
+ u_int32_t spp_vendor; /* vendor ID */
+ u_int32_t spp_product; /* product ID */
+ int spp_expfunc; /* expected function */
+ const char *spp_name; /* product name */
+} sm_pcmcia_products[] = {
+ { PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJACK,
+ 0, PCMCIA_STR_MEGAHERTZ2_XJACK },
+
+ { PCMCIA_VENDOR_NEWMEDIA, PCMCIA_PRODUCT_NEWMEDIA_BASICS,
+ 0, PCMCIA_STR_NEWMEDIA_BASICS },
+
+#if 0
+ { PCMCIA_VENDOR_SMC, PCMCIA_PRODUCT_SMC_8020BT,
+ 0, PCMCIA_STR_SMC_8020BT },
+#endif
+
+ { 0, 0,
+ 0, NULL },
+};
+
+struct sm_pcmcia_product *sm_pcmcia_lookup __P((struct pcmcia_attach_args *));
+
+struct sm_pcmcia_product *
+sm_pcmcia_lookup(pa)
+ struct pcmcia_attach_args *pa;
+{
+ struct sm_pcmcia_product *spp;
+
+ for (spp = sm_pcmcia_products; spp->spp_name != NULL; spp++)
+ if (pa->manufacturer == spp->spp_vendor &&
+ pa->product == spp->spp_product &&
+ pa->pf->number == spp->spp_expfunc)
+ return (spp);
+ return (NULL);
+}
+
+int
+sm_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct pcmcia_attach_args *pa = aux;
+
+ if (sm_pcmcia_lookup(pa) != NULL)
+ return (1);
+ return (0);
+}
+
+void
+sm_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)self;
+ struct smc91cxx_softc *sc = &psc->sc_smc;
+ struct pcmcia_attach_args *pa = aux;
+ struct pcmcia_config_entry *cfe;
+ u_int8_t myla[ETHER_ADDR_LEN], *enaddr = NULL;
+ struct sm_pcmcia_product *spp;
+
+ psc->sc_pf = pa->pf;
+ cfe = pa->pf->cfe_head.sqh_first;
+
+ /* Enable the card. */
+ pcmcia_function_init(pa->pf, cfe);
+ if (pcmcia_function_enable(pa->pf)) {
+ printf(": function enable failed\n");
+ return;
+ }
+
+ /* XXX sanity check number of mem and i/o spaces */
+
+ /* Allocate and map i/o space for the card. */
+ if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
+ cfe->iospace[0].length, &psc->sc_pcioh)) {
+ printf(": can't allocate i/o space\n");
+ return;
+ }
+
+ sc->sc_bst = psc->sc_pcioh.iot;
+ sc->sc_bsh = psc->sc_pcioh.ioh;
+
+ sc->sc_enable = sm_pcmcia_enable;
+ sc->sc_disable = sm_pcmcia_disable;
+
+ if (pcmcia_io_map(pa->pf, (cfe->flags & PCMCIA_CFE_IO16) ?
+ PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8, 0, cfe->iospace[0].length,
+ &psc->sc_pcioh, &psc->sc_io_window)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ spp = sm_pcmcia_lookup(pa);
+ if (spp == NULL)
+ panic("sm_pcmcia_attach: impossible");
+
+ printf(": %s\n", spp->spp_name);
+
+ /*
+ * First try to get the Ethernet address from FUNCE/LANNID tuple.
+ */
+ if (sm_pcmcia_funce_enaddr(parent, myla))
+ enaddr = myla;
+
+ /*
+ * If that failed, try one of the CIS info strings.
+ */
+ if (enaddr == NULL) {
+ char *cisstr = NULL;
+
+ switch (pa->manufacturer) {
+ case PCMCIA_VENDOR_MEGAHERTZ2:
+ cisstr = pa->pf->sc->card.cis1_info[3];
+ break;
+
+ case PCMCIA_VENDOR_SMC:
+ cisstr = pa->pf->sc->card.cis1_info[2];
+ break;
+ }
+
+ if (cisstr != NULL && sm_pcmcia_ascii_enaddr(cisstr, myla))
+ enaddr = myla;
+ }
+
+ if (enaddr == NULL)
+ printf("%s: unable to get Ethernet address\n",
+ sc->sc_dev.dv_xname);
+
+ /* Perform generic intialization. */
+ smc91cxx_attach(sc, enaddr);
+
+ pcmcia_function_disable(pa->pf);
+}
+
+int
+sm_pcmcia_ascii_enaddr(cisstr, myla)
+ const char *cisstr;
+ u_int8_t *myla;
+{
+ char enaddr_str[12];
+ int i, j;
+
+ if (strlen(cisstr) != 12) {
+ /* Bogus address! */
+ return (0);
+ }
+ bcopy(cisstr, enaddr_str, 12);
+ bzero(myla, sizeof(myla));
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 2; j++) {
+ /* Convert to upper case. */
+ if (enaddr_str[(i * 2) + j] >= 'a' &&
+ enaddr_str[(i * 2) + j] <= 'z')
+ enaddr_str[(i * 2) + j] -= 'a' - 'A';
+
+ /* Parse the digit. */
+ if (enaddr_str[(i * 2) + j] >= '0' &&
+ enaddr_str[(i * 2) + j] <= '9')
+ myla[i] |= enaddr_str[(i * 2) + j]
+ - '0';
+ else if (enaddr_str[(i * 2) + j] >= 'A' &&
+ enaddr_str[(i * 2) + j] <= 'F')
+ myla[i] |= enaddr_str[(i * 2) + j]
+ - 'A' + 10;
+ else {
+ /* Bogus digit!! */
+ return (0);
+ }
+
+ /* Compensate for ordering of digits. */
+ if (j == 0)
+ myla[i] <<= 4;
+ }
+ }
+
+ return (1);
+}
+
+int
+sm_pcmcia_funce_enaddr(parent, myla)
+ struct device *parent;
+ u_int8_t *myla;
+{
+
+ return (pcmcia_scan_cis(parent, sm_pcmcia_lannid_ciscallback, myla));
+}
+
+int
+sm_pcmcia_lannid_ciscallback(tuple, arg)
+ struct pcmcia_tuple *tuple;
+ void *arg;
+{
+ u_int8_t *myla = arg;
+ int i;
+
+ if (tuple->code == PCMCIA_CISTPL_FUNCE) {
+ /* subcode, length */
+ if (tuple->length < 2)
+ return (0);
+
+ if ((pcmcia_tuple_read_1(tuple, 0) !=
+ PCMCIA_TPLFE_TYPE_LAN_NID) ||
+ (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN))
+ return (0);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
+ return (1);
+ }
+ return (0);
+}
+
+int
+sm_pcmcia_enable(sc)
+ struct smc91cxx_softc *sc;
+{
+ struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
+
+ /* Establish the interrupt handler. */
+ psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, smc91cxx_intr,
+ sc);
+ if (psc->sc_ih == NULL) {
+ printf("%s: couldn't establish interrupt handler\n",
+ sc->sc_dev.dv_xname);
+ return (1);
+ }
+
+ return (pcmcia_function_enable(psc->sc_pf));
+}
+
+void
+sm_pcmcia_disable(sc)
+ struct smc91cxx_softc *sc;
+{
+ struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
+
+ pcmcia_function_disable(psc->sc_pf);
+
+ pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
+}
diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c
index 16a80a669bd..c7539c7a1f3 100644
--- a/sys/dev/pcmcia/pcmcia.c
+++ b/sys/dev/pcmcia/pcmcia.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pcmcia.c,v 1.10 1997/08/19 21:59:49 angelos Exp $ */
+/* $OpenBSD: pcmcia.c,v 1.11 1998/09/11 10:47:14 fgsch Exp $ */
+/* $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $ */
/*
- * Copyright (c) 1996 John T. Kohl. All rights reserved.
- * Copyright (c) 1994 Stefan Grefen. All rights reserved.
+ * 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
@@ -14,8 +14,7 @@
* 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 Charles Hannum.
- * This product includes software developed by Stefan Grefen.
+ * 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.
*
@@ -29,1340 +28,777 @@
* 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.
- *
*/
-/*
- * XXX - these next two lines are just "glue" until the confusion over
- * pcmcia vs pcmciabus between the framework and sys/conf/files
- * gets resolved
- */
-#define pcmciabus_cd pcmcia_cd
-#define pcmciabus_ca pcmcia_ca
-
-/*
- * derived from scsiconf.c writte by Julian Elischer et al
- * TODO add modload support and loadable lists of devices
- */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
#include <sys/device.h>
-#include <sys/ioctl.h>
-#include <sys/fcntl.h>
-#include <sys/proc.h>
-#include <dev/pcmcia/pcmciavar.h>
+/* XXX only needed for intr debugging */
+#include <vm/vm.h>
+
#include <dev/pcmcia/pcmciareg.h>
-#include <dev/pcmcia/pcmcia_ioctl.h>
+#include <dev/pcmcia/pcmciachip.h>
+#include <dev/pcmcia/pcmciavar.h>
-#ifdef IBM_WD
-#define PCMCIA_DEBUG
-#endif
-#ifdef PCMCIA_DEBUG
-# define PPRINTF(a) printf a
+#ifdef PCMCIADEBUG
+int pcmcia_debug = 1;
+#define DPRINTF(arg) if (pcmcia_debug) printf arg
#else
-# define PPRINTF(a)
+#define DPRINTF(arg)
#endif
-#ifdef PCMCIA_DEBUG
-void pcmciadumpcf __P((struct pcmcia_conf *));
+#ifdef PCMCIAVERBOSE
+int pcmcia_verbose = 1;
+#else
+int pcmcia_verbose = 0;
#endif
-static struct old_devs {
- struct device *dev;
- struct pcmciadevs *pcdev;
-} *deldevs;
-static int ndeldevs = 0;
-
-#define PCMCIA_SERVICE(a,b,c,d,e) ((a)->chip_link->pcmcia_service(b,c,\
- (void *) d,e))
-#define PCMCIA_MAP_IO(a,b,c,d,e) ((a)->chip_link->pcmcia_map_io(b,c,d,e))
-#define PCMCIA_MAP_INTR(a,b,c,d) ((a)->chip_link->pcmcia_map_intr(b,c,d))
-/*
- * XXX
- * this is quite broken in the face of various bus mapping stuff...
- * drivers need to cooperate with the pcmcia framework to deal with
- * bus mapped memory. Whee.
- */
-#define PCMCIA_MAP_MEM(a,b,c,d,e,f,g) ((a)->chip_link->pcmcia_map_mem(b,c,d,e,f,g))
-
-#define SCRATCH_MEM(a) ((caddr_t)(a)->scratch_memh)
-#define SCRATCH_MEMT(a) ((a)->pa_memt)
-#define SCRATCH_SIZE(a) ((a)->scratch_memsiz)
-#define SCRATCH_INUSE(a)((a)->scratch_inuse)
-
-/*
- * Declarations
- */
-int pcmcia_probedev __P((struct pcmcia_link *, struct pcmcia_cardinfo *));
-int pcmcia_probe_bus __P((int, int));
-int pcmciabusmatch __P((struct device *, void *, void *));
-void pcmciabusattach __P((struct device *, struct device *, void *));
-int pcmcia_mapcard __P((struct pcmcia_link *, int, struct pcmcia_conf *));
-int pcmcia_mapcard_and_configure __P((struct pcmcia_link *, int,
- struct pcmcia_conf *));
-
-int pcmcia_unconfigure __P((struct pcmcia_link *));
-int pcmcia_unmapcard __P((struct pcmcia_link *));
+int pcmcia_match __P((struct device *, void *, void *));
+int pcmcia_submatch __P((struct device *, void *, void *));
+void pcmcia_attach __P((struct device *, struct device *, void *));
+int pcmcia_print __P((void *, const char *));
-int pcmcia_print __P((void *, const char *));
-int pcmcia_submatch __P((struct device *, void *, void *));
-void pcmcia_probe_link __P((struct pcmcia_link *));
+static inline void pcmcia_socket_enable __P((pcmcia_chipset_tag_t,
+ pcmcia_chipset_handle_t *));
+static inline void pcmcia_socket_disable __P((pcmcia_chipset_tag_t,
+ pcmcia_chipset_handle_t *));
-void pcmcia_detach __P((struct device *, void *));
-
-struct cfattach pcmcia_ca = {
- sizeof(struct pcmciabus_softc), pcmciabusmatch, pcmciabusattach,
-};
+int pcmcia_card_intr __P((void *));
struct cfdriver pcmcia_cd = {
- NULL, "pcmcia", DV_DULL, 1
+ NULL, "pcmcia", DV_DULL
};
-int pcmciaopen __P((dev_t, int, int, struct proc *));
-int pcmciaclose __P((dev_t, int, int, struct proc *));
-int pcmciachip_ioctl __P((int, int, caddr_t));
-int pcmciaslot_ioctl __P((struct pcmcia_link *, int, int, caddr_t));
-int pcmciaioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
-int pcmciaselect __P((dev_t, int, struct proc *));
-int pcmciammap __P((dev_t, int, int));
-
-#if 0
-int
-pcmcia_register(adapter_softc, bus_link, chip_link, slot)
- void *adapter_softc;
- struct pcmciabus_link *bus_link;
- struct pcmcia_funcs *chip_link;
- int slot;
-{
- PPRINTF(("- pcmcia_register\n"));
- if (pcmcia_cntrl == 0)
- bzero(pcmcia_drivers, sizeof(pcmcia_drivers));
-
- if (pcmcia_cntrl < 4) {
- pcmcia_drivers[slot].adapter_softc = adapter_softc;
- pcmcia_drivers[slot].chip_link = chip_link;
- pcmcia_drivers[slot].bus_link = bus_link;
- pcmcia_cntrl++;
- return 1;
- }
- return 0;
-}
-#endif
+struct cfattach pcmcia_ca = {
+ sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
+};
int
-pcmciabusmatch(parent, self, aux)
- struct device *parent;
- void *self;
- void *aux;
+pcmcia_ccr_read(pf, ccr)
+ struct pcmcia_function *pf;
+ int ccr;
{
- struct pcmciabus_softc *sc = (void *)self;
- struct cfdata *cf = sc->sc_dev.dv_cfdata;
- struct pcmciabus_attach_args *pba = aux;
- struct pcmcia_adapter *pca = pba->pba_aux;
- int found = 0;
- PPRINTF(("- pcmciabusmatch %p %p\n", pba, pca));
-
- if (pca->bus_link) {
- if (PCMCIA_BUS_INIT(pca, parent, cf, aux, pca, 0))
- found++;
- }
- return found != 0;
+ return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
+ pf->pf_ccr_offset + ccr));
}
-/*
- * The routine called by the adapter boards to get all their
- * devices configured in.
- */
void
-pcmciabusattach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+pcmcia_ccr_write(pf, ccr, val)
+ struct pcmcia_function *pf;
+ int ccr;
+ int val;
{
- struct pcmciabus_softc *sc = (struct pcmciabus_softc *) self;
- struct cfdata *cf = self->dv_cfdata;
- struct pcmciabus_attach_args *pba = aux;
- struct pcmcia_adapter *pca = pba->pba_aux;
-
- PPRINTF(("- pcmciabusattach\n"));
- if (pca->bus_link) {
- PCMCIA_BUS_INIT(pca, parent, cf, aux, pca, 1);
- }
- printf("\n");
- sc->sc_driver = pca;
- sc->sc_iot = pba->pba_iot;
- sc->sc_memt = pba->pba_memt;
- pcmcia_probe_bus(sc->sc_dev.dv_unit, -1);
+ if ((pf->ccr_mask) & (1 << (ccr / 2))) {
+ bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
+ pf->pf_ccr_offset + ccr, val);
+ }
}
-/*
- * Probe the requested pcmcia bus. It must be already set up.
- * -1 requests all set up pcmcia busses.
- */
-int pcmcia_probe_busses __P((int, int));
-
int
-pcmcia_probe_busses(bus, slot)
- int bus, slot;
+pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
{
- PPRINTF(("- pcmcia_probe_busses\n"));
- if (bus == -1) {
- for (bus = 0; bus < pcmciabus_cd.cd_ndevs; bus++)
- if (pcmciabus_cd.cd_devs[bus])
- pcmcia_probe_bus(bus, slot);
- return 0;
- } else {
- return pcmcia_probe_bus(bus, slot);
- }
+ /* if the autoconfiguration got this far, there's a socket here */
+ return (1);
}
-/* Macros to clear/set/test flags. */
-#define SET(t, f) (t) |= (f)
-#define CLR(t, f) (t) &= ~(f)
-#define ISSET(t, f) ((t) & (f))
-
-/*
- * Probe the requested pcmcia bus. It must be already set up.
- */
-int
-pcmcia_probe_bus(bus, slot)
- int bus, slot;
+void
+pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
{
- struct pcmciabus_softc *pcmcia;
- int maxslot, minslot;
- struct pcmcia_link *link;
-
- PPRINTF(("- pcmcia_probe_bus\n"));
- if (bus < 0 || bus >= pcmciabus_cd.cd_ndevs)
- return ENXIO;
- pcmcia = pcmciabus_cd.cd_devs[bus];
- if (!pcmcia || pcmcia->sc_driver == NULL) /* bus is not configured */
- return ENXIO;
-
- if (slot == -1) {
- maxslot = pcmcia->sc_driver->nslots - 1;
- minslot = 0;
- } else {
- if (slot < 0 || slot >= pcmcia->sc_driver->nslots)
- return EINVAL;
- maxslot = minslot = slot;
- }
+ struct pcmciabus_attach_args *paa = aux;
+ struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
- for (slot = minslot; slot <= maxslot; slot++) {
- if ((link = pcmcia->sc_link[slot])) {
- if (link->devp)
- continue;
- }
+ printf("\n");
- /*
- * If we presently don't have a link block
- * then allocate one
- */
- if (!link) {
- pcmcia->sc_link[slot] = link =
- malloc(sizeof(*link), M_TEMP, M_NOWAIT);
- if (link == NULL)
- return ENOMEM;
- bzero(link, sizeof(*link));
- link->opennings = 1;
- link->adapter = pcmcia->sc_driver;
- link->bus = pcmcia;
- link->slot = slot;
- }
- (void) pcmcia_probe_link(link);
- }
- return 0;
+ sc->pct = paa->pct;
+ sc->pch = paa->pch;
+ sc->iobase = paa->iobase;
+ sc->iosize = paa->iosize;
+
+ sc->ih = NULL;
}
-void
-pcmcia_probe_link(link)
- struct pcmcia_link *link;
+int
+pcmcia_card_attach(dev)
+ struct device *dev;
{
- struct pcmcia_cardinfo cardinfo;
+ struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
+ struct pcmcia_function *pf;
struct pcmcia_attach_args paa;
- struct pcmciabus_softc *pcmcia = link->bus;
- int i;
+ int attached;
- PPRINTF(("- pcmcia_probe_link %p\n", link));
/*
- * Set up card and fetch card info.
+ * this is here so that when socket_enable calls gettype, trt happens
*/
- if (pcmcia_probedev(link, &cardinfo) == 0) {
- /* could not fetch its strings, so give up on it. */
- PCMCIA_SERVICE(link->adapter,
- link, PCMCIA_OP_POWER,
- 0, 0);
- return;
- }
+ sc->card.pf_head.sqh_first = NULL;
- /*
- * See if we can reattach a device.
- */
- CLR(link->flags, PCMCIA_ATTACH_TYPE);
- SET(link->flags, PCMCIA_REATTACH);
- for (i = 0; i < ndeldevs; i++) {
- if (deldevs[i].dev) {
- PPRINTF(("trying device\n"));
- link->device = deldevs[i].pcdev;
- if (pcmcia_configure(deldevs[i].dev->dv_parent,
- deldevs[i].dev, link)) {
- CLR(link->flags, PCMCIA_ATTACH_TYPE);
- SET(link->flags, PCMCIA_SLOT_INUSE);
- deldevs[i].dev = NULL;
- deldevs[i].pcdev = NULL;
- return;
- }
- }
- }
+ pcmcia_chip_socket_enable(sc->pct, sc->pch);
+ pcmcia_read_cis(sc);
- paa.paa_cardinfo = &cardinfo;
- paa.paa_link = link;
- paa.paa_aux = NULL;
- paa.paa_bestmatch = 0;
- paa.paa_matchonly = 1;
- CLR(link->flags, PCMCIA_ATTACH_TYPE);
- SET(link->flags, PCMCIA_ATTACH);
+ pcmcia_chip_socket_disable(sc->pct, sc->pch);
/*
- * Run the config matching routines to find us a good match.
- * match routines will flag on "matchonly" and fill in stuff
- * into the link structure, but not return any match.
+ * bail now if the card has no functions, or if there was an error in
+ * the cis.
*/
- (void) config_found_sm(&pcmcia->sc_dev,
- &paa,
- pcmcia_print,
- pcmcia_submatch);
-
- if (PCMCIA_BUS_SEARCH(link->adapter,
- &pcmcia->sc_dev,
- link, NULL)) {
- CLR(link->flags, PCMCIA_ATTACH_TYPE);
- SET(link->flags, PCMCIA_SLOT_INUSE);
- } else {
- CLR(link->flags, PCMCIA_ATTACH_TYPE|PCMCIA_SLOT_INUSE);
- link->device = NULL;
- printf("%s slot %d: No matching config entry.\n",
- pcmcia->sc_dev.dv_xname,
- link->slot);
- PCMCIA_SERVICE(link->adapter,
- link, PCMCIA_OP_POWER,
- 0, 0);
- link->fordriver = NULL;
- }
- return;
-}
-/*
- * given a target ask the device what
- * it is, and find the correct driver table
- * entry.
- */
-int
-pcmcia_probedev(link, cardinfo)
- struct pcmcia_link *link;
- struct pcmcia_cardinfo *cardinfo;
-{
- struct pcmcia_adapter *pca = link->adapter;
- u_char scratch[CIS_MAXSIZE];
- int card_stat;
- int err;
- int pow = 0;
- int slot = link->slot;
-
- PPRINTF(("- pcmcia_probe_dev\n"));
-
- printf("%s slot %d: ", ((struct device *) link->bus)->dv_xname, slot);
-
- /* turn off power in case it's on, to get a fresh start on things: */
- PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 0, 0);
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
- &card_stat, 0)) != 0) {
- printf("failed to get status %d\n", err);
- return NULL;
- }
+ if (sc->card.error)
+ return (1);
+ if (sc->card.pf_head.sqh_first == NULL)
+ return (1);
- if (ISSET(card_stat, PCMCIA_CARD_PRESENT) == 0) {
- printf("empty\n");
- return NULL;
- }
+ if (pcmcia_verbose)
+ pcmcia_print_cis(sc);
- if (!ISSET(card_stat, PCMCIA_POWER)) {
- pow = 1;
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 10000,
- PCMCIA_POWER_ON|
- PCMCIA_POWER_5V)) != 0) {
- printf("failed to turn on power %d\n", err);
- return NULL;
- }
- }
+ attached = 0;
- if (!ISSET(link->flags, (PCMCIA_SLOT_INUSE | CARD_IS_MAPPED))) {
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_RESET,
- 500000, 0)) != 0) {
- printf("failed to reset %d\n", err);
- PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 0, 0);
- return NULL;
- }
- }
+ for (pf = sc->card.pf_head.sqh_first; pf != NULL;
+ pf = pf->pf_list.sqe_next) {
+ if (pf->cfe_head.sqh_first == NULL)
+ continue;
- /*
- * Ask the device what it is
- */
- if ((err = pcmcia_read_cis(link, scratch, 0, sizeof(scratch))) != 0) {
- printf("failed to read cis info %d\n", err);
- goto bad;
+ pf->sc = sc;
+ pf->cfe = NULL;
+ pf->ih_fct = NULL;
+ pf->ih_arg = NULL;
}
- if ((err = pcmcia_get_cisver1(link, scratch, sizeof(scratch),
- cardinfo->manufacturer,
- cardinfo->model, cardinfo->add_info1,
- cardinfo->add_info2)) != 0) {
- printf("failed to get cis info %d\n", err);
- goto bad;
+ for (pf = sc->card.pf_head.sqh_first; pf != NULL;
+ pf = pf->pf_list.sqe_next) {
+ if (pf->cfe_head.sqh_first == NULL)
+ continue;
+
+ paa.manufacturer = sc->card.manufacturer;
+ paa.product = sc->card.product;
+ paa.card = &sc->card;
+ paa.pf = pf;
+
+ if (config_found_sm(&sc->dev, &paa, pcmcia_print,
+ pcmcia_submatch)) {
+ attached++;
+
+ DPRINTF(("%s: function %d CCR at %d "
+ "offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
+ sc->dev.dv_xname, pf->number,
+ pf->pf_ccr_window, pf->pf_ccr_offset,
+ pcmcia_ccr_read(pf, 0x00),
+ pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
+ pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
+ pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
+ pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
+ }
}
- printf("<%s, %s", cardinfo->manufacturer, cardinfo->model);
- if (cardinfo->add_info1[0])
- printf(", %s", cardinfo->add_info1);
- if (cardinfo->add_info2[0])
- printf(", %s", cardinfo->add_info2);
- printf(">\n");
-
- return 1;
-bad:
- if (!pow)
- PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 0, 0);
- return 0;
+ return (attached ? 0 : 1);
+}
+
+void
+pcmcia_card_detach(dev)
+ struct device *dev;
+{
+ /* struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
+ /* don't do anything yet */
}
int
-pcmcia_configure(parent, self, aux)
- struct device *parent;
- void *self;
- void *aux;
+pcmcia_submatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
{
- struct device *dev = self;
- struct pcmcia_link *link = aux;
- struct cfdata *cf = dev->dv_cfdata;
- struct cfdriver *cd = cf->cf_driver;
- struct pcmciadevs *pcs = link->device;
- struct pcmcia_device *pcd;
- struct pcmcia_adapter *pca = link->adapter;
- struct pcmcia_conf pc_cf;
- char *devname = (char *) link->fordriver;
- u_char scratch[CIS_MAXSIZE];
- int mymap = 0;
-
- PPRINTF(("- pcmcia_configure\n"));
-
- if ((devname && strcmp(devname, cd->cd_name)) || !pca)
- return 0;
-
- if (link->devp)
- return 0; /* something else already attached */
-
- if (pcs == NULL)
- pcd = NULL;
- else
- pcd = pcs->dev;
-
- PPRINTF(("pcmcia_configure: %p\n", pcd));
- if (!ISSET(link->flags, CARD_IS_MAPPED)) {
- /* read 'suggested' configuration */
- PPRINTF(("pcmcia_configure: calling read cis\n"));
- if (pcmcia_read_cis(link, scratch, 0, sizeof(scratch)) != 0)
- return 0;
-
- bzero(&pc_cf, sizeof(pc_cf));
-
- PPRINTF(("pcmcia_configure: calling get cf\n"));
- if (pcmcia_get_cf(link, scratch, sizeof(scratch), -1,
- &pc_cf) != 0)
- return 0;
-#ifdef PCMCIA_DEBUG
- pcmciadumpcf(&pc_cf);
-#endif
- /* and modify it (device specific) */
- if (pcd && pcd->pcmcia_config) {
- PPRINTF(("pcmcia_configure: calling config %p %p\n",
- pcd, pcd->pcmcia_config));
- if ((*pcd->pcmcia_config)(link, dev, &pc_cf, cf))
- return 0;
-
- if ((pc_cf.cfgtype & CFGENTRYMASK) == CFGENTRYID) {
- PPRINTF(("pcmcia_configure: calling cf2\n"));
- if (pcmcia_get_cf(link, scratch,
- sizeof(scratch), -2,
- &pc_cf) != 0)
- return 0;
-
- PPRINTF(("pcmcia_configure: calling conf2\n"));
- if (pcd->pcmcia_config(link, dev, &pc_cf, cf))
- return 0;
- /* give it a try */
- if(pc_cf.cfgid==0)
- pc_cf.cfgid=1;
- }
- } else {
- PPRINTF(("pcmcia_configure: calling bus config\n"));
- if (PCMCIA_BUS_CONFIG(pca, link, dev, &pc_cf, cf))
- return 0;
- }
-#ifdef PCMCIA_DEBUG
- pcmciadumpcf(&pc_cf);
-#endif
+ struct cfdata *cf = match;
+ struct pcmcia_attach_args *paa = aux;
- if (pcmcia_mapcard(link, -1, &pc_cf) != 0)
- return 0;
+ if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
+ -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
+ cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
+ return (0);
- mymap = 1;
- }
- link->devp = dev;
+ return ((*cf->cf_attach->ca_match)(parent, cf, aux));
+}
- PPRINTF(("pcmcia_configure: calling bus attach\n"));
- if (!(PCMCIA_BUS_PROBE(pca, parent, dev, cf, link))) {
- PPRINTF(("pcmcia_configure: bus probe failed\n"));
- goto bad;
+int
+pcmcia_print(arg, pnp)
+ void *arg;
+ const char *pnp;
+{
+ struct pcmcia_attach_args *pa = arg;
+ struct pcmcia_softc *sc = pa->pf->sc;
+ struct pcmcia_card *card = &sc->card;
+ int i;
+
+ if (pnp) {
+ for (i = 0; i < 4; i++) {
+ if (card->cis1_info[i] == NULL)
+ break;
+ if (i)
+ printf(", ");
+ printf("%s", card->cis1_info[i]);
+ }
+ if (i)
+ printf(" ");
+ printf("(manufacturer 0x%x, product 0x%x)", card->manufacturer,
+ card->product);
}
+ printf(" function %d", pa->pf->number);
- if (pcd && pcd->pcmcia_insert && pcd->pcmcia_insert(link, dev, cf)) {
- PPRINTF(("pcmcia_configure: pcmcia_insert failed\n"));
- goto bad;
- }
+ return (UNCONF);
+}
- return 1;
+int
+pcmcia_card_gettype(dev)
+ struct device *dev;
+{
+ struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
+ struct pcmcia_function *pf;
-bad:
- link->devp = NULL;
- if (mymap)
- pcmcia_unmapcard(link);
- PPRINTF(("pcmcia_configure: configuration error\n"));
- return 0;
+ /*
+ * set the iftype to memory if this card has no functions (not yet
+ * probed), or only one function, and that is not initialized yet or
+ * that is memory.
+ */
+ pf = SIMPLEQ_FIRST(&sc->card.pf_head);
+ if (pf == NULL ||
+ (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
+ (pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
+ return (PCMCIA_IFTYPE_MEMORY);
+ else
+ return (PCMCIA_IFTYPE_IO);
}
+/*
+ * Initialize a PCMCIA function. May be called as long as the function is
+ * disabled.
+ */
void
-pcmcia_detach(dev, arg)
- struct device *dev;
- void *arg;
+pcmcia_function_init(pf, cfe)
+ struct pcmcia_function *pf;
+ struct pcmcia_config_entry *cfe;
{
- struct pcmcia_link *link = arg;
+ if (pf->pf_flags & PFF_ENABLED)
+ panic("pcmcia_function_init: function is enabled");
- link->devp = NULL;
- printf("%s: device %s at slot %d detached/really\n",
- dev->dv_parent->dv_xname,
- dev->dv_xname, link->slot);
+ /* Remember which configuration entry we are using. */
+ pf->cfe = cfe;
}
-int
-pcmcia_unconfigure(link)
- struct pcmcia_link *link;
+static inline void pcmcia_socket_enable(pct, pch)
+ pcmcia_chipset_tag_t pct;
+ pcmcia_chipset_handle_t *pch;
{
- int i;
- struct device *dev;
- struct pcmcia_adapter *pca = link->adapter;
- struct pcmcia_device *pcd;
+ pcmcia_chip_socket_enable(pct, pch);
+}
- PPRINTF(("- pcmcia_unconfigure\n"));
- if (link->devp == NULL)
- return ENODEV;
+static inline void pcmcia_socket_disable(pct, pch)
+ pcmcia_chipset_tag_t pct;
+ pcmcia_chipset_handle_t *pch;
+{
+ pcmcia_chip_socket_disable(pct, pch);
+}
- if (link->device)
- pcd = link->device->dev;
- else
- pcd = NULL;
+/* Enable a PCMCIA function */
+int
+pcmcia_function_enable(pf)
+ struct pcmcia_function *pf;
+{
+ struct pcmcia_function *tmp;
+ int reg;
- if (ISSET(link->flags, CARD_IS_MAPPED)) {
- if (pcd && pcd->pcmcia_remove) {
- if ((*pcd->pcmcia_remove)(link, link->devp))
- return EBUSY;
- }
- else {
- if (PCMCIA_BUS_UNCONFIG(pca, link))
- return EBUSY;
- }
- if (pcmcia_unmapcard(link) != 0)
- return EBUSY;
- }
- if (config_detach(link->devp->dv_cfdata, pcmcia_detach, link)) {
- /* must be retained */
- for (i = 0; deldevs && deldevs[i].dev && i < ndeldevs; i++)
- continue;
+ if (pf->cfe == NULL)
+ panic("pcmcia_function_enable: function not initialized");
- if (i >= ndeldevs) {
- int sz = ndeldevs ? (ndeldevs * 2) :
- (MINALLOCSIZE / sizeof(deldevs[0]));
- struct old_devs *ndel = malloc(sz * sizeof(deldevs[0]),
- M_DEVBUF, M_NOWAIT);
- if (!ndel) {
- PPRINTF(("pcmcia_delete: creating dev array"));
- return ENOMEM;
- }
- bzero(ndel, sz * sizeof(ndel[0]));
- if (ndeldevs) {
- bcopy(deldevs, ndel,
- ndeldevs * sizeof(deldevs[0]));
- free(deldevs, M_DEVBUF);
- }
- ndeldevs = sz - 1;
- deldevs = ndel;
- }
- dev = deldevs[i].dev = link->devp;
- deldevs[i].pcdev = link->device;
- link->devp = NULL;
- TAILQ_REMOVE(&alldevs, dev, dv_list);
- printf("%s: device %s at slot %d detached/retained\n",
- dev->dv_parent->dv_xname,
- dev->dv_xname, link->slot);
+ /*
+ * Increase the reference count on the socket, enabling power, if
+ * necessary.
+ */
+ if (pf->sc->sc_enabled_count++ == 0)
+ pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
+ DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
+ pf->sc->sc_enabled_count));
+
+ if (pf->pf_flags & PFF_ENABLED) {
/*
- * Make this node eligible to probe again.
- * Since we're indirectly allocating state,
- * this device data will not get trashed later and we
- * can hold onto it.
+ * Don't do anything if we're already enabled.
*/
-/* dev->dv_cfdata->cf_fstate = FSTATE_NOTFOUND;*/
+ return (0);
}
- return 0;
-}
-/*
- * Map the card into I/O and memory space, using the details provided
- * with pc_cf.
- */
+ /*
+ * it's possible for different functions' CCRs to be in the same
+ * underlying page. Check for that.
+ */
-int
-pcmcia_mapcard(link, unit, pc_cf)
- struct pcmcia_link *link;
- int unit;
- struct pcmcia_conf *pc_cf;
-{
- struct pcmcia_adapter *pca = link->adapter;
- int s, i, err;
- PPRINTF(("- pcmcia_mapcard\n"));
-
- if (pca == NULL)
- return ENXIO;
- s = splbio();
-
- while (SCRATCH_INUSE(pca))
- sleep((caddr_t) & SCRATCH_INUSE(pca), PZERO - 1);
-
- SCRATCH_INUSE(pca) = 1;
- splx(s);
- for (i = 0; i < pc_cf->memwin; i++) {
- if ((err = PCMCIA_MAP_MEM(pca, link, pca->pa_memt,
- (caddr_t) pc_cf->mem[i].start,
- pc_cf->mem[i].caddr,
- pc_cf->mem[i].len,
- (pc_cf->mem[i].flags &
- (PCMCIA_MAP_16 | PCMCIA_MAP_ATTR)) |
- i | PCMCIA_PHYSICAL_ADDR)) != 0) {
- PPRINTF(("pcmcia_mapcard: mapmem %d err%d\n", i, err));
- goto error;
- }
- }
- for (i = 0; i < pc_cf->iowin; i++) {
- if ((err = PCMCIA_MAP_IO(pca, link, pc_cf->io[i].start,
- pc_cf->io[i].len,
- (pc_cf->io[i].flags & (PCMCIA_MAP_16 |
- PCMCIA_MAP_8)) | i)) != 0) {
- PPRINTF(("pcmcia_mapcard: mapio %d err %d\n", i, err));
- goto error;
+ for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
+ tmp = tmp->pf_list.sqe_next) {
+ if ((tmp->pf_flags & PFF_ENABLED) &&
+ (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
+ ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
+ (tmp->ccr_base - tmp->pf_ccr_offset +
+ tmp->pf_ccr_realsize))) {
+ pf->pf_ccrt = tmp->pf_ccrt;
+ pf->pf_ccrh = tmp->pf_ccrh;
+ pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
+
+ /*
+ * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
+ * tmp->ccr_base) + pf->ccr_base;
+ */
+ pf->pf_ccr_offset =
+ (tmp->pf_ccr_offset + pf->ccr_base) -
+ tmp->ccr_base;
+ pf->pf_ccr_window = tmp->pf_ccr_window;
+ break;
}
}
- if ((pc_cf->irq_num & 0xf) > 0) {
- if ((err = PCMCIA_MAP_INTR(pca, link, pc_cf->irq_num & 0xf,
- 0)) != 0) {
- PPRINTF(("pcmcia_mapcard: map_intr %d err %d\n",
- pc_cf->irq_num & 0xf, err));
- goto error;
+ if (tmp == NULL) {
+ if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
+ goto bad;
+
+ if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
+ PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
+ &pf->pf_ccr_window)) {
+ pcmcia_mem_free(pf, &pf->pf_pcmh);
+ goto bad;
}
}
- /* Now we've mapped everything enable it */
- if ((err = PCMCIA_MAP_MEM(pca, link, SCRATCH_MEMT(pca),
- SCRATCH_MEM(pca), pc_cf->cfg_off & (~(SCRATCH_SIZE(pca) - 1)),
- SCRATCH_SIZE(pca), PCMCIA_MAP_ATTR | PCMCIA_LAST_WIN)) != 0) {
- PPRINTF(("pcmcia_mapcard: enable err %d\n", err));
- goto error;
- }
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_RESET, -500000,
- pc_cf->iocard)) != 0) {
- PPRINTF(("failed to reset %d\n", err));
- goto error;
+ reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
+ reg |= PCMCIA_CCR_OPTION_LEVIREQ;
+ if (pcmcia_mfc(pf->sc)) {
+ reg |= (PCMCIA_CCR_OPTION_FUNC_ENABLE |
+ PCMCIA_CCR_OPTION_ADDR_DECODE);
+ if (pf->ih_fct)
+ reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
+
}
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
-#define GETMEM(x) bus_space_read_1(pca->pa_memt, \
- (bus_space_handle_t)SCRATCH_MEM(pca), \
- (pc_cf->cfg_off & (SCRATCH_SIZE(pca)-1)) + x)
-#define PUTMEM(x,v) bus_space_write_1(pca->pa_memt, \
- (bus_space_handle_t)SCRATCH_MEM(pca), \
- (pc_cf->cfg_off & (SCRATCH_SIZE(pca)-1)) + x, v)
+ reg = 0;
- if (ISSET(pc_cf->cfgtype, DOSRESET)) {
- PUTMEM(0, PCMCIA_SRESET);
- delay(50000);
- }
+ if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
+ reg |= PCMCIA_CCR_STATUS_IOIS8;
+ if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
+ reg |= PCMCIA_CCR_STATUS_AUDIO;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
- PPRINTF(("CMDR %x\n",(ISSET(pc_cf->cfgtype, CFGENTRYID) ?
- pc_cf->cfgid |CFGENTRYID:
- (pc_cf->cfgtype & CFGENTRYMASK)|1)|
- (pc_cf->irq_level ? PCMCIA_LVLREQ : 0)
- ));
+ if (pcmcia_mfc(pf->sc)) {
+ long tmp, iosize;
- PUTMEM(0, (ISSET(pc_cf->cfgtype, CFGENTRYID) ?
- pc_cf->cfgid |CFGENTRYID:
- (pc_cf->cfgtype & CFGENTRYMASK)|1)|
- (pc_cf->irq_level ? PCMCIA_LVLREQ : 0));
- delay(50000);
+ tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
+ /* round up to nearest (2^n)-1 */
+ for (iosize = 1; iosize < tmp; iosize <<= 1)
+ ;
+ iosize--;
- if (ISSET(pc_cf->cfg_regmask, (1 << (PCMCIA_SCR / 2))))
- PUTMEM(PCMCIA_SCR, (link->slot & 1) | 0x10);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
+ pf->pf_mfc_iobase & 0xff);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
+ (pf->pf_mfc_iobase >> 8) & 0xff);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2, 0);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3, 0);
-#if 0
- DPRINTF(("CCSR %x\n", GETMEM(PCMCIA_CCSR]));
- if (ISSET(GETMEM(PCMCIA_CCSR), PCMCIA_POWER_DOWN)) {
- u_char val = GETMEM(PCMCIA_CCSR);
- CLR(val, PCMCIA_POWER_DOWN);
- PUTMEM(PCMCIA_CCSR, var);
- DPRINTF(("CCSR now %x\n", GETMEM(PCMCIA_CCSR)));
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, iosize);
}
-#endif
+ DPRINTF(("%s: function %d CCR at %d offset %lx: "
+ "%x %x %x %x, %x %x %x %x, %x\n",
+ pf->sc->dev.dv_xname, pf->number,
+ pf->pf_ccr_window, pf->pf_ccr_offset,
+ pcmcia_ccr_read(pf, 0x00), pcmcia_ccr_read(pf, 0x02),
+ pcmcia_ccr_read(pf, 0x04), pcmcia_ccr_read(pf, 0x06),
- PPRINTF(("pcmcia_mapcard: about to initialize...\n"));
+ pcmcia_ccr_read(pf, 0x0A), pcmcia_ccr_read(pf, 0x0C),
+ pcmcia_ccr_read(pf, 0x0E), pcmcia_ccr_read(pf, 0x10),
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_WAIT,
- 1000, 0)) != 0) {
- PPRINTF(("failed to initialize %d\n", err));
- err = 0; /* XXX */
- }
-error:
- PCMCIA_MAP_MEM(pca, link, SCRATCH_MEMT(pca), SCRATCH_MEM(pca), 0,
- SCRATCH_SIZE(pca), PCMCIA_LAST_WIN | PCMCIA_UNMAP);
- if (err != 0) {
- PPRINTF(("pcmcia_mapcard: unmaping\n"));
- for (i = 0; i < pc_cf->memwin; i++) {
- PCMCIA_MAP_MEM(pca, link,
- pca->pa_memt,
- (caddr_t) pc_cf->mem[i].start,
- pc_cf->mem[i].caddr,
- pc_cf->mem[i].len,
- (pc_cf->mem[i].flags & (PCMCIA_MAP_16 |
- PCMCIA_MAP_ATTR)) | i |
- PCMCIA_PHYSICAL_ADDR | PCMCIA_UNMAP);
- }
- for (i = 0; i < pc_cf->iowin; i++) {
- PCMCIA_MAP_IO(pca, link, pc_cf->io[i].start,
- pc_cf->io[i].len,
- (pc_cf->io[i].flags & (PCMCIA_MAP_16 |
- PCMCIA_MAP_8)) | i | PCMCIA_UNMAP);
- }
- PCMCIA_MAP_INTR(pca, link, pc_cf->irq_num, PCMCIA_UNMAP);
- CLR(link->flags, CARD_IS_MAPPED);
- link->iowin = 0;
- link->memwin = 0;
- link->intr = 0;
- } else {
- SET(link->flags, CARD_IS_MAPPED);
- link->iowin = pc_cf->iowin;
- link->memwin = pc_cf->memwin;
- link->intr = pc_cf->irq_num;
- }
- s = splbio();
- SCRATCH_INUSE(pca) = 0;
- wakeup((caddr_t) & SCRATCH_INUSE(pca));
- splx(s);
- return err;
-}
+ pcmcia_ccr_read(pf, 0x12)));
-int
-pcmcia_unmapcard(link)
- struct pcmcia_link *link;
-{
- int i;
- struct pcmcia_adapter *pca = link->adapter;
- PPRINTF(("- pcmcia_unmapcard\n"));
- if (!pca)
- return ENODEV;
-
- for (i = 0; i < link->memwin; i++)
- PCMCIA_MAP_MEM(pca, link, pca->pa_memt, 0, 0, 0,
- (i | PCMCIA_UNMAP));
-
- for (i = 0; i < link->iowin; i++)
- PCMCIA_MAP_IO(pca, link, 0, 0, (i | PCMCIA_UNMAP));
-
- PCMCIA_MAP_INTR(pca, link, link->intr, PCMCIA_UNMAP);
- PCMCIA_SERVICE(pca, link, PCMCIA_OP_RESET, 50000, 0);
- CLR(link->flags, (CARD_IS_MAPPED | PCMCIA_SLOT_INUSE));
- link->iowin = 0;
- link->memwin = 0;
- link->intr = 0;
- return 0;
-}
+ pf->pf_flags |= PFF_ENABLED;
+ return (0);
+ bad:
+ /*
+ * Decrement the reference count, and power down the socket, if
+ * necessary.
+ */
+ if (--pf->sc->sc_enabled_count == 0)
+ pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
+ DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
+ pf->sc->sc_enabled_count));
-int
-pcmcia_mapcard_and_configure(link, unit, pc_cf)
- struct pcmcia_link *link;
- struct pcmcia_conf *pc_cf;
- int unit;
+ return (1);
+}
+
+/* Disable PCMCIA function. */
+void
+pcmcia_function_disable(pf)
+ struct pcmcia_function *pf;
{
- int mymap = 0;
- int err;
+ struct pcmcia_function *tmp;
- PPRINTF(("- pcmcia_mapcard_and_configure\n"));
- if (pc_cf->driver_name[0][0]) {
- if ((err = pcmcia_mapcard(link, unit, pc_cf)) != 0) {
- return err;
- }
- mymap=1;
- link->fordriver = pc_cf->driver_name[0];
- } else
- link->fordriver = NULL;
-
- pcmcia_probe_link(link);
-
- if (!ISSET(link->flags, PCMCIA_SLOT_INUSE)) {
- if (mymap)
- pcmcia_unmapcard(link);
- return ENODEV;
+ if (pf->cfe == NULL)
+ panic("pcmcia_function_enable: function not initialized");
+
+ if ((pf->pf_flags & PFF_ENABLED) == 0) {
+ /*
+ * Don't do anything if we're already disabled.
+ */
+ return;
}
- return 0;
-}
+ /*
+ * it's possible for different functions' CCRs to be in the same
+ * underlying page. Check for that. Note we mark us as disabled
+ * first to avoid matching ourself.
+ */
-int
-pcmcia_read_cis(link, scratch, offs, len)
- struct pcmcia_link *link;
- u_char *scratch;
- int offs, len;
-{
- struct pcmcia_adapter *pca = link->adapter;
- int s;
- int err = 0;
- int j = 0;
- u_char *p = SCRATCH_MEM(pca);
- int size = SCRATCH_SIZE(pca);
- volatile int *inuse = &SCRATCH_INUSE(pca);
- int pgoff = offs / size;
- int toff;
-
- toff = offs - (pgoff * size);
-
- PPRINTF(("- pcmcia_read_cis: mem %p size %d\n", p, size));
- if (pca == NULL)
- return ENXIO;
-
- s = splbio();
- while (*inuse)
- sleep((caddr_t) inuse, PZERO - 1);
- *inuse = 1;
- splx(s);
-
- while (len > 0) {
- int tlen = min(len, (size - toff) / 2);
- int i;
-
- if ((err = PCMCIA_MAP_MEM(pca, link, pca->pa_memt, p, pgoff,
- size,
- PCMCIA_MAP_ATTR |
- PCMCIA_LAST_WIN)) != 0)
- goto error;
-
- PPRINTF(("- pcmcia_read_cis: mem mapped\n"));
-
- for (i = 0; i < tlen; j++, i++)
- scratch[j] = p[toff + i * 2];
-
- PCMCIA_MAP_MEM(pca, link, pca->pa_memt, p, 0, size,
- PCMCIA_LAST_WIN | PCMCIA_UNMAP);
- len -= tlen;
- pgoff++;
- toff = 0;
+ pf->pf_flags &= ~PFF_ENABLED;
+ for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
+ tmp = tmp->pf_list.sqe_next) {
+ if ((tmp->pf_flags & PFF_ENABLED) &&
+ (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
+ ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
+ (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
+ break;
}
-error:
- s = splbio();
- *inuse = 0;
- wakeup((caddr_t) inuse);
- splx(s);
-
- PPRINTF(("- pcmcia_read_cis return %d\n", err));
- return err;
-}
-/* here we start our pseudodev for controlling the slots */
-#define PCMCIABUS_UNIT(a) (minor(a))
-#define PCMCIABUS_SLOT(a) (a&0x3) /* per-controller */
-#define PCMCIABUS_SLOTID(a) (a&0xf) /* system-wide assignment */
-#define PCMCIABUS_CHIPNO(a) ((a&0xf)>>2)
-#define PCMCIABUS_CHIPID(a) (a&0x3)
-#define PCMCIABUS_CHIP 0x40
-#define PCMCIABUS_BUS 0x80
-#define PCMCIABUS_BUSID(a) (a&0x3)
-#define PCMCIABUS_DEVTYPE(a) ((a)&(PCMCIABUS_CHIP|PCMCIABUS_BUS))
-static int busopen = 0;
-static int chipopen[4] = {0, 0, 0, 0};
+ /* Not used by anyone else; unmap the CCR. */
+ if (tmp == NULL) {
+ pcmcia_mem_unmap(pf, pf->pf_ccr_window);
+ pcmcia_mem_free(pf, &pf->pf_pcmh);
+ }
+
+ /*
+ * Decrement the reference count, and power down the socket, if
+ * necessary.
+ */
+ if (--pf->sc->sc_enabled_count == 0)
+ pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
+ DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
+ pf->sc->sc_enabled_count));
+}
int
-pcmciaopen(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
+pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
+ struct pcmcia_function *pf;
+ int width;
+ bus_addr_t offset;
+ bus_size_t size;
+ struct pcmcia_io_handle *pcihp;
+ int *windowp;
{
- int unit = PCMCIABUS_UNIT(dev);
- int chipid, slot;
- struct pcmcia_link *link;
- struct pcmciabus_softc *pcmcia;
-
- PPRINTF(("- pcmciabusopen\n"));
- switch (PCMCIABUS_DEVTYPE(unit)) {
- case PCMCIABUS_BUS:
- if (unit != PCMCIABUS_BUS)
- return ENXIO;
- if (busopen)
- return EBUSY;
- busopen = 1;
- break;
-
- case PCMCIABUS_CHIP:
- chipid = PCMCIABUS_CHIPID(unit);
- if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
- return ENXIO;
- pcmcia = pcmciabus_cd.cd_devs[chipid];
- if (pcmcia == NULL || pcmcia->sc_driver == NULL)
- return ENXIO;
-
- if (chipopen[chipid])
- return EBUSY;
-
- chipopen[chipid] = 1;
- break;
-
- case 0:
- slot = PCMCIABUS_SLOT(unit);
- chipid = PCMCIABUS_CHIPNO(unit);
-
- if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
- return ENXIO;
-
- pcmcia = pcmciabus_cd.cd_devs[chipid];
- if (pcmcia == NULL || pcmcia->sc_driver == NULL)
- return ENXIO;
- link = pcmcia->sc_link[slot];
- if (!link)
- return ENXIO;
-
- if (ISSET(link->flags, PCMCIA_SLOT_OPEN))
- return EBUSY;
-
- SET(link->flags, PCMCIA_SLOT_OPEN);
- break;
-
- default:
- return ENXIO;
+ int reg;
- }
- return 0;
-}
+ if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
+ width, offset, size, pcihp, windowp))
+ return (1);
+ /*
+ * XXX in the multifunction multi-iospace-per-function case, this
+ * needs to cooperate with io_alloc to make sure that the spaces
+ * don't overlap, and that the ccr's are set correctly
+ */
-int
-pcmciaclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
-{
- int unit = PCMCIABUS_UNIT(dev);
- int chipid, slot;
- struct pcmcia_link *link;
- struct pcmciabus_softc *pcmcia;
- int s;
-
- PPRINTF(("- pcmciabusclose\n"));
- switch (PCMCIABUS_DEVTYPE(unit)) {
- case PCMCIABUS_BUS:
- busopen = 0;
- break;
-
- case PCMCIABUS_CHIP:
- chipid = PCMCIABUS_CHIPID(unit);
- chipopen[chipid] = 0;
- break;
-
- case 0:
- slot = PCMCIABUS_SLOT(unit);
- chipid = PCMCIABUS_CHIPNO(unit);
- pcmcia = pcmciabus_cd.cd_devs[chipid];
- link = pcmcia->sc_link[slot];
-
- s = splclock();
- CLR(link->flags, (PCMCIA_SLOT_OPEN|PCMCIA_SLOT_EVENT));
- splx(s);
- break;
-
- default:
- return ENXIO;
- }
- return 0;
-}
+ if (pcmcia_mfc(pf->sc)) {
+ long tmp, iosize;
-int
-pcmciachip_ioctl(chipid, cmd, data)
- int chipid, cmd;
- caddr_t data;
-{
- struct pcmciabus_softc *pcmcia = pcmciabus_cd.cd_devs[chipid];
- struct pcmcia_adapter *pca = pcmcia->sc_driver;
- struct pcmcia_link link;
- struct pcmcia_regs *pi = (void *) data;
-
- PPRINTF(("- pcmciachip_ioctl\n"));
- if (pca->chip_link == NULL || pca->adapter_softc == NULL)
- return ENXIO;
-
- switch (cmd) {
- case PCMCIAIO_READ_REGS:
- pi->chip = chipid;
- link.adapter = pca;
- link.slot = 0;
- return PCMCIA_SERVICE(pca, &link, PCMCIA_OP_GETREGS,
- pi->chip_data, 0);
+ if (pf->pf_mfc_iomax == 0) {
+ pf->pf_mfc_iobase = pcihp->addr + offset;
+ pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
+ } else {
+ /* this makes the assumption that nothing overlaps */
+ if (pf->pf_mfc_iobase > pcihp->addr + offset)
+ pf->pf_mfc_iobase = pcihp->addr + offset;
+ if (pf->pf_mfc_iomax < pcihp->addr + offset + size)
+ pf->pf_mfc_iomax = pcihp->addr + offset + size;
+ }
+
+ tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
+ /* round up to nearest (2^n)-1 */
+ for (iosize = 1; iosize >= tmp; iosize <<= 1)
+ ;
+ iosize--;
+
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
+ pf->pf_mfc_iobase & 0xff);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
+ (pf->pf_mfc_iobase >> 8) & 0xff);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2, 0);
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3, 0);
+
+ pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, iosize);
+
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
+ reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
}
- return ENOTTY;
+ return (0);
}
-int
-pcmciaslot_ioctl(link, slotid, cmd, data)
- struct pcmcia_link *link;
- int slotid, cmd;
- caddr_t data;
+void *
+pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
+ struct pcmcia_function *pf;
+ int ipl;
+ int (*ih_fct) __P((void *));
+ void *ih_arg;
{
- int err = 0;
- struct pcmciabus_softc *pcmcia =
- pcmciabus_cd.cd_devs[PCMCIABUS_CHIPNO(slotid)];
- struct pcmcia_adapter *pca = pcmcia->sc_driver;
-
- PPRINTF(("- pcmciaslot_ioctl\n"));
- if (link == NULL || pca->chip_link == NULL ||
- pca->adapter_softc == NULL)
- return ENXIO;
-
- switch (cmd) {
- case PCMCIAIO_GET_STATUS:
- {
- struct pcmcia_status *pi = (void *) data;
- pi->slot = slotid;
- pi->status = 0;
- err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
- &pi->status, 0);
- if (!err) {
- if (ISSET(link->flags, CARD_IS_MAPPED))
- SET(pi->status, PCMCIA_CARD_IS_MAPPED);
- if (ISSET(link->flags, PCMCIA_SLOT_INUSE))
- SET(pi->status, PCMCIA_CARD_INUSE);
- }
- return err;
- }
+ void *ret;
- case PCMCIAIO_GET_INFO:
- {
- struct pcmcia_info *pi = (void *) data;
- int status;
-
- if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
- &status, 0)) != 0)
- return err;
- if (!ISSET(status, PCMCIA_CARD_PRESENT))
- return ENODEV;
- pi->slot = slotid;
- return pcmcia_read_cis(link, pi->cis_data, 0,
- CIS_MAXSIZE);
- }
+ /* behave differently if this is a multifunction card */
- case PCMCIAIO_CONFIGURE:
- {
- struct pcmcia_conf *pc_cf = (void *) data;
- return pcmcia_mapcard_and_configure(link, -1, pc_cf);
- }
+ if (pcmcia_mfc(pf->sc)) {
+ int s, ihcnt, hiipl, reg;
+ struct pcmcia_function *pf2;
+
+ /*
+ * mask all the ipl's which are already used by this card,
+ * and find the highest ipl number (lowest priority)
+ */
- case PCMCIAIO_UNCONFIGURE:
- return pcmcia_unconfigure(link);
-
- case PCMCIAIO_UNMAP:
- if (ISSET(link->flags, PCMCIA_SLOT_INUSE))
- return EBUSY;
- return pcmcia_unmapcard(link);
-
- case PCMCIAIO_SET_POWER:
- {
- int pi = *(int *) data;
- pi &= 0x3;
- switch (pi) {
- case PCMCIASIO_POWER_OFF:
- return PCMCIA_SERVICE(pca, link,
- PCMCIA_OP_POWER, 0, 0);
-
- case PCMCIASIO_POWER_5V:
- case PCMCIASIO_POWER_3V:
- case PCMCIASIO_POWER_AUTO:
- err = PCMCIA_SERVICE(pca, link,
- PCMCIA_OP_POWER,
- 10000, pi);
- if (err)
- return err;
-
- err = PCMCIA_SERVICE(pca, link,
- PCMCIA_OP_RESET,
- 500000, 0);
- if (err) {
- PPRINTF(("failed to reset %d\n", err));
- PCMCIA_SERVICE(pca, link,
- PCMCIA_OP_POWER, 0, 0);
- return err;
+ ihcnt = 0;
+ s = 0; /* this is only here to keep the compiler
+ happy */
+ hiipl = 0; /* this is only here to keep the compiler
+ happy */
+
+ for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
+ pf2 = pf2->pf_list.sqe_next) {
+ if (pf2->ih_fct) {
+ DPRINTF(("%s: function %d has ih_fct %p\n",
+ pf->sc->dev.dv_xname, pf2->number,
+ pf2->ih_fct));
+
+ if (ihcnt == 0) {
+ hiipl = pf2->ih_ipl;
+ } else {
+ if (pf2->ih_ipl > hiipl)
+ hiipl = pf2->ih_ipl;
}
- return 0;
- default:
- return EINVAL;
+ ihcnt++;
}
}
- case PCMCIAIO_READ_COR:
- {
- struct pcmcia_info *pi = (void *)data;
- struct pcmcia_conf pc_cf;
- int status,s;
+ /*
+ * establish the real interrupt, changing the ipl if
+ * necessary
+ */
- err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
- &status, 0);
- if (err)
- return err;
- if (!ISSET(status, PCMCIA_CARD_PRESENT))
- return ENODEV;
+ if (ihcnt == 0) {
+#ifdef DIAGNOSTIC
+ if (pf->sc->ih != NULL)
+ panic("card has intr handler, but no function does");
+#endif
+ s = splhigh();
- if ((status = pcmcia_read_cis(link, pi->cis_data, 0,
- CIS_MAXSIZE)))
- return status;
+ /* set up the handler for the new function */
- bzero(&pc_cf, sizeof(pc_cf));
- if (pcmcia_get_cf(link, pi->cis_data,
- sizeof(pi->cis_data), -1,
- &pc_cf) != 0 )
- return EIO;
+ pf->ih_fct = ih_fct;
+ pf->ih_arg = ih_arg;
+ pf->ih_ipl = ipl;
- s=splbio();
+ pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
+ pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
+ splx(s);
+ } else if (ipl > hiipl) {
+#ifdef DIAGNOSTIC
+ if (pf->sc->ih == NULL)
+ panic("functions have ih, but the card does not");
+#endif
- while(SCRATCH_INUSE(pca))
- sleep((caddr_t)&SCRATCH_INUSE(pca), PZERO - 1);
+ /* XXX need #ifdef for splserial on x86 */
+ s = splhigh();
+
+ pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
+ pf->sc->ih);
+
+ /* set up the handler for the new function */
+ pf->ih_fct = ih_fct;
+ pf->ih_arg = ih_arg;
+ pf->ih_ipl = ipl;
+
+ pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
+ pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
- SCRATCH_INUSE(pca) = 1;
splx(s);
- if ((err = PCMCIA_MAP_MEM(pca, link,
- SCRATCH_MEMT(pca),
- SCRATCH_MEM(pca),
- pc_cf.cfg_off &
- ~(SCRATCH_SIZE(pca)-1),
- SCRATCH_SIZE(pca),
- PCMCIA_MAP_ATTR|
- PCMCIA_LAST_WIN)) == 0) {
- int m, i;
- u_char *d = pi->cis_data,*p;
- p = SCRATCH_MEM(pca)+
- (pc_cf.cfg_off & (SCRATCH_SIZE(pca)-1));
- for (i = 0, m = 1; i < 32; i++, m <<= 1) {
- if (pc_cf.cfg_regmask & m) {
- *d++ = i;
- *d++ = p[i*2];
- }
- }
- *d++ = 0xff;
- *d++ = 0xff;
- PCMCIA_MAP_MEM(pca, link,
- SCRATCH_MEMT(pca),
- SCRATCH_MEM(pca),
- 0,SCRATCH_SIZE(pca),
- PCMCIA_LAST_WIN|PCMCIA_UNMAP);
- }
- s = splbio();
- SCRATCH_INUSE(pca)=0;
- wakeup((caddr_t)&SCRATCH_INUSE(pca));
+ } else {
+ s = splhigh();
+
+ /* set up the handler for the new function */
+
+ pf->ih_fct = ih_fct;
+ pf->ih_arg = ih_arg;
+ pf->ih_ipl = ipl;
+
splx(s);
- return err;
}
- default:
- return ENOTTY;
+
+ ret = pf->sc->ih;
+
+ if (ret != NULL) {
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
+ reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
+
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
+ reg |= PCMCIA_CCR_STATUS_INTRACK;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
+ }
+ } else {
+ ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
+ pf, ipl, ih_fct, ih_arg);
}
- return ENOTTY;
+
+ return (ret);
}
-int
-pcmciaioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
+void
+pcmcia_intr_disestablish(pf, ih)
+ struct pcmcia_function *pf;
+ void *ih;
{
- int unit = PCMCIABUS_UNIT(dev);
- int chipid = PCMCIABUS_CHIPNO(unit);
- struct pcmciabus_softc *pcmcia;
- struct pcmcia_link *link;
+ /* behave differently if this is a multifunction card */
- PPRINTF(("- pcmciabusioctl\n"));
- if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
- return ENXIO;
+ if (pcmcia_mfc(pf->sc)) {
+ int s, ihcnt, hiipl;
+ struct pcmcia_function *pf2;
- pcmcia = pcmciabus_cd.cd_devs[chipid];
- if (pcmcia == NULL)
- return ENXIO;
+ /*
+ * mask all the ipl's which are already used by this card,
+ * and find the highest ipl number (lowest priority). Skip
+ * the current function.
+ */
- switch (PCMCIABUS_DEVTYPE(unit)) {
-#if 0
- case PCMCIABUS_BUS:
- return pcmciabus_ioctl(PCMCIABUS_BUSID(unit), cmd, data);
+ ihcnt = 0;
+ s = 0; /* this is only here to keep the compipler
+ happy */
+ hiipl = 0; /* this is only here to keep the compipler
+ happy */
+
+ for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
+ pf2 = pf2->pf_list.sqe_next) {
+ if (pf2 == pf)
+ continue;
+
+ if (pf2->ih_fct) {
+ if (ihcnt == 0) {
+ hiipl = pf2->ih_ipl;
+ } else {
+ if (pf2->ih_ipl > hiipl)
+ hiipl = pf2->ih_ipl;
+ }
+ ihcnt++;
+ }
+ }
+
+ /*
+ * if the ih being removed is lower priority than the lowest
+ * priority remaining interrupt, up the priority.
+ */
+
+ /* ihcnt is the number of interrupt handlers *not* including
+ the one about to be removed. */
+
+ if (ihcnt == 0) {
+ int reg;
+
+#ifdef DIAGNOSTIC
+ if (pf->sc->ih == NULL)
+ panic("disestablishing last function, but card has no ih");
#endif
- case PCMCIABUS_CHIP:
- return pcmciachip_ioctl(PCMCIABUS_CHIPID(unit), cmd, data);
- case 0:
- link = pcmcia->sc_link[PCMCIABUS_SLOT(unit)];
- return pcmciaslot_ioctl(link, PCMCIABUS_SLOTID(unit),
- cmd, data);
- default:
- return ENXIO;
- }
-}
+ pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
+ pf->sc->ih);
-int
-pcmciaselect(device, rw, p)
- dev_t device;
- int rw;
- struct proc *p;
-{
- int s;
- int unit = PCMCIABUS_UNIT(device);
- int chipid = PCMCIABUS_CHIPNO(unit);
- struct pcmciabus_softc *pcmcia;
- struct pcmcia_link *link;
-
- PPRINTF(("- pcmciabus_select\n"));
- pcmcia = pcmciabus_cd.cd_devs[chipid];
-
- switch (PCMCIABUS_DEVTYPE(unit)) {
- case 0:
- link = pcmcia->sc_link[PCMCIABUS_SLOT(unit)];
- break;
- case PCMCIABUS_BUS:
- case PCMCIABUS_CHIP:
- default:
- return 0;
- }
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
+ reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
+ pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
+
+ pf->ih_fct = NULL;
+ pf->ih_arg = NULL;
+
+ pf->sc->ih = NULL;
+ } else if (pf->ih_ipl > hiipl) {
+#ifdef DIAGNOSTIC
+ if (pf->sc->ih == NULL)
+ panic("changing ih ipl, but card has no ih");
+#endif
+ /* XXX need #ifdef for splserial on x86 */
+ s = splhigh();
+
+ pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
+ pf->sc->ih);
+ pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
+ pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc);
+
+ /* null out the handler for this function */
+
+ pf->ih_fct = NULL;
+ pf->ih_arg = NULL;
+
+ splx(s);
+ } else {
+ s = splhigh();
+
+ pf->ih_fct = NULL;
+ pf->ih_arg = NULL;
- s = splpcmcia();
- switch (rw) {
- case FREAD:
- case FWRITE:
- break;
- case 0:
- if (ISSET(link->flags, PCMCIA_SLOT_EVENT)) {
- CLR(link->flags, PCMCIA_SLOT_EVENT);
splx(s);
- return 1;
}
- selrecord(p, &link->pcmcialink_sel);
- break;
+ } else {
+ pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
}
- splx(s);
- return 0;
}
-int
-pcmciammap(dev, offset, nprot)
- dev_t dev;
- int offset, nprot;
+int
+pcmcia_card_intr(arg)
+ void *arg;
{
- return ENXIO;
-}
+ struct pcmcia_softc *sc = arg;
+ struct pcmcia_function *pf;
+ int reg, ret, ret2;
+ ret = 0;
-#ifdef PCMCIA_DEBUG
-void
-pcmciadumpcf(cf)
- struct pcmcia_conf * cf;
-{
- int i;
- static char *ios[] = {
- "auto", "8bit", "16bit", "illegal"
- };
- printf("Driver name %s\n", cf->driver_name[0]);
- printf("CFG offset %x\n", cf->cfg_off);
- printf("IRQ type %s%s\n", cf->irq_level ? "Level " : "",
- cf->irq_pulse ? "Pulse" : "");
- printf("IRQ num %x\n", cf->irq_num);
- printf("IRQ mask %x\n", cf->irq_mask);
- printf("CFG type %x %x\n", cf->cfgtype,cf->cfgid);
- printf("Cardtype %s\n", cf->iocard ? "IO" : "MEM");
- for (i = 0; i < cf->iowin; i++) {
- printf("iowin %x-%x %s\n", cf->io[i].start,
- cf->io[i].start + cf->io[i].len - 1,
- ios[(cf->io[i].flags &
- (PCMCIA_MAP_8 | PCMCIA_MAP_16)) >> 8]);
- }
- for (i = 0; i < cf->memwin; i++) {
- printf("memwin (%x)%x-%x %x\n",
- cf->mem[i].caddr,
- cf->mem[i].start,
- cf->mem[i].start + cf->mem[i].len - 1,
- cf->mem[i].flags);
- }
-}
+ for (pf = sc->card.pf_head.sqh_first; pf != NULL;
+ pf = pf->pf_list.sqe_next) {
+#if 0
+ printf("%s: intr flags=%x fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
+ sc->dev.dv_xname, pf->pf_flags, pf->number,
+ pmap_extract(pmap_kernel(),
+ (vaddr_t) pf->pf_ccrh) + pf->pf_ccr_offset,
+ pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
+ pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
+ pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
#endif
-
-int
-pcmcia_print(aux, pnp)
- void *aux;
- const char *pnp;
-{
+ if (pf->ih_fct != NULL &&
+ (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
+ if (reg & PCMCIA_CCR_STATUS_INTR) {
+ ret2 = (*pf->ih_fct)(pf->ih_arg);
+ if (ret2 != 0 && ret == 0)
+ ret = ret2;
+ reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
#if 0
- struct pcmcia_attach_args *paa = aux;
- printf(" slot %d", paa->paa_link->slot);
+ printf("; csr %02x->%02x",
+ reg, reg & ~PCMCIA_CCR_STATUS_INTR);
#endif
- return (0); /* be silent */
-}
-
-/*
- * Filter out inappropriate configurations before heading off to
- * the device match routines.
- */
-int
-pcmcia_submatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct device *self = match;
- struct cfdata *cf = self->dv_cfdata;
- struct pcmcia_attach_args *paa = aux;
- struct pcmcia_link *link = paa->paa_link;
-
+ pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
+ reg & ~PCMCIA_CCR_STATUS_INTR);
+ }
+ }
#if 0
- printf("pcmcia_submatch: paa=%p link=%p, cf=%p\n", paa, link, cf);
- delay(2000000);
-
+ printf("\n");
#endif
-
- if (cf->cf_loc[6] != -1 && link->slot != cf->cf_loc[6]) {
- printf("slot mismatch: %d cf_loc %d\n", link->slot,
- cf->cf_loc[6]);
- return 0;
}
- return ((*cf->cf_attach->ca_match)(parent, match, aux));
+ return (ret);
}
diff --git a/sys/dev/pcmcia/pcmcia_cis.c b/sys/dev/pcmcia/pcmcia_cis.c
new file mode 100644
index 00000000000..1653f1aea6d
--- /dev/null
+++ b/sys/dev/pcmcia/pcmcia_cis.c
@@ -0,0 +1,1196 @@
+/* $OpenBSD: pcmcia_cis.c,v 1.1 1998/09/11 10:47:15 fgsch Exp $ */
+/* $NetBSD: pcmcia_cis.c,v 1.9 1998/08/22 23:41:48 msaitoh 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/malloc.h>
+
+#include <dev/pcmcia/pcmciareg.h>
+#include <dev/pcmcia/pcmciachip.h>
+#include <dev/pcmcia/pcmciavar.h>
+
+#ifdef PCMCIACISDEBUG
+int pcmciacis_debug = 1;
+#define DPRINTF(arg) if (pcmciacis_debug) printf arg
+#else
+#define DPRINTF(arg)
+#endif
+
+#define PCMCIA_CIS_SIZE 1024
+
+struct cis_state {
+ int count;
+ int gotmfc;
+ struct pcmcia_config_entry temp_cfe;
+ struct pcmcia_config_entry *default_cfe;
+ struct pcmcia_card *card;
+ struct pcmcia_function *pf;
+};
+
+int pcmcia_parse_cis_tuple __P((struct pcmcia_tuple *, void *));
+
+void
+pcmcia_read_cis(sc)
+ struct pcmcia_softc *sc;
+{
+ struct cis_state state;
+
+ state.count = 0;
+ state.gotmfc = 0;
+
+ state.card = &sc->card;
+
+ state.card->error = 0;
+ state.card->cis1_major = -1;
+ state.card->cis1_minor = -1;
+ state.card->cis1_info[0] = NULL;
+ state.card->cis1_info[1] = NULL;
+ state.card->cis1_info[2] = NULL;
+ state.card->cis1_info[3] = NULL;
+ state.card->manufacturer = PCMCIA_VENDOR_INVALID;
+ state.card->product = PCMCIA_PRODUCT_INVALID;
+ SIMPLEQ_INIT(&state.card->pf_head);
+
+ state.pf = NULL;
+
+ if (pcmcia_scan_cis((struct device *)sc, pcmcia_parse_cis_tuple,
+ &state) == -1)
+ state.card->error++;
+}
+
+int
+pcmcia_scan_cis(dev, fct, arg)
+ struct device *dev;
+ int (*fct) __P((struct pcmcia_tuple *, void *));
+ void *arg;
+{
+ struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
+ pcmcia_chipset_tag_t pct;
+ pcmcia_chipset_handle_t pch;
+ int window;
+ struct pcmcia_mem_handle pcmh;
+ struct pcmcia_tuple tuple;
+ int longlink_present;
+ int longlink_common;
+ u_long longlink_addr;
+ int mfc_count;
+ int mfc_index;
+ struct {
+ int common;
+ u_long addr;
+ } mfc[256 / 5];
+ int ret;
+
+ ret = 0;
+
+ pct = sc->pct;
+ pch = sc->pch;
+
+ /* allocate some memory */
+
+ if (pcmcia_chip_mem_alloc(pct, pch, PCMCIA_CIS_SIZE, &pcmh)) {
+#ifdef DIAGNOSTIC
+ printf("%s: can't alloc memory to read attributes\n",
+ sc->dev.dv_xname);
+#endif
+ return -1;
+ }
+ tuple.memt = pcmh.memt;
+ tuple.memh = pcmh.memh;
+
+ /* initialize state for the primary tuple chain */
+ if (pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_ATTR, 0,
+ PCMCIA_CIS_SIZE, &pcmh, &tuple.ptr, &window)) {
+ pcmcia_chip_mem_free(pct, pch, &pcmh);
+#ifdef DIAGNOSTIC
+ printf("%s: can't map memory to read attributes\n",
+ sc->dev.dv_xname);
+#endif
+ return -1;
+ }
+ DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
+
+ tuple.mult = 2;
+
+ longlink_present = 1;
+ longlink_common = 1;
+ longlink_addr = 0;
+
+ mfc_count = 0;
+ mfc_index = 0;
+
+ DPRINTF(("%s: CIS tuple chain:\n", sc->dev.dv_xname));
+
+ while (1) {
+ while (1) {
+ /* get the tuple code */
+
+ tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
+
+ /* two special-case tuples */
+
+ if (tuple.code == PCMCIA_CISTPL_NULL) {
+ DPRINTF(("CISTPL_NONE\n 00\n"));
+ tuple.ptr++;
+ continue;
+ } else if (tuple.code == PCMCIA_CISTPL_END) {
+ DPRINTF(("CISTPL_END\n ff\n"));
+ /* Call the function for the END tuple, since
+ the CIS semantics depend on it */
+ if ((*fct) (&tuple, arg)) {
+ pcmcia_chip_mem_unmap(pct, pch,
+ window);
+ ret = 1;
+ goto done;
+ }
+ tuple.ptr++;
+ break;
+ }
+ /* now all the normal tuples */
+
+ tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
+ switch (tuple.code) {
+ case PCMCIA_CISTPL_LONGLINK_A:
+ case PCMCIA_CISTPL_LONGLINK_C:
+ if (tuple.length < 4) {
+ DPRINTF(("CISTPL_LONGLINK_%s too "
+ "short %d\n",
+ longlink_common ? "C" : "A",
+ tuple.length));
+ break;
+ }
+ longlink_present = 1;
+ longlink_common = (tuple.code ==
+ PCMCIA_CISTPL_LONGLINK_C) ? 1 : 0;
+ longlink_addr = pcmcia_tuple_read_4(&tuple, 0);
+ DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
+ longlink_common ? "C" : "A",
+ longlink_addr));
+ break;
+ case PCMCIA_CISTPL_NO_LINK:
+ longlink_present = 0;
+ DPRINTF(("CISTPL_NO_LINK\n"));
+ break;
+ case PCMCIA_CISTPL_CHECKSUM:
+ if (tuple.length < 5) {
+ DPRINTF(("CISTPL_CHECKSUM too "
+ "short %d\n", tuple.length));
+ break;
+ } {
+ int16_t offset;
+ u_long addr, length;
+ u_int cksum, sum;
+ int i;
+
+ *((u_int16_t *) & offset) =
+ pcmcia_tuple_read_2(&tuple, 0);
+ length = pcmcia_tuple_read_2(&tuple, 2);
+ cksum = pcmcia_tuple_read_1(&tuple, 4);
+
+ addr = tuple.ptr + offset;
+
+ DPRINTF(("CISTPL_CHECKSUM addr=%lx "
+ "len=%lx cksum=%x",
+ addr, length, cksum));
+
+ /*
+ * XXX do more work to deal with
+ * distant regions
+ */
+ if ((addr >= PCMCIA_CIS_SIZE) ||
+ ((addr + length) < 0) ||
+ ((addr + length) >=
+ PCMCIA_CIS_SIZE)) {
+ DPRINTF((" skipped, "
+ "too distant\n"));
+ break;
+ }
+ sum = 0;
+ for (i = 0; i < length; i++)
+ sum +=
+ bus_space_read_1(tuple.memt,
+ tuple.memh,
+ addr + tuple.mult * i);
+ if (cksum != (sum & 0xff)) {
+ DPRINTF((" failed sum=%x\n",
+ sum));
+ printf("%s: CIS checksum "
+ "failed\n",
+ sc->dev.dv_xname);
+#if 0
+ /*
+ * XXX Some working cards have
+ * XXX bad checksums!!
+ */
+ ret = -1;
+#endif
+ } else {
+ DPRINTF((" ok\n"));
+ }
+ }
+ break;
+ case PCMCIA_CISTPL_LONGLINK_MFC:
+ if (tuple.length < 1) {
+ DPRINTF(("CISTPL_LONGLINK_MFC too "
+ "short %d\n", tuple.length));
+ break;
+ }
+ /*
+ * this is kind of ad hoc, as I don't have
+ * any real documentation
+ */
+ {
+ int i;
+
+ mfc_count =
+ pcmcia_tuple_read_1(&tuple, 0);
+ DPRINTF(("CISTPL_LONGLINK_MFC %d",
+ mfc_count));
+ for (i = 0; i < mfc_count; i++) {
+ mfc[i].common =
+ (pcmcia_tuple_read_1(&tuple,
+ 1 + 5 * i) ==
+ PCMCIA_MFC_MEM_COMMON) ?
+ 1 : 0;
+ mfc[i].addr =
+ pcmcia_tuple_read_4(&tuple,
+ 1 + 5 * i + 1);
+ DPRINTF((" %s:%lx",
+ mfc[i].common ? "common" :
+ "attr", mfc[i].addr));
+ }
+ DPRINTF(("\n"));
+ }
+ /*
+ * for LONGLINK_MFC, fall through to the
+ * function. This tuple has structural and
+ * semantic content.
+ */
+ default:
+ {
+ if ((*fct) (&tuple, arg)) {
+ pcmcia_chip_mem_unmap(pct,
+ pch, window);
+ ret = 1;
+ goto done;
+ }
+ }
+ break;
+ } /* switch */
+#ifdef PCMCIACISDEBUG
+ /* print the tuple */
+ {
+ int i;
+
+ DPRINTF((" %02x %02x", tuple.code,
+ tuple.length));
+
+ for (i = 0; i < tuple.length; i++) {
+ DPRINTF((" %02x",
+ pcmcia_tuple_read_1(&tuple, i)));
+ if ((i % 16) == 13)
+ DPRINTF(("\n"));
+ }
+ if ((i % 16) != 14)
+ DPRINTF(("\n"));
+ }
+#endif
+ /* skip to the next tuple */
+ tuple.ptr += 2 + tuple.length;
+ }
+ /*
+ * the chain is done. Clean up and move onto the next one,
+ * if any. The loop is here in the case that there is an MFC
+ * card with no longlink (which defaults to existing, == 0).
+ * In general, this means that if one pointer fails, it will
+ * try the next one, instead of just bailing.
+ */
+
+ while (1) {
+ pcmcia_chip_mem_unmap(pct, pch, window);
+
+ if (longlink_present) {
+ /*
+ * if the longlink is to attribute memory,
+ * then it is unindexed. That is, if the
+ * link value is 0x100, then the actual
+ * memory address is 0x200. This means that
+ * we need to multiply by 2 before calling
+ * mem_map, and then divide the resulting ptr
+ * by 2 after.
+ */
+
+ if (!longlink_common)
+ longlink_addr *= 2;
+
+ pcmcia_chip_mem_map(pct, pch, longlink_common ?
+ PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
+ longlink_addr, PCMCIA_CIS_SIZE,
+ &pcmh, &tuple.ptr, &window);
+
+ if (!longlink_common)
+ tuple.ptr /= 2;
+
+ DPRINTF(("cis mem map %x\n",
+ (unsigned int) tuple.memh));
+
+ tuple.mult = longlink_common ? 1 : 2;
+ longlink_present = 0;
+ longlink_common = 1;
+ longlink_addr = 0;
+ } else if (mfc_count && (mfc_index < mfc_count)) {
+ if (!mfc[mfc_index].common)
+ mfc[mfc_index].addr *= 2;
+
+ pcmcia_chip_mem_map(pct, pch,
+ mfc[mfc_index].common ?
+ PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
+ mfc[mfc_index].addr, PCMCIA_CIS_SIZE,
+ &pcmh, &tuple.ptr, &window);
+
+ if (!mfc[mfc_index].common)
+ tuple.ptr /= 2;
+
+ DPRINTF(("cis mem map %x\n",
+ (unsigned int) tuple.memh));
+
+ /* set parse state, and point at the next one */
+
+ tuple.mult = mfc[mfc_index].common ? 1 : 2;
+
+ mfc_index++;
+ } else {
+ goto done;
+ }
+
+ /* make sure that the link is valid */
+ tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
+ if (tuple.code != PCMCIA_CISTPL_LINKTARGET) {
+ DPRINTF(("CISTPL_LINKTARGET expected, "
+ "code %02x observed\n", tuple.code));
+ continue;
+ }
+ tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
+ if (tuple.length < 3) {
+ DPRINTF(("CISTPL_LINKTARGET too short %d\n",
+ tuple.length));
+ continue;
+ }
+ if ((pcmcia_tuple_read_1(&tuple, 0) != 'C') ||
+ (pcmcia_tuple_read_1(&tuple, 1) != 'I') ||
+ (pcmcia_tuple_read_1(&tuple, 2) != 'S')) {
+ DPRINTF(("CISTPL_LINKTARGET magic "
+ "%02x%02x%02x incorrect\n",
+ pcmcia_tuple_read_1(&tuple, 0),
+ pcmcia_tuple_read_1(&tuple, 1),
+ pcmcia_tuple_read_1(&tuple, 2)));
+ continue;
+ }
+ tuple.ptr += 2 + tuple.length;
+
+ break;
+ }
+ }
+
+ pcmcia_chip_mem_unmap(pct, pch, window);
+
+done:
+ /* Last, free the allocated memory block */
+ pcmcia_chip_mem_free(pct, pch, &pcmh);
+
+ return (ret);
+}
+
+/* XXX this is incredibly verbose. Not sure what trt is */
+
+void
+pcmcia_print_cis(sc)
+ struct pcmcia_softc *sc;
+{
+ struct pcmcia_card *card = &sc->card;
+ struct pcmcia_function *pf;
+ struct pcmcia_config_entry *cfe;
+ int i;
+
+ printf("%s: CIS version ", sc->dev.dv_xname);
+ if (card->cis1_major == 4) {
+ if (card->cis1_minor == 0)
+ printf("PCMCIA 1.0\n");
+ else if (card->cis1_minor == 1)
+ printf("PCMCIA 2.0 or 2.1\n");
+ } else if (card->cis1_major >= 5)
+ printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
+ else
+ printf("unknown (major=%d, minor=%d)\n",
+ card->cis1_major, card->cis1_minor);
+
+ printf("%s: CIS info: ", sc->dev.dv_xname);
+ for (i = 0; i < 4; i++) {
+ if (card->cis1_info[i] == NULL)
+ break;
+ if (i)
+ printf(", ");
+ printf("%s", card->cis1_info[i]);
+ }
+ printf("\n");
+
+ printf("%s: Manufacturer code 0x%x, product 0x%x\n",
+ sc->dev.dv_xname, card->manufacturer, card->product);
+
+ for (pf = card->pf_head.sqh_first; pf != NULL;
+ pf = pf->pf_list.sqe_next) {
+ printf("%s: function %d: ", sc->dev.dv_xname, pf->number);
+
+ switch (pf->function) {
+ case PCMCIA_FUNCTION_UNSPEC:
+ printf("unspecified");
+ break;
+ case PCMCIA_FUNCTION_MULTIFUNCTION:
+ printf("multi-function");
+ break;
+ case PCMCIA_FUNCTION_MEMORY:
+ printf("memory");
+ break;
+ case PCMCIA_FUNCTION_SERIAL:
+ printf("serial port");
+ break;
+ case PCMCIA_FUNCTION_PARALLEL:
+ printf("parallel port");
+ break;
+ case PCMCIA_FUNCTION_DISK:
+ printf("fixed disk");
+ break;
+ case PCMCIA_FUNCTION_VIDEO:
+ printf("video adapter");
+ break;
+ case PCMCIA_FUNCTION_NETWORK:
+ printf("network adapter");
+ break;
+ case PCMCIA_FUNCTION_AIMS:
+ printf("auto incrementing mass storage");
+ break;
+ case PCMCIA_FUNCTION_SCSI:
+ printf("SCSI bridge");
+ break;
+ case PCMCIA_FUNCTION_SECURITY:
+ printf("Security services");
+ break;
+ case PCMCIA_FUNCTION_INSTRUMENT:
+ printf("Instrument");
+ break;
+ default:
+ printf("unknown (%d)", pf->function);
+ break;
+ }
+
+ printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
+
+ for (cfe = pf->cfe_head.sqh_first; cfe != NULL;
+ cfe = cfe->cfe_list.sqe_next) {
+ printf("%s: function %d, config table entry %d: ",
+ sc->dev.dv_xname, pf->number, cfe->number);
+
+ switch (cfe->iftype) {
+ case PCMCIA_IFTYPE_MEMORY:
+ printf("memory card");
+ break;
+ case PCMCIA_IFTYPE_IO:
+ printf("I/O card");
+ break;
+ default:
+ printf("card type unknown");
+ break;
+ }
+
+ printf("; irq mask %x", cfe->irqmask);
+
+ if (cfe->num_iospace) {
+ printf("; iomask %lx, iospace", cfe->iomask);
+
+ for (i = 0; i < cfe->num_iospace; i++)
+ printf(" %lx%s%lx",
+ cfe->iospace[i].start,
+ cfe->iospace[i].length ? "-" : "",
+ cfe->iospace[i].start +
+ cfe->iospace[i].length - 1);
+ }
+ if (cfe->num_memspace) {
+ printf("; memspace");
+
+ for (i = 0; i < cfe->num_memspace; i++)
+ printf(" %lx%s%lx%s%lx",
+ cfe->memspace[i].cardaddr,
+ cfe->memspace[i].length ? "-" : "",
+ cfe->memspace[i].cardaddr +
+ cfe->memspace[i].length - 1,
+ cfe->memspace[i].hostaddr ?
+ "@" : "",
+ cfe->memspace[i].hostaddr);
+ }
+ if (cfe->maxtwins)
+ printf("; maxtwins %d", cfe->maxtwins);
+
+ printf(";");
+
+ if (cfe->flags & PCMCIA_CFE_MWAIT_REQUIRED)
+ printf(" mwait_required");
+ if (cfe->flags & PCMCIA_CFE_RDYBSY_ACTIVE)
+ printf(" rdybsy_active");
+ if (cfe->flags & PCMCIA_CFE_WP_ACTIVE)
+ printf(" wp_active");
+ if (cfe->flags & PCMCIA_CFE_BVD_ACTIVE)
+ printf(" bvd_active");
+ if (cfe->flags & PCMCIA_CFE_IO8)
+ printf(" io8");
+ if (cfe->flags & PCMCIA_CFE_IO16)
+ printf(" io16");
+ if (cfe->flags & PCMCIA_CFE_IRQSHARE)
+ printf(" irqshare");
+ if (cfe->flags & PCMCIA_CFE_IRQPULSE)
+ printf(" irqpulse");
+ if (cfe->flags & PCMCIA_CFE_IRQLEVEL)
+ printf(" irqlevel");
+ if (cfe->flags & PCMCIA_CFE_POWERDOWN)
+ printf(" powerdown");
+ if (cfe->flags & PCMCIA_CFE_READONLY)
+ printf(" readonly");
+ if (cfe->flags & PCMCIA_CFE_AUDIO)
+ printf(" audio");
+
+ printf("\n");
+ }
+ }
+
+ if (card->error)
+ printf("%s: %d errors found while parsing CIS\n",
+ sc->dev.dv_xname, card->error);
+}
+
+int
+pcmcia_parse_cis_tuple(tuple, arg)
+ struct pcmcia_tuple *tuple;
+ void *arg;
+{
+ /* most of these are educated guesses */
+ static struct pcmcia_config_entry init_cfe = {
+ -1, PCMCIA_CFE_RDYBSY_ACTIVE | PCMCIA_CFE_WP_ACTIVE |
+ PCMCIA_CFE_BVD_ACTIVE, PCMCIA_IFTYPE_MEMORY,
+ };
+
+ struct cis_state *state = arg;
+
+ switch (tuple->code) {
+ case PCMCIA_CISTPL_END:
+ /* if we've seen a LONGLINK_MFC, and this is the first
+ * END after it, reset the function list.
+ *
+ * XXX This might also be the right place to start a
+ * new function, but that assumes that a function
+ * definition never crosses any longlink, and I'm not
+ * sure about that. This is probably safe for MFC
+ * cards, but what we have now isn't broken, so I'd
+ * rather not change it.
+ */
+ if (state->gotmfc == 1) {
+ struct pcmcia_function *pf, *pfnext;
+
+ for (pf = state->card->pf_head.sqh_first; pf != NULL;
+ pf = pfnext) {
+ pfnext = pf->pf_list.sqe_next;
+ free(pf, M_DEVBUF);
+ }
+
+ SIMPLEQ_INIT(&state->card->pf_head);
+
+ state->count = 0;
+ state->gotmfc = 2;
+ state->pf = NULL;
+ }
+ break;
+ case PCMCIA_CISTPL_LONGLINK_MFC:
+ /*
+ * this tuple's structure was dealt with in scan_cis. here,
+ * record the fact that the MFC tuple was seen, so that
+ * functions declared before the MFC link can be cleaned
+ * up.
+ */
+ state->gotmfc = 1;
+ break;
+#ifdef PCMCIACISDEBUG
+ case PCMCIA_CISTPL_DEVICE:
+ case PCMCIA_CISTPL_DEVICE_A:
+ {
+ u_int reg, dtype, dspeed;
+
+ reg = pcmcia_tuple_read_1(tuple, 0);
+ dtype = reg & PCMCIA_DTYPE_MASK;
+ dspeed = reg & PCMCIA_DSPEED_MASK;
+
+ DPRINTF(("CISTPL_DEVICE%s type=",
+ (tuple->code == PCMCIA_CISTPL_DEVICE) ? "" : "_A"));
+ switch (dtype) {
+ case PCMCIA_DTYPE_NULL:
+ DPRINTF(("null"));
+ break;
+ case PCMCIA_DTYPE_ROM:
+ DPRINTF(("rom"));
+ break;
+ case PCMCIA_DTYPE_OTPROM:
+ DPRINTF(("otprom"));
+ break;
+ case PCMCIA_DTYPE_EPROM:
+ DPRINTF(("eprom"));
+ break;
+ case PCMCIA_DTYPE_EEPROM:
+ DPRINTF(("eeprom"));
+ break;
+ case PCMCIA_DTYPE_FLASH:
+ DPRINTF(("flash"));
+ break;
+ case PCMCIA_DTYPE_SRAM:
+ DPRINTF(("sram"));
+ break;
+ case PCMCIA_DTYPE_DRAM:
+ DPRINTF(("dram"));
+ break;
+ case PCMCIA_DTYPE_FUNCSPEC:
+ DPRINTF(("funcspec"));
+ break;
+ case PCMCIA_DTYPE_EXTEND:
+ DPRINTF(("extend"));
+ break;
+ default:
+ DPRINTF(("reserved"));
+ break;
+ }
+ DPRINTF((" speed="));
+ switch (dspeed) {
+ case PCMCIA_DSPEED_NULL:
+ DPRINTF(("null"));
+ break;
+ case PCMCIA_DSPEED_250NS:
+ DPRINTF(("250ns"));
+ break;
+ case PCMCIA_DSPEED_200NS:
+ DPRINTF(("200ns"));
+ break;
+ case PCMCIA_DSPEED_150NS:
+ DPRINTF(("150ns"));
+ break;
+ case PCMCIA_DSPEED_100NS:
+ DPRINTF(("100ns"));
+ break;
+ case PCMCIA_DSPEED_EXT:
+ DPRINTF(("ext"));
+ break;
+ default:
+ DPRINTF(("reserved"));
+ break;
+ }
+ }
+ DPRINTF(("\n"));
+ break;
+#endif
+ case PCMCIA_CISTPL_VERS_1:
+ if (tuple->length < 6) {
+ DPRINTF(("CISTPL_VERS_1 too short %d\n",
+ tuple->length));
+ break;
+ } {
+ int start, i, ch, count;
+
+ state->card->cis1_major = pcmcia_tuple_read_1(tuple, 0);
+ state->card->cis1_minor = pcmcia_tuple_read_1(tuple, 1);
+
+ for (count = 0, start = 0, i = 0;
+ (count < 4) && ((i + 4) < 256); i++) {
+ ch = pcmcia_tuple_read_1(tuple, 2 + i);
+ if (ch == 0xff)
+ break;
+ state->card->cis1_info_buf[i] = ch;
+ if (ch == 0) {
+ state->card->cis1_info[count] =
+ state->card->cis1_info_buf + start;
+ start = i + 1;
+ count++;
+ }
+ }
+ DPRINTF(("CISTPL_VERS_1\n"));
+ }
+ break;
+ case PCMCIA_CISTPL_MANFID:
+ if (tuple->length < 4) {
+ DPRINTF(("CISTPL_MANFID too short %d\n",
+ tuple->length));
+ break;
+ }
+ state->card->manufacturer = pcmcia_tuple_read_2(tuple, 0);
+ state->card->product = pcmcia_tuple_read_2(tuple, 2);
+ DPRINTF(("CISTPL_MANFID\n"));
+ break;
+ case PCMCIA_CISTPL_FUNCID:
+ if (tuple->length < 1) {
+ DPRINTF(("CISTPL_FUNCID too short %d\n",
+ tuple->length));
+ break;
+ }
+ if ((state->pf == NULL) || (state->gotmfc == 2)) {
+ state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
+ M_NOWAIT);
+ bzero(state->pf, sizeof(*state->pf));
+ state->pf->number = state->count++;
+ state->pf->last_config_index = -1;
+ SIMPLEQ_INIT(&state->pf->cfe_head);
+
+ SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf,
+ pf_list);
+ }
+ state->pf->function = pcmcia_tuple_read_1(tuple, 0);
+
+ DPRINTF(("CISTPL_FUNCID\n"));
+ break;
+ case PCMCIA_CISTPL_CONFIG:
+ if (tuple->length < 3) {
+ DPRINTF(("CISTPL_CONFIG too short %d\n",
+ tuple->length));
+ break;
+ } {
+ u_int reg, rasz, rmsz, rfsz;
+ int i;
+
+ reg = pcmcia_tuple_read_1(tuple, 0);
+ rasz = 1 + ((reg & PCMCIA_TPCC_RASZ_MASK) >>
+ PCMCIA_TPCC_RASZ_SHIFT);
+ rmsz = 1 + ((reg & PCMCIA_TPCC_RMSZ_MASK) >>
+ PCMCIA_TPCC_RMSZ_SHIFT);
+ rfsz = ((reg & PCMCIA_TPCC_RFSZ_MASK) >>
+ PCMCIA_TPCC_RFSZ_SHIFT);
+
+ if (tuple->length < (rasz + rmsz + rfsz)) {
+ DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
+ "short %d\n", rasz, rmsz, rfsz,
+ tuple->length));
+ break;
+ }
+ if (state->pf == NULL) {
+ state->pf = malloc(sizeof(*state->pf),
+ M_DEVBUF, M_NOWAIT);
+ bzero(state->pf, sizeof(*state->pf));
+ state->pf->number = state->count++;
+ state->pf->last_config_index = -1;
+ SIMPLEQ_INIT(&state->pf->cfe_head);
+
+ SIMPLEQ_INSERT_TAIL(&state->card->pf_head,
+ state->pf, pf_list);
+
+ state->pf->function = PCMCIA_FUNCTION_UNSPEC;
+ }
+ state->pf->last_config_index =
+ pcmcia_tuple_read_1(tuple, 1);
+
+ state->pf->ccr_base = 0;
+ for (i = 0; i < rasz; i++)
+ state->pf->ccr_base |=
+ ((pcmcia_tuple_read_1(tuple, 2 + i)) <<
+ (i * 8));
+
+ state->pf->ccr_mask = 0;
+ for (i = 0; i < rmsz; i++)
+ state->pf->ccr_mask |=
+ ((pcmcia_tuple_read_1(tuple,
+ 2 + rasz + i)) << (i * 8));
+
+ /* skip the reserved area and subtuples */
+
+ /* reset the default cfe for each cfe list */
+ state->temp_cfe = init_cfe;
+ state->default_cfe = &state->temp_cfe;
+ }
+ DPRINTF(("CISTPL_CONFIG\n"));
+ break;
+ case PCMCIA_CISTPL_CFTABLE_ENTRY:
+ {
+ int idx, i, j;
+ u_int reg, reg2;
+ u_int intface, def, num;
+ u_int power, timing, iospace, irq, memspace, misc;
+ struct pcmcia_config_entry *cfe;
+
+ idx = 0;
+
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ intface = reg & PCMCIA_TPCE_INDX_INTFACE;
+ def = reg & PCMCIA_TPCE_INDX_DEFAULT;
+ num = reg & PCMCIA_TPCE_INDX_NUM_MASK;
+
+ /*
+ * this is a little messy. Some cards have only a
+ * cfentry with the default bit set. So, as we go
+ * through the list, we add new indexes to the queue,
+ * and keep a pointer to the last one with the
+ * default bit set. if we see a record with the same
+ * index, as the default, we stash the default and
+ * replace the queue entry. otherwise, we just add
+ * new entries to the queue, pointing the default ptr
+ * at them if the default bit is set. if we get to
+ * the end with the default pointer pointing at a
+ * record which hasn't had a matching index, that's
+ * ok; it just becomes a cfentry like any other.
+ */
+
+ /*
+ * if the index in the cis differs from the default
+ * cis, create new entry in the queue and start it
+ * with the current default
+ */
+ if (num != state->default_cfe->number) {
+ cfe = (struct pcmcia_config_entry *)
+ malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
+
+ *cfe = *state->default_cfe;
+
+ SIMPLEQ_INSERT_TAIL(&state->pf->cfe_head,
+ cfe, cfe_list);
+
+ cfe->number = num;
+
+ /*
+ * if the default bit is set in the cis, then
+ * point the new default at whatever is being
+ * filled in
+ */
+ if (def)
+ state->default_cfe = cfe;
+ } else {
+ /*
+ * the cis index matches the default index,
+ * fill in the default cfentry. It is
+ * assumed that the cfdefault index is in the
+ * queue. For it to be otherwise, the cis
+ * index would have to be -1 (initial
+ * condition) which is not possible, or there
+ * would have to be a preceding cis entry
+ * which had the same cis index and had the
+ * default bit unset. Neither condition
+ * should happen. If it does, this cfentry
+ * is lost (written into temp space), which
+ * is an acceptable failure mode.
+ */
+
+ cfe = state->default_cfe;
+
+ /*
+ * if the cis entry does not have the default
+ * bit set, copy the default out of the way
+ * first.
+ */
+ if (!def) {
+ state->temp_cfe = *state->default_cfe;
+ state->default_cfe = &state->temp_cfe;
+ }
+ }
+
+ if (intface) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ if (reg & PCMCIA_TPCE_IF_MWAIT)
+ cfe->flags |= PCMCIA_CFE_MWAIT_REQUIRED;
+ if (reg & PCMCIA_TPCE_IF_RDYBSY)
+ cfe->flags |= PCMCIA_CFE_RDYBSY_ACTIVE;
+ if (reg & PCMCIA_TPCE_IF_WP)
+ cfe->flags |= PCMCIA_CFE_WP_ACTIVE;
+ if (reg & PCMCIA_TPCE_IF_BVD)
+ cfe->flags |= PCMCIA_CFE_BVD_ACTIVE;
+ cfe->iftype = reg & PCMCIA_TPCE_IF_IFTYPE;
+ }
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ power = reg & PCMCIA_TPCE_FS_POWER_MASK;
+ timing = reg & PCMCIA_TPCE_FS_TIMING;
+ iospace = reg & PCMCIA_TPCE_FS_IOSPACE;
+ irq = reg & PCMCIA_TPCE_FS_IRQ;
+ memspace = reg & PCMCIA_TPCE_FS_MEMSPACE_MASK;
+ misc = reg & PCMCIA_TPCE_FS_MISC;
+
+ if (power) {
+ /* skip over power, don't save */
+ /* for each parameter selection byte */
+ for (i = 0; i < power; i++) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ /* for each bit */
+ for (j = 0; j < 7; j++) {
+ /* if the bit is set */
+ if ((reg >> j) & 0x01) {
+ /* skip over bytes */
+ do {
+ reg2 = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ /*
+ * until
+ * non-extensi
+ * on byte
+ */
+ } while (reg2 & 0x80);
+ }
+ }
+ }
+ }
+ if (timing) {
+ /* skip over timing, don't save */
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ if ((reg & PCMCIA_TPCE_TD_RESERVED_MASK) !=
+ PCMCIA_TPCE_TD_RESERVED_MASK)
+ idx++;
+ if ((reg & PCMCIA_TPCE_TD_RDYBSY_MASK) !=
+ PCMCIA_TPCE_TD_RDYBSY_MASK)
+ idx++;
+ if ((reg & PCMCIA_TPCE_TD_WAIT_MASK) !=
+ PCMCIA_TPCE_TD_WAIT_MASK)
+ idx++;
+ }
+ if (iospace) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ if (reg & PCMCIA_TPCE_IO_BUSWIDTH_8BIT)
+ cfe->flags |= PCMCIA_CFE_IO8;
+ if (reg & PCMCIA_TPCE_IO_BUSWIDTH_16BIT)
+ cfe->flags |= PCMCIA_CFE_IO16;
+ cfe->iomask =
+ reg & PCMCIA_TPCE_IO_IOADDRLINES_MASK;
+
+ if (reg & PCMCIA_TPCE_IO_HASRANGE) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ cfe->num_iospace = 1 + (reg &
+ PCMCIA_TPCE_IO_RANGE_COUNT);
+
+ if (cfe->num_iospace >
+ (sizeof(cfe->iospace) /
+ sizeof(cfe->iospace[0]))) {
+ DPRINTF(("too many io "
+ "spaces %d",
+ cfe->num_iospace));
+ state->card->error++;
+ break;
+ }
+ for (i = 0; i < cfe->num_iospace; i++) {
+ switch (reg & PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK) {
+ case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE:
+ cfe->iospace[i].start =
+ pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ break;
+ case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO:
+ cfe->iospace[i].start =
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ break;
+ case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR:
+ cfe->iospace[i].start =
+ pcmcia_tuple_read_4(tuple, idx);
+ idx += 4;
+ break;
+ }
+ switch (reg &
+ PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
+ case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE:
+ cfe->iospace[i].length =
+ pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ break;
+ case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO:
+ cfe->iospace[i].length =
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ break;
+ case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
+ cfe->iospace[i].length =
+ pcmcia_tuple_read_4(tuple, idx);
+ idx += 4;
+ break;
+ }
+ cfe->iospace[i].length++;
+ }
+ } else {
+ cfe->num_iospace = 1;
+ cfe->iospace[0].start = 0;
+ cfe->iospace[0].length =
+ (1 << cfe->iomask);
+ }
+ }
+ if (irq) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ if (reg & PCMCIA_TPCE_IR_SHARE)
+ cfe->flags |= PCMCIA_CFE_IRQSHARE;
+ if (reg & PCMCIA_TPCE_IR_PULSE)
+ cfe->flags |= PCMCIA_CFE_IRQPULSE;
+ if (reg & PCMCIA_TPCE_IR_LEVEL)
+ cfe->flags |= PCMCIA_CFE_IRQLEVEL;
+
+ if (reg & PCMCIA_TPCE_IR_HASMASK) {
+ /*
+ * it's legal to ignore the
+ * special-interrupt bits, so I will
+ */
+
+ cfe->irqmask =
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ } else {
+ cfe->irqmask =
+ (1 << (reg & PCMCIA_TPCE_IR_IRQ));
+ }
+ }
+ if (memspace) {
+ if (memspace == PCMCIA_TPCE_FS_MEMSPACE_LENGTH) {
+ cfe->num_memspace = 1;
+ cfe->memspace[0].length = 256 *
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ cfe->memspace[0].cardaddr = 0;
+ cfe->memspace[0].hostaddr = 0;
+ } else if (memspace ==
+ PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR) {
+ cfe->num_memspace = 1;
+ cfe->memspace[0].length = 256 *
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ cfe->memspace[0].cardaddr = 256 *
+ pcmcia_tuple_read_2(tuple, idx);
+ idx += 2;
+ cfe->memspace[0].hostaddr = 0;
+ } else {
+ int lengthsize;
+ int cardaddrsize;
+ int hostaddrsize;
+
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ cfe->num_memspace = reg &
+ PCMCIA_TPCE_MS_COUNT;
+
+ if (cfe->num_memspace >
+ (sizeof(cfe->memspace) /
+ sizeof(cfe->memspace[0]))) {
+ DPRINTF(("too many mem "
+ "spaces %d",
+ cfe->num_memspace));
+ state->card->error++;
+ break;
+ }
+ lengthsize =
+ ((reg & PCMCIA_TPCE_MS_LENGTH_SIZE_MASK) >>
+ PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT);
+ cardaddrsize =
+ ((reg & PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK) >>
+ PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT);
+ hostaddrsize =
+ (reg & PCMCIA_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
+
+ if (lengthsize == 0) {
+ DPRINTF(("cfe memspace "
+ "lengthsize == 0"));
+ state->card->error++;
+ }
+ for (i = 0; i < cfe->num_memspace; i++) {
+ if (lengthsize) {
+ cfe->memspace[i].length =
+ 256 * pcmcia_tuple_read_n(tuple, lengthsize,
+ idx);
+ idx += lengthsize;
+ } else {
+ cfe->memspace[i].length = 0;
+ }
+ if (cfe->memspace[i].length == 0) {
+ DPRINTF(("cfe->memspace[%d].length == 0",
+ i));
+ state->card->error++;
+ }
+ if (cardaddrsize) {
+ cfe->memspace[i].cardaddr =
+ 256 * pcmcia_tuple_read_n(tuple, cardaddrsize,
+ idx);
+ idx += cardaddrsize;
+ } else {
+ cfe->memspace[i].cardaddr = 0;
+ }
+ if (hostaddrsize) {
+ cfe->memspace[i].hostaddr =
+ 256 * pcmcia_tuple_read_n(tuple, hostaddrsize,
+ idx);
+ idx += hostaddrsize;
+ } else {
+ cfe->memspace[i].hostaddr = 0;
+ }
+ }
+ }
+ }
+ if (misc) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+
+ if (reg & PCMCIA_TPCE_MI_PWRDOWN)
+ cfe->flags = PCMCIA_CFE_POWERDOWN;
+ if (reg & PCMCIA_TPCE_MI_READONLY)
+ cfe->flags = PCMCIA_CFE_READONLY;
+ if (reg & PCMCIA_TPCE_MI_AUDIO)
+ cfe->flags = PCMCIA_CFE_AUDIO;
+ cfe->maxtwins = reg & PCMCIA_TPCE_MI_MAXTWINS;
+
+ while (reg & PCMCIA_TPCE_MI_EXT) {
+ reg = pcmcia_tuple_read_1(tuple, idx);
+ idx++;
+ }
+ }
+ /* skip all the subtuples */
+ }
+ DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
+ break;
+ default:
+ DPRINTF(("unhandled CISTPL %x\n", tuple->code));
+ break;
+ }
+
+ return (0);
+}
diff --git a/sys/dev/pcmcia/pcmciachip.h b/sys/dev/pcmcia/pcmciachip.h
new file mode 100644
index 00000000000..6950c6775e9
--- /dev/null
+++ b/sys/dev/pcmcia/pcmciachip.h
@@ -0,0 +1,145 @@
+/* $OpenBSD: pcmciachip.h,v 1.1 1998/09/11 10:47:15 fgsch Exp $ */
+/* $NetBSD: pcmciachip.h,v 1.2 1997/10/16 23:27:36 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.
+ */
+
+#ifndef _PCMCIA_PCMCIACHIP_H_
+#define _PCMCIA_PCMCIACHIP_H_
+
+#include <machine/bus.h>
+
+struct pcmcia_function;
+struct pcmcia_mem_handle;
+struct pcmcia_io_handle;
+
+/* interfaces for pcmcia to call the chipset */
+
+typedef struct pcmcia_chip_functions *pcmcia_chipset_tag_t;
+typedef void *pcmcia_chipset_handle_t;
+typedef int pcmcia_mem_handle_t;
+
+#define PCMCIA_MEM_ATTR 1
+#define PCMCIA_MEM_COMMON 2
+
+#define PCMCIA_WIDTH_AUTO 0
+#define PCMCIA_WIDTH_IO8 1
+#define PCMCIA_WIDTH_IO16 2
+
+struct pcmcia_chip_functions {
+ /* memory space allocation */
+ int (*mem_alloc) __P((pcmcia_chipset_handle_t, bus_size_t,
+ struct pcmcia_mem_handle *));
+ void (*mem_free) __P((pcmcia_chipset_handle_t,
+ struct pcmcia_mem_handle *));
+
+ /* memory space window mapping */
+ int (*mem_map) __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_mem_handle *,
+ bus_addr_t *, int *));
+ void (*mem_unmap) __P((pcmcia_chipset_handle_t, int));
+
+ /* I/O space allocation */
+ int (*io_alloc) __P((pcmcia_chipset_handle_t, bus_addr_t,
+ bus_size_t, bus_size_t, struct pcmcia_io_handle *));
+ void (*io_free) __P((pcmcia_chipset_handle_t,
+ struct pcmcia_io_handle *));
+
+ /* I/O space window mapping */
+ int (*io_map) __P((pcmcia_chipset_handle_t, int, bus_addr_t,
+ bus_size_t, struct pcmcia_io_handle *, int *));
+ void (*io_unmap) __P((pcmcia_chipset_handle_t, int));
+
+ /* interrupt glue */
+ void *(*intr_establish) __P((pcmcia_chipset_handle_t,
+ struct pcmcia_function *, int, int (*)(void *), void *));
+ void (*intr_disestablish) __P((pcmcia_chipset_handle_t, void *));
+
+ /* card enable/disable */
+ void (*socket_enable) __P((pcmcia_chipset_handle_t));
+ void (*socket_disable) __P((pcmcia_chipset_handle_t));
+};
+
+/* Memory space functions. */
+#define pcmcia_chip_mem_alloc(tag, handle, size, pcmhp) \
+ ((*(tag)->mem_alloc)((handle), (size), (pcmhp)))
+
+#define pcmcia_chip_mem_free(tag, handle, pcmhp) \
+ ((*(tag)->mem_free)((handle), (pcmhp)))
+
+#define pcmcia_chip_mem_map(tag, handle, kind, card_addr, size, pcmhp, \
+ offsetp, windowp) \
+ ((*(tag)->mem_map)((handle), (kind), (card_addr), (size), (pcmhp), \
+ (offsetp), (windowp)))
+
+#define pcmcia_chip_mem_unmap(tag, handle, window) \
+ ((*(tag)->mem_unmap)((handle), (window)))
+
+/* I/O space functions. */
+#define pcmcia_chip_io_alloc(tag, handle, start, size, align, pcihp) \
+ ((*(tag)->io_alloc)((handle), (start), (size), (align), (pcihp)))
+
+#define pcmcia_chip_io_free(tag, handle, pcihp) \
+ ((*(tag)->io_free)((handle), (pcihp)))
+
+#define pcmcia_chip_io_map(tag, handle, width, card_addr, size, pcihp, \
+ windowp) \
+ ((*(tag)->io_map)((handle), (width), (card_addr), (size), (pcihp), \
+ (windowp)))
+
+#define pcmcia_chip_io_unmap(tag, handle, window) \
+ ((*(tag)->io_unmap)((handle), (window)))
+
+/* Interrupt functions. */
+#define pcmcia_chip_intr_establish(tag, handle, pf, ipl, fct, arg) \
+ ((*(tag)->intr_establish)((handle), (pf), (ipl), (fct), (arg)))
+
+#define pcmcia_chip_intr_disestablish(tag, handle, ih) \
+ ((*(tag)->intr_disestablish)((handle), (ih)))
+
+/* Socket functions. */
+#define pcmcia_chip_socket_enable(tag, handle) \
+ ((*(tag)->socket_enable)((handle)))
+#define pcmcia_chip_socket_disable(tag, handle) \
+ ((*(tag)->socket_disable)((handle)))
+
+struct pcmciabus_attach_args {
+ pcmcia_chipset_tag_t pct;
+ pcmcia_chipset_handle_t pch;
+ bus_addr_t iobase; /* start i/o space allocation here */
+ bus_size_t iosize; /* size of the i/o space range */
+};
+
+/* interfaces for the chipset to call pcmcia */
+
+int pcmcia_card_attach __P((struct device *));
+void pcmcia_card_detach __P((struct device *));
+int pcmcia_card_gettype __P((struct device *));
+
+#endif /* _PCMCIA_PCMCIACHIP_H_ */
diff --git a/sys/dev/pcmcia/pcmciadevs b/sys/dev/pcmcia/pcmciadevs
new file mode 100644
index 00000000000..7bbc4091464
--- /dev/null
+++ b/sys/dev/pcmcia/pcmciadevs
@@ -0,0 +1,129 @@
+ $OpenBSD: pcmciadevs,v 1.1 1998/09/11 10:47:15 fgsch Exp $
+/* $NetBSD: pcmciadevs,v 1.13 1998/08/17 23:10:12 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1998, Christos Zoulas
+ * 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 Christos Zoulas
+ * for the NetBSD Project.
+ * 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.
+ */
+
+/*
+ * List of known PCMCIA vendors
+ */
+
+vendor NEWMEDIA 0x0057 NewMedia Corporation
+vendor IBM 0x00a4 IBM Corporation
+vendor 3COM 0x0101 3Com Corporation
+vendor MEGAHERTZ 0x0102 Megahertz Corporation
+vendor SOCKET 0x0104 Socket Communications
+vendor TDK 0x0105 TDK Corporation
+vendor SMC 0x0108 Standard Microsystems Corporation
+vendor MOTOROLA 0x0109 Motorola Corporation
+vendor USROBOTICS 0x0115 US Robotics Corporation
+vendor MEGAHERTZ2 0x0128 Megahertz Corporation
+vendor ADAPTEC 0x012f Adaptec Corporation
+vendor LINKSYS 0x0149 Linksys Corporation
+vendor SIMPLETECH 0x014d Simple Technology
+vendor DAYNA 0x0194 Dayna Corporation
+vendor IODATA 0x01bf I-O DATA
+
+/*
+ * List of known products. Grouped by vendor.
+ */
+/* Adaptec Products */
+product ADAPTEC APA1460_1 0x0001 Adaptec APA-1460/A SCSI Host Adapter
+product ADAPTEC APA1460_2 0x0002 Adaptec APA-1460/B SCSI Host Adapter
+
+/* 3COM Products */
+product 3COM 3C562 0x0562 3Com 3c562 33.6 Modem/10Mbps Ethernet
+product 3COM 3C589 0x0589 3Com 3c589 10Mbps Ethernet
+product 3COM 3C574 0x0574 3Com 3c574-TX 10/100Mbps Ethernet
+
+/* Dayna Products */
+product DAYNA COMMUNICARD_E 0x002d Dayna CommuniCard E
+
+/* Motorola Products */
+product MOTOROLA POWER144 0x0105 Motorola Power 14.4 Modem
+product MOTOROLA PM100C 0x0302 Motorola Personal Messenger 100C CDPD Modem
+product MOTOROLA MONTANA_33.6 0x0505 Motorola Montana 33.6 Fax/Modem
+
+/* IBM Products */
+product IBM INFOMOVER 0x0002 National Semiconductor InfoMover
+product IBM HOME_AND_AWAY 0x002e IBM Home and Away Modem
+
+/* I-O DATA */
+product IODATA PCLAT 0x2216 I-O DATA PCLA/T
+
+/* Linksys corporation */
+product LINKSYS ECARD 0x0265 Linksys EthernetCard
+product LINKSYS COMBO_ECARD 0xc1ab Linksys Combo EthernetCard
+product LINKSYS TRUST_COMBO_ECARD 0x021b Trust (Linksys) Combo EthernetCard
+
+/* Megahertz Products */
+product MEGAHERTZ XJ4288 0x0023 Megahertz XJ4288 Modem
+product MEGAHERTZ2 XJEM1144 0x0101 Megahertz XJEM1144 Ethernet
+product MEGAHERTZ2 XJACK 0x0103 Megahertz X-JACK Ethernet
+
+/* US Robotics Products */
+product USROBOTICS WORLDPORT144 0x3330 US Robotics WorldPort 14.4 Modem
+
+/* Simple Technology Products */
+product SIMPLETECH COMMUNICATOR288 0x0100 Simple Technology 28.8 Communicator
+
+/* Socket Communications Products */
+product SOCKET PAGECARD 0x0003 Socket Communications PageCard
+product SOCKET DUAL_RS232 0x0012 Socket Communications Dual RS232
+
+/* TDK Products */
+product TDK LAK_CD021BX 0x0200 TDK LAK-CD021BX Ethernet
+product TDK DFL9610 0x0d0a TDK DFL9610 Ethernet & Digital Cellular
+
+/* NewMedia Products */
+product NEWMEDIA BASICS 0x0019 NewMedia BASICS Ethernet
+
+/* Standard Microsystems Corporation Products */
+product SMC 8016 0x0105 SMC 8016 EtherCard
+
+/* Cards we know only by their cis */
+vendor PREMAX -1 Premax
+vendor PLANET -1 Planet
+vendor DLINK -1 D-Link
+vendor RPTI -1 RPTI
+vendor ACCTON -1 ACCTON
+vendor YEDATA -1 Y-E DATA
+vendor DIGITAL -1 Digital Equipment Corporation
+
+product MEGAHERTZ XJ2288 { "MEGAHERTZ", "MODEM&spXJ2288", NULL, NULL } Megahertz XJ2288 Modem
+product PREMAX PE200 { "PMX&sp&sp&sp", "PE-200", NULL, NULL } PreMax PE-200
+product PLANET SMARTCOM2000 { "PCMCIA", "UE2212", NULL, NULL } Planet SmartCOM 2000
+product DLINK DE650 { "D-Link", "DE-650", NULL, NULL } D-Link DE-650
+product DLINK DE660 { "D-Link", "DE-660", NULL, NULL } D-Link DE-660
+product RPTI EP401 { "RPTI", "EP401&spEthernet&spNE2000&spCompatible", NULL, NULL } RPTI EP401
+product ACCTON EN2212 { "ACCTON", "EN2212", NULL, NULL } Accton EN2212
+product YEDATA EXTERNAL_FDD { "Y-E&spDATA", "External&spFDD", NULL, NULL } Y-E DATA External FDD
+product DIGITAL DEPCMXX { "DIGITAL", "DEPCM-XX", NULL, NULL } DEC DEPCM-BA
diff --git a/sys/dev/pcmcia/pcmciadevs.h b/sys/dev/pcmcia/pcmciadevs.h
new file mode 100644
index 00000000000..d5052d8dd5a
--- /dev/null
+++ b/sys/dev/pcmcia/pcmciadevs.h
@@ -0,0 +1,206 @@
+/* $OpenBSD: pcmciadevs.h,v 1.1 1998/09/11 10:47:15 fgsch Exp $ */
+
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * generated from:
+ * OpenBSD
+ */
+/* $NetBSD: pcmciadevs,v 1.13 1998/08/17 23:10:12 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1998, Christos Zoulas
+ * 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 Christos Zoulas
+ * for the NetBSD Project.
+ * 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.
+ */
+
+/*
+ * List of known PCMCIA vendors
+ */
+
+#define PCMCIA_VENDOR_NEWMEDIA 0x0057 /* NewMedia Corporation */
+#define PCMCIA_VENDOR_IBM 0x00a4 /* IBM Corporation */
+#define PCMCIA_VENDOR_3COM 0x0101 /* 3Com Corporation */
+#define PCMCIA_VENDOR_MEGAHERTZ 0x0102 /* Megahertz Corporation */
+#define PCMCIA_VENDOR_SOCKET 0x0104 /* Socket Communications */
+#define PCMCIA_VENDOR_TDK 0x0105 /* TDK Corporation */
+#define PCMCIA_VENDOR_SMC 0x0108 /* Standard Microsystems Corporation */
+#define PCMCIA_VENDOR_MOTOROLA 0x0109 /* Motorola Corporation */
+#define PCMCIA_VENDOR_USROBOTICS 0x0115 /* US Robotics Corporation */
+#define PCMCIA_VENDOR_MEGAHERTZ2 0x0128 /* Megahertz Corporation */
+#define PCMCIA_VENDOR_ADAPTEC 0x012f /* Adaptec Corporation */
+#define PCMCIA_VENDOR_LINKSYS 0x0149 /* Linksys Corporation */
+#define PCMCIA_VENDOR_SIMPLETECH 0x014d /* Simple Technology */
+#define PCMCIA_VENDOR_DAYNA 0x0194 /* Dayna Corporation */
+#define PCMCIA_VENDOR_IODATA 0x01bf /* I-O DATA */
+
+/*
+ * List of known products. Grouped by vendor.
+ */
+/* Adaptec Products */
+#define PCMCIA_CIS_ADAPTEC_APA1460_1 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_ADAPTEC_APA1460_1 0x0001
+#define PCMCIA_STR_ADAPTEC_APA1460_1 "Adaptec APA-1460/A SCSI Host Adapter"
+#define PCMCIA_CIS_ADAPTEC_APA1460_2 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_ADAPTEC_APA1460_2 0x0002
+#define PCMCIA_STR_ADAPTEC_APA1460_2 "Adaptec APA-1460/B SCSI Host Adapter"
+
+/* 3COM Products */
+#define PCMCIA_CIS_3COM_3C562 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_3COM_3C562 0x0562
+#define PCMCIA_STR_3COM_3C562 "3Com 3c562 33.6 Modem/10Mbps Ethernet"
+#define PCMCIA_CIS_3COM_3C589 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_3COM_3C589 0x0589
+#define PCMCIA_STR_3COM_3C589 "3Com 3c589 10Mbps Ethernet"
+#define PCMCIA_CIS_3COM_3C574 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_3COM_3C574 0x0574
+#define PCMCIA_STR_3COM_3C574 "3Com 3c574-TX 10/100Mbps Ethernet"
+
+/* Dayna Products */
+#define PCMCIA_CIS_DAYNA_COMMUNICARD_E { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_DAYNA_COMMUNICARD_E 0x002d
+#define PCMCIA_STR_DAYNA_COMMUNICARD_E "Dayna CommuniCard E"
+
+/* Motorola Products */
+#define PCMCIA_CIS_MOTOROLA_POWER144 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MOTOROLA_POWER144 0x0105
+#define PCMCIA_STR_MOTOROLA_POWER144 "Motorola Power 14.4 Modem"
+#define PCMCIA_CIS_MOTOROLA_PM100C { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MOTOROLA_PM100C 0x0302
+#define PCMCIA_STR_MOTOROLA_PM100C "Motorola Personal Messenger 100C CDPD Modem"
+#define PCMCIA_CIS_MOTOROLA_MONTANA_33.6 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MOTOROLA_MONTANA_33.6 0x0505
+#define PCMCIA_STR_MOTOROLA_MONTANA_33.6 "Motorola Montana 33.6 Fax/Modem"
+
+/* IBM Products */
+#define PCMCIA_CIS_IBM_INFOMOVER { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_IBM_INFOMOVER 0x0002
+#define PCMCIA_STR_IBM_INFOMOVER "National Semiconductor InfoMover"
+#define PCMCIA_CIS_IBM_HOME_AND_AWAY { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_IBM_HOME_AND_AWAY 0x002e
+#define PCMCIA_STR_IBM_HOME_AND_AWAY "IBM Home and Away Modem"
+
+/* I-O DATA */
+#define PCMCIA_CIS_IODATA_PCLAT { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_IODATA_PCLAT 0x2216
+#define PCMCIA_STR_IODATA_PCLAT "I-O DATA PCLA/T"
+
+/* Linksys corporation */
+#define PCMCIA_CIS_LINKSYS_ECARD { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_LINKSYS_ECARD 0x0265
+#define PCMCIA_STR_LINKSYS_ECARD "Linksys EthernetCard"
+#define PCMCIA_CIS_LINKSYS_COMBO_ECARD { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD 0xc1ab
+#define PCMCIA_STR_LINKSYS_COMBO_ECARD "Linksys Combo EthernetCard"
+#define PCMCIA_CIS_LINKSYS_TRUST_COMBO_ECARD { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_LINKSYS_TRUST_COMBO_ECARD 0x021b
+#define PCMCIA_STR_LINKSYS_TRUST_COMBO_ECARD "Trust (Linksys) Combo EthernetCard"
+
+/* Megahertz Products */
+#define PCMCIA_CIS_MEGAHERTZ_XJ4288 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MEGAHERTZ_XJ4288 0x0023
+#define PCMCIA_STR_MEGAHERTZ_XJ4288 "Megahertz XJ4288 Modem"
+#define PCMCIA_CIS_MEGAHERTZ2_XJEM1144 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144 0x0101
+#define PCMCIA_STR_MEGAHERTZ2_XJEM1144 "Megahertz XJEM1144 Ethernet"
+#define PCMCIA_CIS_MEGAHERTZ2_XJACK { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_MEGAHERTZ2_XJACK 0x0103
+#define PCMCIA_STR_MEGAHERTZ2_XJACK "Megahertz X-JACK Ethernet"
+
+/* US Robotics Products */
+#define PCMCIA_CIS_USROBOTICS_WORLDPORT144 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_USROBOTICS_WORLDPORT144 0x3330
+#define PCMCIA_STR_USROBOTICS_WORLDPORT144 "US Robotics WorldPort 14.4 Modem"
+
+/* Simple Technology Products */
+#define PCMCIA_CIS_SIMPLETECH_COMMUNICATOR288 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_SIMPLETECH_COMMUNICATOR288 0x0100
+#define PCMCIA_STR_SIMPLETECH_COMMUNICATOR288 "Simple Technology 28.8 Communicator"
+
+/* Socket Communications Products */
+#define PCMCIA_CIS_SOCKET_PAGECARD { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_SOCKET_PAGECARD 0x0003
+#define PCMCIA_STR_SOCKET_PAGECARD "Socket Communications PageCard"
+#define PCMCIA_CIS_SOCKET_DUAL_RS232 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_SOCKET_DUAL_RS232 0x0012
+#define PCMCIA_STR_SOCKET_DUAL_RS232 "Socket Communications Dual RS232"
+
+/* TDK Products */
+#define PCMCIA_CIS_TDK_LAK_CD021BX { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_TDK_LAK_CD021BX 0x0200
+#define PCMCIA_STR_TDK_LAK_CD021BX "TDK LAK-CD021BX Ethernet"
+#define PCMCIA_CIS_TDK_DFL9610 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_TDK_DFL9610 0x0d0a
+#define PCMCIA_STR_TDK_DFL9610 "TDK DFL9610 Ethernet & Digital Cellular"
+
+/* NewMedia Products */
+#define PCMCIA_CIS_NEWMEDIA_BASICS { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_NEWMEDIA_BASICS 0x0019
+#define PCMCIA_STR_NEWMEDIA_BASICS "NewMedia BASICS Ethernet"
+
+/* Standard Microsystems Corporation Products */
+#define PCMCIA_CIS_SMC_8016 { NULL, NULL, NULL, NULL }
+#define PCMCIA_PRODUCT_SMC_8016 0x0105
+#define PCMCIA_STR_SMC_8016 "SMC 8016 EtherCard"
+
+/* Cards we know only by their cis */
+#define PCMCIA_VENDOR_PREMAX -1 /* Premax */
+#define PCMCIA_VENDOR_PLANET -1 /* Planet */
+#define PCMCIA_VENDOR_DLINK -1 /* D-Link */
+#define PCMCIA_VENDOR_RPTI -1 /* RPTI */
+#define PCMCIA_VENDOR_ACCTON -1 /* ACCTON */
+#define PCMCIA_VENDOR_YEDATA -1 /* Y-E DATA */
+#define PCMCIA_VENDOR_DIGITAL -1 /* Digital Equipment Corporation */
+
+#define PCMCIA_CIS_MEGAHERTZ_XJ2288 { "MEGAHERTZ", "MODEM XJ2288", NULL, NULL }
+#define PCMCIA_PRODUCT_MEGAHERTZ_XJ2288 -1
+#define PCMCIA_STR_MEGAHERTZ_XJ2288 "Megahertz XJ2288 Modem"
+#define PCMCIA_CIS_PREMAX_PE200 { "PMX ", "PE-200", NULL, NULL }
+#define PCMCIA_PRODUCT_PREMAX_PE200 -1
+#define PCMCIA_STR_PREMAX_PE200 "PreMax PE-200"
+#define PCMCIA_CIS_PLANET_SMARTCOM2000 { "PCMCIA", "UE2212", NULL, NULL }
+#define PCMCIA_PRODUCT_PLANET_SMARTCOM2000 -1
+#define PCMCIA_STR_PLANET_SMARTCOM2000 "Planet SmartCOM 2000"
+#define PCMCIA_CIS_DLINK_DE650 { "D-Link", "DE-650", NULL, NULL }
+#define PCMCIA_PRODUCT_DLINK_DE650 -1
+#define PCMCIA_STR_DLINK_DE650 "D-Link DE-650"
+#define PCMCIA_CIS_DLINK_DE660 { "D-Link", "DE-660", NULL, NULL }
+#define PCMCIA_PRODUCT_DLINK_DE660 -1
+#define PCMCIA_STR_DLINK_DE660 "D-Link DE-660"
+#define PCMCIA_CIS_RPTI_EP401 { "RPTI", "EP401 Ethernet NE2000 Compatible", NULL, NULL }
+#define PCMCIA_PRODUCT_RPTI_EP401 -1
+#define PCMCIA_STR_RPTI_EP401 "RPTI EP401"
+#define PCMCIA_CIS_ACCTON_EN2212 { "ACCTON", "EN2212", NULL, NULL }
+#define PCMCIA_PRODUCT_ACCTON_EN2212 -1
+#define PCMCIA_STR_ACCTON_EN2212 "Accton EN2212"
+#define PCMCIA_CIS_YEDATA_EXTERNAL_FDD { "Y-E DATA", "External FDD", NULL, NULL }
+#define PCMCIA_PRODUCT_YEDATA_EXTERNAL_FDD -1
+#define PCMCIA_STR_YEDATA_EXTERNAL_FDD "Y-E DATA External FDD"
+#define PCMCIA_CIS_DIGITAL_DEPCMXX { "DIGITAL", "DEPCM-XX", NULL, NULL }
+#define PCMCIA_PRODUCT_DIGITAL_DEPCMXX -1
+#define PCMCIA_STR_DIGITAL_DEPCMXX "DEC DEPCM-BA"
diff --git a/sys/dev/pcmcia/pcmciadevs_data.h b/sys/dev/pcmcia/pcmciadevs_data.h
new file mode 100644
index 00000000000..f1f13e81280
--- /dev/null
+++ b/sys/dev/pcmcia/pcmciadevs_data.h
@@ -0,0 +1,443 @@
+/* $OpenBSD: pcmciadevs_data.h,v 1.1 1998/09/11 10:47:15 fgsch Exp $ */
+
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * generated from:
+ * OpenBSD
+ */
+/* $NetBSD: pcmciadevs,v 1.13 1998/08/17 23:10:12 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1998, Christos Zoulas
+ * 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 Christos Zoulas
+ * for the NetBSD Project.
+ * 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.
+ */
+
+struct pcmcia_knowndev pcmcia_knowndevs[] = {
+ {
+ PCMCIA_VENDOR_ADAPTEC, PCMCIA_PRODUCT_ADAPTEC_APA1460_1,
+ PCMCIA_CIS_ADAPTEC_APA1460_1,
+ 0,
+ "Adaptec Corporation",
+ "Adaptec APA-1460/A SCSI Host Adapter" },
+ },
+ {
+ PCMCIA_VENDOR_ADAPTEC, PCMCIA_PRODUCT_ADAPTEC_APA1460_2,
+ PCMCIA_CIS_ADAPTEC_APA1460_2,
+ 0,
+ "Adaptec Corporation",
+ "Adaptec APA-1460/B SCSI Host Adapter" },
+ },
+ {
+ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C562,
+ PCMCIA_CIS_3COM_3C562,
+ 0,
+ "3Com Corporation",
+ "3Com 3c562 33.6 Modem/10Mbps Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C589,
+ PCMCIA_CIS_3COM_3C589,
+ 0,
+ "3Com Corporation",
+ "3Com 3c589 10Mbps Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C574,
+ PCMCIA_CIS_3COM_3C574,
+ 0,
+ "3Com Corporation",
+ "3Com 3c574-TX 10/100Mbps Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_DAYNA, PCMCIA_PRODUCT_DAYNA_COMMUNICARD_E,
+ PCMCIA_CIS_DAYNA_COMMUNICARD_E,
+ 0,
+ "Dayna Corporation",
+ "Dayna CommuniCard E" },
+ },
+ {
+ PCMCIA_VENDOR_MOTOROLA, PCMCIA_PRODUCT_MOTOROLA_POWER144,
+ PCMCIA_CIS_MOTOROLA_POWER144,
+ 0,
+ "Motorola Corporation",
+ "Motorola Power 14.4 Modem" },
+ },
+ {
+ PCMCIA_VENDOR_MOTOROLA, PCMCIA_PRODUCT_MOTOROLA_PM100C,
+ PCMCIA_CIS_MOTOROLA_PM100C,
+ 0,
+ "Motorola Corporation",
+ "Motorola Personal Messenger 100C CDPD Modem" },
+ },
+ {
+ PCMCIA_VENDOR_MOTOROLA, PCMCIA_PRODUCT_MOTOROLA_MONTANA_33.6,
+ PCMCIA_CIS_MOTOROLA_MONTANA_33.6,
+ 0,
+ "Motorola Corporation",
+ "Motorola Montana 33.6 Fax/Modem" },
+ },
+ {
+ PCMCIA_VENDOR_IBM, PCMCIA_PRODUCT_IBM_INFOMOVER,
+ PCMCIA_CIS_IBM_INFOMOVER,
+ 0,
+ "IBM Corporation",
+ "National Semiconductor InfoMover" },
+ },
+ {
+ PCMCIA_VENDOR_IBM, PCMCIA_PRODUCT_IBM_HOME_AND_AWAY,
+ PCMCIA_CIS_IBM_HOME_AND_AWAY,
+ 0,
+ "IBM Corporation",
+ "IBM Home and Away Modem" },
+ },
+ {
+ PCMCIA_VENDOR_IODATA, PCMCIA_PRODUCT_IODATA_PCLAT,
+ PCMCIA_CIS_IODATA_PCLAT,
+ 0,
+ "I-O DATA",
+ "I-O DATA PCLA/T" },
+ },
+ {
+ PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_ECARD,
+ PCMCIA_CIS_LINKSYS_ECARD,
+ 0,
+ "Linksys Corporation",
+ "Linksys EthernetCard" },
+ },
+ {
+ PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD,
+ PCMCIA_CIS_LINKSYS_COMBO_ECARD,
+ 0,
+ "Linksys Corporation",
+ "Linksys Combo EthernetCard" },
+ },
+ {
+ PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_TRUST_COMBO_ECARD,
+ PCMCIA_CIS_LINKSYS_TRUST_COMBO_ECARD,
+ 0,
+ "Linksys Corporation",
+ "Trust (Linksys) Combo EthernetCard" },
+ },
+ {
+ PCMCIA_VENDOR_MEGAHERTZ, PCMCIA_PRODUCT_MEGAHERTZ_XJ4288,
+ PCMCIA_CIS_MEGAHERTZ_XJ4288,
+ 0,
+ "Megahertz Corporation",
+ "Megahertz XJ4288 Modem" },
+ },
+ {
+ PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
+ PCMCIA_CIS_MEGAHERTZ2_XJEM1144,
+ 0,
+ "Megahertz Corporation",
+ "Megahertz XJEM1144 Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJACK,
+ PCMCIA_CIS_MEGAHERTZ2_XJACK,
+ 0,
+ "Megahertz Corporation",
+ "Megahertz X-JACK Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_USROBOTICS, PCMCIA_PRODUCT_USROBOTICS_WORLDPORT144,
+ PCMCIA_CIS_USROBOTICS_WORLDPORT144,
+ 0,
+ "US Robotics Corporation",
+ "US Robotics WorldPort 14.4 Modem" },
+ },
+ {
+ PCMCIA_VENDOR_SIMPLETECH, PCMCIA_PRODUCT_SIMPLETECH_COMMUNICATOR288,
+ PCMCIA_CIS_SIMPLETECH_COMMUNICATOR288,
+ 0,
+ "Simple Technology",
+ "Simple Technology 28.8 Communicator" },
+ },
+ {
+ PCMCIA_VENDOR_SOCKET, PCMCIA_PRODUCT_SOCKET_PAGECARD,
+ PCMCIA_CIS_SOCKET_PAGECARD,
+ 0,
+ "Socket Communications",
+ "Socket Communications PageCard" },
+ },
+ {
+ PCMCIA_VENDOR_SOCKET, PCMCIA_PRODUCT_SOCKET_DUAL_RS232,
+ PCMCIA_CIS_SOCKET_DUAL_RS232,
+ 0,
+ "Socket Communications",
+ "Socket Communications Dual RS232" },
+ },
+ {
+ PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_LAK_CD021BX,
+ PCMCIA_CIS_TDK_LAK_CD021BX,
+ 0,
+ "TDK Corporation",
+ "TDK LAK-CD021BX Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_DFL9610,
+ PCMCIA_CIS_TDK_DFL9610,
+ 0,
+ "TDK Corporation",
+ "TDK DFL9610 Ethernet & Digital Cellular" },
+ },
+ {
+ PCMCIA_VENDOR_NEWMEDIA, PCMCIA_PRODUCT_NEWMEDIA_BASICS,
+ PCMCIA_CIS_NEWMEDIA_BASICS,
+ 0,
+ "NewMedia Corporation",
+ "NewMedia BASICS Ethernet" },
+ },
+ {
+ PCMCIA_VENDOR_SMC, PCMCIA_PRODUCT_SMC_8016,
+ PCMCIA_CIS_SMC_8016,
+ 0,
+ "Standard Microsystems Corporation",
+ "SMC 8016 EtherCard" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_MEGAHERTZ_XJ2288,
+ PCMCIA_CIS_MEGAHERTZ_XJ2288,
+ 0,
+ "Megahertz Corporation",
+ "Megahertz XJ2288 Modem" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_PREMAX_PE200,
+ PCMCIA_CIS_PREMAX_PE200,
+ 0,
+ "Premax",
+ "PreMax PE-200" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_PLANET_SMARTCOM2000,
+ PCMCIA_CIS_PLANET_SMARTCOM2000,
+ 0,
+ "Planet",
+ "Planet SmartCOM 2000" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_DLINK_DE650,
+ PCMCIA_CIS_DLINK_DE650,
+ 0,
+ "D-Link",
+ "D-Link DE-650" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_DLINK_DE660,
+ PCMCIA_CIS_DLINK_DE660,
+ 0,
+ "D-Link",
+ "D-Link DE-660" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_RPTI_EP401,
+ PCMCIA_CIS_RPTI_EP401,
+ 0,
+ "RPTI",
+ "RPTI EP401" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_ACCTON_EN2212,
+ PCMCIA_CIS_ACCTON_EN2212,
+ 0,
+ "ACCTON",
+ "Accton EN2212" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_YEDATA_EXTERNAL_FDD,
+ PCMCIA_CIS_YEDATA_EXTERNAL_FDD,
+ 0,
+ "Y-E DATA",
+ "Y-E DATA External FDD" },
+ },
+ {
+ PCMCIA_VENDOR_UNKNOWN, PCMCIA_PRODUCT_DIGITAL_DEPCMXX,
+ PCMCIA_CIS_DIGITAL_DEPCMXX,
+ 0,
+ "Digital Equipment Corporation",
+ "DEC DEPCM-BA" },
+ },
+ {
+ PCMCIA_VENDOR_NEWMEDIA, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "NewMedia Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_IBM, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "IBM Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_3COM, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "3Com Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_MEGAHERTZ, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Megahertz Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_SOCKET, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Socket Communications",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_TDK, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "TDK Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_SMC, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Standard Microsystems Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_MOTOROLA, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Motorola Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_USROBOTICS, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "US Robotics Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_MEGAHERTZ2, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Megahertz Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_ADAPTEC, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Adaptec Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_LINKSYS, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Linksys Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_SIMPLETECH, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Simple Technology",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_DAYNA, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Dayna Corporation",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_IODATA, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "I-O DATA",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_PREMAX, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Premax",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_PLANET, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Planet",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_DLINK, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "D-Link",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_RPTI, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "RPTI",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_ACCTON, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "ACCTON",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_YEDATA, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Y-E DATA",
+ NULL,
+ },
+ {
+ PCMCIA_VENDOR_DIGITAL, 0,
+ PCMCIA_KNOWNDEV_NOPROD,
+ PCMCIA_CIS_INVALID,
+ "Digital Equipment Corporation",
+ NULL,
+ },
+ { 0, 0, { NULL, NULL, NULL, NULL }, 0, NULL, NULL, }
+};
diff --git a/sys/dev/pcmcia/pcmciareg.h b/sys/dev/pcmcia/pcmciareg.h
index 840d745aba3..caa30615ac2 100644
--- a/sys/dev/pcmcia/pcmciareg.h
+++ b/sys/dev/pcmcia/pcmciareg.h
@@ -1,136 +1,247 @@
-/* $OpenBSD: pcmciareg.h,v 1.2 1997/11/07 08:07:35 niklas Exp $ */
+/* $OpenBSD: pcmciareg.h,v 1.3 1998/09/11 10:47:15 fgsch Exp $ */
+/* $NetBSD: pcmciareg.h,v 1.6 1998/08/13 15:00:02 nathanw Exp $ */
+
/*
- * This file was apparently first written by Stefan Grefen, although it
- * contained no copyright notice at the time.
+ * 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.
*/
-#ifndef __PCMCIAREG_H__
-#define __PCMCIAREG_H__
+
+/* most of this is from the PCMCIA PC Card Standard, Release 2.1 */
+
+/* Note: the weird indenting here is to make the constants more
+ readable. Please don't normalize it. --marc */
/*
- * Configuration Registers
- *
- * These are the registers required by Release 2.0 of the standard
- * (Section 4.15)
+ * CIS Tuples */
+
+/* Layer 1 Basic Compatibility Tuples */
+#define PCMCIA_CISTPL_NULL 0x00
+#define PCMCIA_CISTPL_DEVICE 0x01
+#define PCMCIA_DTYPE_MASK 0xF0
+#define PCMCIA_DTYPE_NULL 0x00
+#define PCMCIA_DTYPE_ROM 0x10
+#define PCMCIA_DTYPE_OTPROM 0x20
+#define PCMCIA_DTYPE_EPROM 0x30
+#define PCMCIA_DTYPE_EEPROM 0x40
+#define PCMCIA_DTYPE_FLASH 0x50
+#define PCMCIA_DTYPE_SRAM 0x60
+#define PCMCIA_DTYPE_DRAM 0x70
+#define PCMCIA_DTYPE_FUNCSPEC 0xD0
+#define PCMCIA_DTYPE_EXTEND 0xE0
+#define PCMCIA_DSPEED_MASK 0x07
+#define PCMCIA_DSPEED_NULL 0x00
+#define PCMCIA_DSPEED_250NS 0x01
+#define PCMCIA_DSPEED_200NS 0x02
+#define PCMCIA_DSPEED_150NS 0x03
+#define PCMCIA_DSPEED_100NS 0x04
+#define PCMCIA_DSPEED_EXT 0x07
+
+/*
+ * the 2.1 docs have 0x02-0x07 as reserved, but the linux drivers list the
+ * follwing tuple code values. I have at least one card (3com 3c562
+ * lan+modem) which has a code 0x06 tuple, so I'm going to assume that these
+ * are for real
*/
-/* Offsets for register ordering */
-#define PCMCIA_COR 0x00 /* Configuration and Option Register */
-#define PCMCIA_CCSR 0x02 /* Card Configuration and Status Register */
-#define PCMCIA_PIR 0x04 /* Pin Replacement Register */
-#define PCMCIA_SCR 0x06 /* Socket and Copy Register */
-
-/* Now register bits, ordered by reg # */
-
-/* For Configuration and Option Register (PCMCIA_COR) */
-#define PCMCIA_MEMIO 0x01 /* Use I/O Space */
-#define PCMCIA_CNFG 0x0e /* I/O decoding configuration */
-#define PCMCIA_CNFGMASK 0x3f /* Use template */
-#define PCMCIA_LVLREQ 0x40 /* Generate level mode interrupts */
-#define PCMCIA_SRESET 0x80 /* Reset Card */
-
-/* For Card Configuration and Status Register (PCMCIA_CCSR) */
-#define PCMCIA_INTR 0x02 /* Interrupt Pending */
-#define PCMCIA_POWER_DOWN 0x04
-#define PCMCIA_AUDIO_ENA 0x08
-#define PCMCIA_IOIS8 0x20
-#define PCMCIA_SIGCHG_ENA 0x40
-#define PCMCIA_CHANGED 0x80
-
-/* Pin Replacement Register (PCMCIA_PIR) */
-#define PCMCIA_WP_STATUS 0x01
-#define PCMCIA_READY_STATUS 0x02
-#define PCMCIA_BVD2_STATUS 0x04
-#define PCMCIA_BVD1_STATUS 0x08
-#define PCMCIA_WP_EVENT 0x10
-#define PCMCIA_READY_EVENT 0x20
-#define PCMCIA_BVD2_EVENT 0x40
-#define PCMCIA_BVD1_EVENT 0x80
-
-
-/* For Socket and Copy Register (PCMCIA_SCR) */
-#define PCMCIA_SOCKNUM 0x0f /* Which socket I'm sitting in */
-#define PCMCIA_COPNUM 0x70 /* Which instance I am. */
+#define PCMCIA_CISTPL_LONGLINK_CB 0x02
+#define PCMCIA_CISTPL_INDIRECT 0x03
+#define PCMCIA_CISTPL_CONFIG_CB 0x04
+#define PCMCIA_CISTPL_CFTABLE_ENTRY_CB 0x05
+#define PCMCIA_CISTPL_LONGLINK_MFC 0x06
+#define PCMCIA_MFC_MEM_ATTR 0x00
+#define PCMCIA_MFC_MEM_COMMON 0x01
+#define PCMCIA_CISTPL_BAR 0x07
+#define PCMCIA_CISTPL_PWR_MGMNT 0x08
+
+#define PCMCIA_CISTPL_CHECKSUM 0x10
+#define PCMCIA_CISTPL_LONGLINK_A 0x11
+#define PCMCIA_CISTPL_LONGLINK_C 0x12
+#define PCMCIA_CISTPL_LINKTARGET 0x13
+#define PCMCIA_CISTPL_NO_LINK 0x14
+#define PCMCIA_CISTPL_VERS_1 0x15
+#define PCMCIA_CISTPL_ALTSTR 0x16
+#define PCMCIA_CISTPL_DEVICE_A 0x17
+#define PCMCIA_CISTPL_JEDEC_C 0x18
+#define PCMCIA_CISTPL_JEDEC_A 0x19
+#define PCMCIA_CISTPL_CONFIG 0x1A
+#define PCMCIA_TPCC_RASZ_MASK 0x03
+#define PCMCIA_TPCC_RASZ_SHIFT 0
+#define PCMCIA_TPCC_RMSZ_MASK 0x3C
+#define PCMCIA_TPCC_RMSZ_SHIFT 2
+#define PCMCIA_TPCC_RFSZ_MASK 0xC0
+#define PCMCIA_TPCC_RFSZ_SHIFT 6
+#define PCMCIA_CISTPL_CFTABLE_ENTRY 0x1B
+#define PCMCIA_TPCE_INDX_INTFACE 0x80
+#define PCMCIA_TPCE_INDX_DEFAULT 0x40
+#define PCMCIA_TPCE_INDX_NUM_MASK 0x3F
+#define PCMCIA_TPCE_IF_MWAIT 0x80
+#define PCMCIA_TPCE_IF_RDYBSY 0x40
+#define PCMCIA_TPCE_IF_WP 0x20
+#define PCMCIA_TPCE_IF_BVD 0x10
+#define PCMCIA_TPCE_IF_IFTYPE 0x0F
+#define PCMCIA_IFTYPE_MEMORY 0
+#define PCMCIA_IFTYPE_IO 1
+#define PCMCIA_TPCE_FS_MISC 0x80
+#define PCMCIA_TPCE_FS_MEMSPACE_MASK 0x60
+#define PCMCIA_TPCE_FS_MEMSPACE_NONE 0x00
+#define PCMCIA_TPCE_FS_MEMSPACE_LENGTH 0x20
+#define PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR 0x40
+#define PCMCIA_TPCE_FS_MEMSPACE_TABLE 0x60
+#define PCMCIA_TPCE_FS_IRQ 0x10
+#define PCMCIA_TPCE_FS_IOSPACE 0x08
+#define PCMCIA_TPCE_FS_TIMING 0x04
+#define PCMCIA_TPCE_FS_POWER_MASK 0x03
+#define PCMCIA_TPCE_FS_POWER_NONE 0x00
+#define PCMCIA_TPCE_FS_POWER_VCC 0x01
+#define PCMCIA_TPCE_FS_POWER_VCCVPP1 0x02
+#define PCMCIA_TPCE_FS_POWER_VCCVPP1VPP2 0x03
+#define PCMCIA_TPCE_TD_RESERVED_MASK 0xE0
+#define PCMCIA_TPCE_TD_RDYBSY_MASK 0x1C
+#define PCMCIA_TPCE_TD_WAIT_MASK 0x03
+#define PCMCIA_TPCE_IO_HASRANGE 0x80
+#define PCMCIA_TPCE_IO_BUSWIDTH_16BIT 0x40
+#define PCMCIA_TPCE_IO_BUSWIDTH_8BIT 0x20
+#define PCMCIA_TPCE_IO_IOADDRLINES_MASK 0x1F
+#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK 0xC0
+#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_NONE 0x00
+#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE 0x40
+#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO 0x80
+#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR 0xC0
+#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK 0x30
+#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_NONE 0x00
+#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE 0x10
+#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO 0x20
+#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR 0x30
+#define PCMCIA_TPCE_IO_RANGE_COUNT 0x0F
+#define PCMCIA_TPCE_IR_SHARE 0x80
+#define PCMCIA_TPCE_IR_PULSE 0x40
+#define PCMCIA_TPCE_IR_LEVEL 0x20
+#define PCMCIA_TPCE_IR_HASMASK 0x10
+#define PCMCIA_TPCE_IR_IRQ 0x0F
+#define PCMCIA_TPCE_MS_HOSTADDR 0x80
+#define PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK 0x60
+#define PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT 5
+#define PCMCIA_TPCE_MS_LENGTH_SIZE_MASK 0x18
+#define PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT 3
+#define PCMCIA_TPCE_MS_COUNT 0x07
+#define PCMCIA_TPCE_MI_EXT 0x80
+#define PCMCIA_TPCE_MI_RESERVED 0x40
+#define PCMCIA_TPCE_MI_PWRDOWN 0x20
+#define PCMCIA_TPCE_MI_READONLY 0x10
+#define PCMCIA_TPCE_MI_AUDIO 0x08
+#define PCMCIA_TPCE_MI_MAXTWINS 0x07
+#define PCMCIA_CISTPL_DEVICE_OC 0x1C
+#define PCMCIA_CISTPL_DEVICE_OA 0x1D
+#define PCMCIA_CISTPL_DEVICE_GEO 0x1E
+#define PCMCIA_CISTPL_DEVICE_GEO_A 0x1F
+#define PCMCIA_CISTPL_MANFID 0x20
+#define PCMCIA_CISTPL_FUNCID 0x21
+#define PCMCIA_FUNCTION_UNSPEC -1
+#define PCMCIA_FUNCTION_MULTIFUNCTION 0
+#define PCMCIA_FUNCTION_MEMORY 1
+#define PCMCIA_FUNCTION_SERIAL 2
+#define PCMCIA_FUNCTION_PARALLEL 3
+#define PCMCIA_FUNCTION_DISK 4
+#define PCMCIA_FUNCTION_VIDEO 5
+#define PCMCIA_FUNCTION_NETWORK 6
+#define PCMCIA_FUNCTION_AIMS 7
+#define PCMCIA_FUNCTION_SCSI 8
+#define PCMCIA_FUNCTION_SECURITY 9
+#define PCMCIA_FUNCTION_INSTRUMENT 10
+#define PCMCIA_CISTPL_FUNCE 0x22
+#define PCMCIA_TPLFE_TYPE_LAN_TECH 0x01
+#define PCMCIA_TPLFE_TYPE_LAN_SPEED 0x02
+#define PCMCIA_TPLFE_TYPE_LAN_MEDIA 0x03
+#define PCMCIA_TPLFE_TYPE_LAN_NID 0x04
+#define PCMCIA_TPLFE_TYPE_LAN_CONN 0x05
+#define PCMCIA_CISTPL_END 0xFF
+
+/* Layer 2 Data Recording Format Tuples */
+
+#define PCMCIA_CISTPL_SWIL 0x23
+/* #define PCMCIA_CISTPL_RESERVED 0x24-0x3F */
+#define PCMCIA_CISTPL_VERS_2 0x40
+#define PCMCIA_CISTPL_FORMAT 0x41
+#define PCMCIA_CISTPL_GEOMETRY 0x42
+#define PCMCIA_CISTPL_BYTEORDER 0x43
+#define PCMCIA_CISTPL_DATE 0x44
+#define PCMCIA_CISTPL_BATTERY 0x45
+#define PCMCIA_CISTPL_FORAMT_A 0x47
+
+/* Layer 3 Data Organization Tuples */
+
+#define PCMCIA_CISTPL_ORG 0x46
+/* #define PCMCIA_CISTPL_RESERVED 0x47-0x7F */
+
+/* Layer 4 System-Specific Standard Tuples */
+
+/* #define PCMCIA_CISTPL_RESERVED 0x80-0x8F */
+#define PCMCIA_CISTPL_SPCL 0x90
+/* #define PCMCIA_CISTPL_RESERVED 0x90-0xFE */
/*
- * CIS Tuple defines
+ * Card Configuration Registers
*/
-#define CIS_MAXSIZE 512
-
-/* Define tuple types */
-#define CIS_NULL 0x00 /* null tuple */
-#define CIS_DEVICE 0x01 /* Device descriptor, common mem */
-#define CIS_DEVICE_A 0x17 /* Device descriptor, attribute mem */
-#define CIS_DEVICE_TYPE 0xf0 /* type mask */
-#define CIS_DEVICE_TYPE_SHIFT 4 /* type offset */
-#define CIS_DEVICE_WPS 0x08 /* WPS mask */
-#define CIS_DEVICE_SPEED 0x07 /* speed mask */
-#define CIS_DEVICE_ADDRS 0xf8 /* # addr units */
-#define CIS_DEVICE_ADDRS_SHIFT 3 /* # addr units offset */
-#define CIS_DEVICE_SIZE 0x07
-#define CIS_CSUM 0x10 /* Checksum field */
-#define CIS_NOLINK 0x14 /* No Link */
-#define CIS_VER1 0x15 /* Level 1 Version/Product info */
-#define CIS_CFG_INFO 0x1a /* Configuration info map */
-#define TPCC_RASZ 0x03 /* size of regaddr */
-#define TPCC_RASZ_SHIFT 0
-#define TPCC_RMSZ 0x3c /* size of regmask */
-#define TPCC_RMSZ_SHIFT 2
-#define TPCC_LAST 0x3f /* last con entry idx */
-#define TPCC_LAST_SHIFT 0
-#define CIS_CFG_ENT 0x1b /* Configuration info entry */
-#define TPCE_INDX_ENTRY 0x3f /* config entry # */
-#define TPCE_INDX_DEF 0x40 /* default bit */
-#define TPCE_INDX_INT 0x80 /* interface bit */
-#define TPCE_IF_TYPE 0x0f /* interface type */
-#define TPCE_IF_BVD 0x10 /* BVD active bit */
-#define TPCE_IF_WP 0x20 /* WP active bit */
-#define TPCE_IF_RDYBSY 0x40 /* RdyBsy active bit */
-#define TPCE_IF_MWAIT 0x80 /* Wait Sig req. bit */
-#define TPCE_FS_PWR 0x03 /* Power */
-#define TPCE_FS_PWR_VCC 0x01 /* Vcc struct */
-#define TPCE_FS_PWR_VPP 0x02 /* Vpp struct */
-#define TPCE_FS_TD 0x04 /* Timing */
-#define TPCE_FS_TD_WAIT 0x03 /* wait scale */
-#define TPCE_FS_TD_RDY 0x1c /* rdy/bsy scale */
-#define TPCE_FS_TD_RDY_SHIFT 2
-#define TPCE_FS_TD_RSV 0xe0 /* reserved scale */
-#define TPCE_FS_TD_RSV_SHIFT 5
-#define TPCE_FS_IO 0x08 /* I/O Space */
-#define TPCE_FS_IO_LINES 0x1f /* IO addr lines */
-#define TPCE_FS_IO_BUS8 0x20 /* bus 8 bit */
-#define TPCE_FS_IO_BUS16 0x40 /* bus 16 bit */
-#define TPCE_FS_IO_RANGE 0x80 /* range bit */
-#define TPCE_FS_IO_LEN 0xc0 /* block len size */
-#define TPCE_FS_IO_LEN_SHIFT 6
-#define TPCE_FS_IO_SIZE 0x30 /* block size size */
-#define TPCE_FS_IO_SIZE_SHIFT 4
-#define TPCE_FS_IO_NUM 0x0f /* # of blocks */
-#define TPCE_FS_IRQ 0x10 /* IRQ */
-#define TPCE_FS_IRQ_SHARE 0x80 /* int sharing */
-#define TPCE_FS_IRQ_PULSE 0x40 /* pulse request */
-#define TPCE_FS_IRQ_LEVEL 0x20 /* level-trig int */
-#define TPCE_FS_IRQ_MASK 0x10 /* irq mask bit */
-#define TPCE_FS_IRQ_IRQN 0x0f /* irqn mask */
-#define TPCE_FS_IRQ_VEND 0x08 /* vendor sig */
-#define TPCE_FS_IRQ_BERR 0x04 /* bus error */
-#define TPCE_FS_IRQ_IOCK 0x02 /* io check */
-#define TPCE_FS_IRQ_NMI 0x01 /* nmi */
-#define TPCE_FS_MEM 0x60 /* Mem Space */
-#define TPCE_FS_MEM_SHIFT 5
-#define TPCE_FS_MEM_HOST 0x80
-#define TPCE_FS_MEM_ADDR 0x60
-#define TPCE_FS_MEM_ADDR_SHIFT 5
-#define TPCE_FS_MEM_LEN 0x18
-#define TPCE_FS_MEM_LEN_SHIFT 3
-#define TPCE_FS_MEM_WINS 0x07
-#define TPCE_FS_MISC 0x80 /* Misc */
-#define CIS_MFG 0x20 /* Manufacturer's ID */
-#define CIS_FUNC 0x21 /* Function ID */
-#define CIS_FUNE 0x22 /* Function Extension */
-#define CIS_DRIVER 0x77 /* Driver ID */
-#define CIS_END 0xff /* Last Entry */
-
-#define splpcmcia spltty
-#define IPL_PCMCIA IPL_TTY
-
-#endif /* __PCMCIAREG_H__ */
+
+#define PCMCIA_CCR_OPTION 0x00
+#define PCMCIA_CCR_OPTION_SRESET 0x80
+#define PCMCIA_CCR_OPTION_LEVIREQ 0x40
+#define PCMCIA_CCR_OPTION_CFINDEX 0x3F
+#define PCMCIA_CCR_OPTION_IREQ_ENABLE 0x04
+#define PCMCIA_CCR_OPTION_ADDR_DECODE 0x02
+#define PCMCIA_CCR_OPTION_FUNC_ENABLE 0x01
+#define PCMCIA_CCR_STATUS 0x02
+#define PCMCIA_CCR_STATUS_PINCHANGED 0x80
+#define PCMCIA_CCR_STATUS_SIGCHG 0x40
+#define PCMCIA_CCR_STATUS_IOIS8 0x20
+#define PCMCIA_CCR_STATUS_RESERVED1 0x10
+#define PCMCIA_CCR_STATUS_AUDIO 0x08
+#define PCMCIA_CCR_STATUS_PWRDWN 0x04
+#define PCMCIA_CCR_STATUS_INTR 0x02
+#define PCMCIA_CCR_STATUS_INTRACK 0x01
+#define PCMCIA_CCR_PIN 0x04
+#define PCMCIA_CCR_PIN_CBVD1 0x80
+#define PCMCIA_CCR_PIN_CBVD2 0x40
+#define PCMCIA_CCR_PIN_CRDYBSY 0x20
+#define PCMCIA_CCR_PIN_CWPROT 0x10
+#define PCMCIA_CCR_PIN_RBVD1 0x08
+#define PCMCIA_CCR_PIN_RBVD2 0x04
+#define PCMCIA_CCR_PIN_RRDYBSY 0x02
+#define PCMCIA_CCR_PIN_RWPROT 0x01
+#define PCMCIA_CCR_SOCKETCOPY 0x06
+#define PCMCIA_CCR_SOCKETCOPY_RESERVED 0x80
+#define PCMCIA_CCR_SOCKETCOPY_COPY_MASK 0x70
+#define PCMCIA_CCR_SOCKETCOPY_COPY_SHIFT 4
+#define PCMCIA_CCR_SOCKETCOPY_SOCKET_MASK 0x0F
+#define PCMCIA_CCR_EXTSTATUS 0x08
+#define PCMCIA_CCR_IOBASE0 0x0A
+#define PCMCIA_CCR_IOBASE1 0x0C
+#define PCMCIA_CCR_IOBASE2 0x0E
+#define PCMCIA_CCR_IOBASE3 0x10
+#define PCMCIA_CCR_IOSIZE 0x12
+
+#define PCMCIA_CCR_SIZE 0x14
diff --git a/sys/dev/pcmcia/pcmciavar.h b/sys/dev/pcmcia/pcmciavar.h
index 58872f0722c..203fb3ab0b5 100644
--- a/sys/dev/pcmcia/pcmciavar.h
+++ b/sys/dev/pcmcia/pcmciavar.h
@@ -1,19 +1,20 @@
-/* $OpenBSD: pcmciavar.h,v 1.5 1997/11/07 08:07:36 niklas Exp $ */
+/* $OpenBSD: pcmciavar.h,v 1.6 1998/09/11 10:47:15 fgsch Exp $ */
+/* $NetBSD: pcmciavar.h,v 1.5 1998/07/19 17:28:17 christos Exp $ */
+
/*
- * Copyright (c) 1995,1996 John T. Kohl. All rights reserved.
- * Copyright (c) 1993, 1994 Stefan Grefen. All rights reserved.
+ * 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 dipclaimer.
+ * 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 Charles Hannum.
+ * 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.
*
@@ -27,304 +28,236 @@
* 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.
- *
*/
- /* derived from scsicconf.[ch] writenn by Julian Elischer et al */
-
-#ifndef _PCMCIA_PCMCIAVAR_H_
-#define _PCMCIA_PCMCIAVAR_H_ 1
+#include <sys/types.h>
#include <sys/queue.h>
-#include <sys/select.h>
-#include <machine/cpu.h>
-#include <machine/bus.h>
-
-/*
- * The following documentation tries to describe the relationship between the
- * various structures defined in this file:
- *
- * each adapter type has a pcmcia_adapter struct. This describes the adapter and
- * identifies routines that can be called to use the adapter.
- * each device type has a pcmcia_device struct. This describes the device and
- * identifies routines that can be called to use the device.
- * each existing device position (pcmciabus + port)
- * can be described by a pcmcia_link struct.
- * Only port positions that actually have devices, have a pcmcia_link
- * structure assigned. so in effect each device has pcmcia_link struct.
- * The pcmcia_link structure contains information identifying both the
- * device driver and the adapter driver for that port on that pcmcia bus,
- * and can be said to 'link' the two.
- * each individual pcmcia bus has an array that points to all the pcmcia_link
- * structs associated with that pcmcia bus. Slots with no device have
- * a NULL pointer.
- * each individual device also knows the address of it's own pcmcia_link
- * structure.
- *
- * -------------
- *
- * The key to all this is the pcmcia_link structure which associates all the
- * other structures with each other in the correct configuration. The
- * pcmcia_link is the connecting information that allows each part of the
- * pcmcia system to find the associated other parts.
- */
+#include <machine/bus.h>
-struct pcmcia_link;
-struct pcmcia_conf;
-struct pcmcia_adapter;
+#include <dev/pcmcia/pcmciachip.h>
/*
- * These entrypoints are called by the high-end drivers to get services from
- * whatever low-end drivers they are attached to each adapter type has one of
- * these statically allocated.
+ * Contains information about mapped/allocated i/o spaces.
*/
-struct pcmcia_funcs {
-/* 4 map io range */
- int (*pcmcia_map_io) __P((struct pcmcia_link *, u_int, u_int, int));
-/* 8 map memory window */
- int (*pcmcia_map_mem) __P((struct pcmcia_link *, bus_space_tag_t,
- caddr_t, u_int, u_int, int));
-/*12 map interrupt */
- int (*pcmcia_map_intr) __P((struct pcmcia_link *, int, int));
-/*16 power on/off etc */
- int (*pcmcia_service) __P((struct pcmcia_link *, int, void *, int));
-};
-
-struct pcmciabus_link { /* Link back to the bus we are on */
- /* Bus specific configure */
- int (*bus_config) __P((struct pcmcia_link *, struct device *,
- struct pcmcia_conf *, struct cfdata *));
- /* Bus specific unconfigure */
- int (*bus_unconfig) __P((struct pcmcia_link *));
- /* Bus specific probe */
- int (*bus_probe) __P((struct device *, void *,
- void *, struct pcmcia_link *));
- /* Bus specific search */
- int (*bus_search) __P((struct device *, void *, cfprint_t));
- /* initialize scratch */
- int (*bus_init) __P((struct device *, struct cfdata *,
- void *, struct pcmcia_adapter *, int));
+struct pcmcia_io_handle {
+ bus_space_tag_t iot; /* bus space tag (from chipset) */
+ bus_space_handle_t ioh; /* mapped space handle */
+ bus_addr_t addr; /* resulting address in bus space */
+ bus_size_t size; /* size of i/o space */
+ int flags; /* misc. information */
};
-#define PCMCIA_BUS_INIT(a,b,c,d,e,f) \
- ((*(a)->bus_link->bus_init)((b),(c),(d),(e),(f)))
-#define PCMCIA_BUS_SEARCH(a,b,c,d) \
- ((*(a)->bus_link->bus_search)((b),(c),(d)))
-#define PCMCIA_BUS_PROBE(a,b,c,d,e) \
- ((*(a)->bus_link->bus_probe)((b),(c),(d),(e)))
-#define PCMCIA_BUS_CONFIG(a,b,c,d,e) \
- ((*(a)->bus_link->bus_config)((b),(c),(d),(e)))
-#define PCMCIA_BUS_UNCONFIG(a,b) \
- ((*(a)->bus_link->bus_unconfig)((b)))
+#define PCMCIA_IO_ALLOCATED 0x01 /* i/o space was allocated */
/*
- * One of these goes at the front of each chip controller's softc, right
- * after the struct device.
+ * Contains information about allocated memory space.
*/
-struct pcmcia_adapter {
- struct pcmcia_funcs *chip_link;
- struct pcmciabus_link *bus_link;
- bus_space_tag_t pa_memt; /* mem access handle */
- void *adapter_softc;
- caddr_t scratch_mem; /* pointer to scratch window */
- int scratch_memsiz; /* size of scratch window */
- bus_space_handle_t scratch_memh;/* bus memory handle */
- int scratch_inuse; /* window in use */
- int nslots; /* # of slots controlled */
+struct pcmcia_mem_handle {
+ bus_space_tag_t memt; /* bus space tag (from chipset) */
+ bus_space_handle_t memh; /* mapped space handle */
+ bus_addr_t addr; /* resulting address in bus space */
+ bus_size_t size; /* size of mem space */
+ pcmcia_mem_handle_t mhandle; /* opaque memory handle */
+ bus_size_t realsize; /* how much we really allocated */
};
-#define PCMCIA_MAP_ATTR 0x0100 /* for memory only */
-#define PCMCIA_MAP_8 0x0100 /* for io only */
-#define PCMCIA_MAP_16 0x0200
-#define PCMCIA_UNMAP 0x0400
-#define PCMCIA_PHYSICAL_ADDR 0x0800
-#define PCMCIA_UNMAP_ALL 0x0c00
-#define PCMCIA_FIXED_WIN 0x1000
-#define PCMCIA_LAST_WIN 0x0010
-#define PCMCIA_FIRST_WIN 0x0020
-#define PCMCIA_ANY_WIN 0x0030
-
-#define PCMCIA_OP_RESET 0x0000
-#define PCMCIA_OP_POWER 0x0001
-#define PCMCIA_OP_STATUS 0x0002
-#define PCMCIA_OP_GETREGS 0x0003
-#define PCMCIA_OP_WAIT 0x0004
-
-#define PCMCIA_POWER_ON 0x0001
-#define PCMCIA_POWER_5V 0x0002
-#define PCMCIA_POWER_3V 0x0004
-#define PCMCIA_POWER_AUTO 0x0008
-
-#define PCMCIA_CARD_PRESENT 0x0001
-#define PCMCIA_BATTERY 0x0002
-#define PCMCIA_WRITE_PROT 0x0004
-#define PCMCIA_READY 0x0008
-#define PCMCIA_POWER 0x0010
-#define PCMCIA_POWER_PP 0x0020
-#define PCMCIA_CARD_IS_MAPPED 0x1000
-#define PCMCIA_CARD_INUSE 0x2000
+/* pcmcia itself */
+#define PCMCIA_CFE_MWAIT_REQUIRED 0x0001
+#define PCMCIA_CFE_RDYBSY_ACTIVE 0x0002
+#define PCMCIA_CFE_WP_ACTIVE 0x0004
+#define PCMCIA_CFE_BVD_ACTIVE 0x0008
+#define PCMCIA_CFE_IO8 0x0010
+#define PCMCIA_CFE_IO16 0x0020
+#define PCMCIA_CFE_IRQSHARE 0x0040
+#define PCMCIA_CFE_IRQPULSE 0x0080
+#define PCMCIA_CFE_IRQLEVEL 0x0100
+#define PCMCIA_CFE_POWERDOWN 0x0200
+#define PCMCIA_CFE_READONLY 0x0400
+#define PCMCIA_CFE_AUDIO 0x0800
-/*
- * This structure describes the connection between an adapter driver and
- * a device driver, and is used by each to call services provided by
- * the other, and to allow generic pcmcia glue code to call these services
- * as well.
- */
-struct pcmcia_link {
- u_char pcmciabus; /* the Nth pcmciabus */
- u_char slot; /* slot of this dev */
- u_char flags;
-#define CARD_IS_MAPPED 0x01
-#define PCMCIA_ATTACH 0x02
-#define PCMCIA_REATTACH 0x04
-#define PCMCIA_SLOT_INUSE 0x08
-#define PCMCIA_ATTACH_TYPE (PCMCIA_ATTACH|PCMCIA_REATTACH)
-#define PCMCIA_SLOT_EVENT 0x80
-#define PCMCIA_SLOT_OPEN 0x40
- u_char opennings;
-
- u_char iowin;
- u_char memwin;
- u_char intr;
- u_char dummy;
- struct pcmcia_adapter *adapter; /* adapter entry points etc. */
- struct pcmciadevs *device; /* device entry points etc. */
- struct pcmciabus_softc *bus; /* parent pcmcia bus */
- struct device *devp; /* pointer to configured device */
- void *fordriver; /* for private use by the driver */
- struct selinfo pcmcialink_sel; /* for select users */
-};
+struct pcmcia_config_entry {
+ int number;
+ u_int32_t flags;
+ int iftype;
+ int num_iospace;
-/*
- * One of these is allocated and filled in for each pcmcia bus.
- * it holds pointers to allow the pcmcia bus to get to the driver
- * it also has a template entry which is the prototype struct
- * supplied by the adapter driver, this is used to initialise
- * the others, before they have the rest of the fields filled in
- */
-struct pcmciabus_softc {
- struct device sc_dev;
- bus_space_tag_t sc_iot;
- bus_space_tag_t sc_memt;
- struct pcmcia_link *sc_link[4]; /* up to 4 slots per bus */
- struct pcmcia_adapter *sc_driver;
+ /*
+ * The card will only decode this mask in any case, so we can
+ * do dynamic allocation with this in mind, in case the suggestions
+ * below are no good.
+ */
+ u_long iomask;
+ struct {
+ u_long length;
+ u_long start;
+ } iospace[4]; /* XXX this could be as high as 16 */
+ u_int16_t irqmask;
+ int num_memspace;
+ struct {
+ u_long length;
+ u_long cardaddr;
+ u_long hostaddr;
+ } memspace[2]; /* XXX this could be as high as 8 */
+ int maxtwins;
+ SIMPLEQ_ENTRY(pcmcia_config_entry) cfe_list;
};
-struct pcmcia_conf {
- int irq_share:1;
- int irq_level:1; /* 1 level */
- int irq_pulse:1; /* 1 pulse */
- int irq_vend:1;
- int irq_iock:1;
- int irq_berr:1;
- int irq_nmi:1;
- int iocard:1;
- u_char iowin;
- u_char memwin;
- u_char irq_num;
- u_char cfgtype;
-#define CFGENTRYID 0x20
-#define CFGENTRYMASK (CFGENTRYID|(CFGENTRYID-1))
-#define DOSRESET 0x40
- int cfg_regmask;
- int irq_mask;
- int cfg_off;
- struct iowin {
- int start;
- int len;
- int flags;
- }io[4];
- struct memwin {
- int start;
- int caddr;
- int len;
- int flags;
- }mem[4];
- char driver_name[8][4]; /* up to four different functions on a card */
- int unitid;
- int cfgid;
+struct pcmcia_function {
+ /* read off the card */
+ int number;
+ int function;
+ int last_config_index;
+ u_long ccr_base;
+ u_long ccr_mask;
+ SIMPLEQ_HEAD(, pcmcia_config_entry) cfe_head;
+ SIMPLEQ_ENTRY(pcmcia_function) pf_list;
+ /* run-time state */
+ struct pcmcia_softc *sc;
+ struct pcmcia_config_entry *cfe;
+ struct pcmcia_mem_handle pf_pcmh;
+#define pf_ccrt pf_pcmh.memt
+#define pf_ccrh pf_pcmh.memh
+#define pf_ccr_mhandle pf_pcmh.mhandle
+#define pf_ccr_realsize pf_pcmh.realsize
+ bus_addr_t pf_ccr_offset;
+ int pf_ccr_window;
+ long pf_mfc_iobase;
+ long pf_mfc_iomax;
+ int (*ih_fct) __P((void *));
+ void *ih_arg;
+ int ih_ipl;
+ int pf_flags;
};
-struct pcmcia_device {
- char *name;
- int (*pcmcia_config) __P((struct pcmcia_link *, struct device *,
- struct pcmcia_conf *, struct cfdata *));
- int (*pcmcia_probe) __P((struct device *, void *,
- void *, struct pcmcia_link *));
- int (*pcmcia_insert) __P((struct pcmcia_link *, struct device *,
- struct cfdata *));
- int (*pcmcia_remove) __P((struct pcmcia_link *, struct device *));
+/* pf_flags */
+#define PFF_ENABLED 0x0001 /* function is enabled */
+
+struct pcmcia_card {
+ int cis1_major;
+ int cis1_minor;
+ /* XXX waste of space? */
+ char cis1_info_buf[256];
+ char *cis1_info[4];
+ /*
+ * Use int32_t for manufacturer and product so that they can
+ * hold the id value found in card CIS and special value that
+ * indicates no id was found.
+ */
+ int32_t manufacturer;
+#define PCMCIA_VENDOR_INVALID -1
+ int32_t product;
+#define PCMCIA_PRODUCT_INVALID -1
+ u_int16_t error;
+#define PCMCIA_CIS_INVALID { NULL, NULL, NULL, NULL }
+ SIMPLEQ_HEAD(, pcmcia_function) pf_head;
};
-#define MAX_CIS_NAMELEN 64 /* version info string len */
+struct pcmcia_softc {
+ struct device dev;
-struct pcmcia_cardinfo {
- char manufacturer[MAX_CIS_NAMELEN];
- char model[MAX_CIS_NAMELEN];
- char add_info1[MAX_CIS_NAMELEN];
- char add_info2[MAX_CIS_NAMELEN];
-};
+ /* this stuff is for the socket */
+ pcmcia_chipset_tag_t pct;
+ pcmcia_chipset_handle_t pch;
-struct pcmciadevs {
- char *devname;
- int flags; /* 1 show my comparisons during boot(debug) */
-#define PC_SHOWME 0x01
- char *manufacturer;
- char *model;
- char *add_inf1;
- char *add_inf2;
- void *param;
- struct pcmcia_device *dev;
+ /* this stuff is for the card */
+ struct pcmcia_card card;
+ void *ih;
+ int sc_enabled_count; /* how many functions are
+ enabled */
+
+ /*
+ * These are passed down from the PCMCIA chip, and exist only
+ * so that cards with Very Special address allocation needs
+ * know what range they should be dealing with.
+ */
+ bus_addr_t iobase; /* start i/o space allocation here */
+ bus_size_t iosize; /* size of the i/o space range */
};
-/*
- * PCMCIA driver attach arguments
- */
struct pcmcia_attach_args {
- struct pcmcia_cardinfo *paa_cardinfo; /* card that we're looking at */
- struct pcmcia_link *paa_link; /* this nexus */
- int paa_bestmatch; /* best match so far */
- int paa_matchonly; /* only do matches, don't attach */
- void *paa_aux; /* driver specific */
+ int32_t manufacturer;
+ int32_t product;
+ struct pcmcia_card *card;
+ struct pcmcia_function *pf;
};
-struct pcmciabus_attach_args {
- bus_space_tag_t pba_iot;
- bus_space_tag_t pba_memt;
- bus_space_tag_t pba_memh;
- int pba_maddr;
- int pba_msize;
- void *pba_aux; /* driver specific */
+struct pcmcia_tuple {
+ unsigned int code;
+ unsigned int length;
+ u_long mult;
+ bus_addr_t ptr;
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
};
-#ifdef _KERNEL
-extern int pcmcia_add_device __P((struct pcmciadevs *));
-extern int pcmcia_get_cf __P((struct pcmcia_link *, u_char *, int, int,
- struct pcmcia_conf *));
-extern int pcmcia_targmatch __P((struct device *, struct cfdata *, void *));
-#endif
-
-/* in pcmcia_conf.c, available for user space too: */
-extern int pcmcia_get_cisver1 __P((struct pcmcia_link *, u_char *, int,
- char *, char *, char *, char *));
-void parse_cfent __P((u_char *, int, int, struct pcmcia_conf *));
-void read_cfg_info __P((u_char *, int, struct pcmcia_conf *));
-void pcmcia_getstr __P((char *buf, u_char **, u_char *));
-extern int pcmcia_configure __P((struct device *, void *, void *));
-extern int pcmcia_register __P((void *, struct pcmciabus_link *,
- struct pcmcia_funcs *, int));
-extern int pcmcia_read_cis __P((struct pcmcia_link *, u_char *, int, int));
-extern int pcmcia_strcmp __P((const char *, const char *, int, const char *));
-extern int pcmcia_matchvalue __P((const struct pcmcia_cardinfo *,
- struct pcmciadevs *));
-extern int pcmcia_bestvalue __P((struct pcmcia_cardinfo *,
- struct pcmciadevs *,
- int,
- struct pcmciadevs **));
-extern int pcmcia_slave_match __P((struct device *,
- void *,
- void *aux,
- struct pcmciadevs *,
- int));
-#endif /* _PCMCIA_PCMCIAVAR_H_ */
+void pcmcia_read_cis __P((struct pcmcia_softc *));
+void pcmcia_print_cis __P((struct pcmcia_softc *));
+int pcmcia_scan_cis __P((struct device * dev,
+ int (*) (struct pcmcia_tuple *, void *), void *));
+
+#define pcmcia_cis_read_1(tuple, idx0) \
+ (bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0)))
+
+#define pcmcia_tuple_read_1(tuple, idx1) \
+ (pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1)))))
+
+#define pcmcia_tuple_read_2(tuple, idx2) \
+ (pcmcia_tuple_read_1((tuple), (idx2)) | \
+ (pcmcia_tuple_read_1((tuple), (idx2)+1)<<8))
+
+#define pcmcia_tuple_read_3(tuple, idx3) \
+ (pcmcia_tuple_read_1((tuple), (idx3)) | \
+ (pcmcia_tuple_read_1((tuple), (idx3)+1)<<8) | \
+ (pcmcia_tuple_read_1((tuple), (idx3)+2)<<16))
+
+#define pcmcia_tuple_read_4(tuple, idx4) \
+ (pcmcia_tuple_read_1((tuple), (idx4)) | \
+ (pcmcia_tuple_read_1((tuple), (idx4)+1)<<8) | \
+ (pcmcia_tuple_read_1((tuple), (idx4)+2)<<16) | \
+ (pcmcia_tuple_read_1((tuple), (idx4)+3)<<24))
+
+#define pcmcia_tuple_read_n(tuple, n, idxn) \
+ (((n)==1)?pcmcia_tuple_read_1((tuple), (idxn)) : \
+ (((n)==2)?pcmcia_tuple_read_2((tuple), (idxn)) : \
+ (((n)==3)?pcmcia_tuple_read_3((tuple), (idxn)) : \
+ /* n == 4 */ pcmcia_tuple_read_4((tuple), (idxn)))))
+
+#define PCMCIA_SPACE_MEMORY 1
+#define PCMCIA_SPACE_IO 2
+
+int pcmcia_ccr_read __P((struct pcmcia_function *, int));
+void pcmcia_ccr_write __P((struct pcmcia_function *, int, int));
+
+#define pcmcia_mfc(sc) ((sc)->card.pf_head.sqh_first && \
+ (sc)->card.pf_head.sqh_first->pf_list.sqe_next)
+
+void pcmcia_function_init __P((struct pcmcia_function *,
+ struct pcmcia_config_entry *));
+int pcmcia_function_enable __P((struct pcmcia_function *));
+void pcmcia_function_disable __P((struct pcmcia_function *));
+
+#define pcmcia_io_alloc(pf, start, size, align, pciop) \
+ (pcmcia_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start), \
+ (size), (align), (pciop)))
+
+int pcmcia_io_map __P((struct pcmcia_function *, int, bus_addr_t,
+ bus_size_t, struct pcmcia_io_handle *, int *));
+
+#define pcmcia_mem_alloc(pf, size, pcmhp) \
+ (pcmcia_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
+
+#define pcmcia_mem_free(pf, pcmhp) \
+ (pcmcia_chip_mem_free((pf)->sc->pct, (pf)->sc->pch, (pcmhp)))
+
+#define pcmcia_mem_map(pf, kind, card_addr, size, pcmhp, offsetp, windowp) \
+ (pcmcia_chip_mem_map((pf)->sc->pct, (pf)->sc->pch, (kind), \
+ (card_addr), (size), (pcmhp), (offsetp), (windowp)))
+
+#define pcmcia_mem_unmap(pf, window) \
+ (pcmcia_chip_mem_unmap((pf)->sc->pct, (pf)->sc->pch, (window)))
+
+void *pcmcia_intr_establish __P((struct pcmcia_function *, int,
+ int (*) (void *), void *));
+void pcmcia_intr_disestablish __P((struct pcmcia_function *, void *));