summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorhvozda <hvozda@cvs.openbsd.org>1996-04-29 14:17:54 +0000
committerhvozda <hvozda@cvs.openbsd.org>1996-04-29 14:17:54 +0000
commit7a9ddc83f934914d39af72bf24b67290a9e5700f (patch)
treed4e40de8eec73b77be31c346455984224213ff31 /sys/dev
parentfdecada6f88b495c1afc81ad3a15c0cedffa2338 (diff)
Pull in John Kohl's [jtk@netbsd.org] most recent (15Apr96) APM and PCMCIA work
(original PCMCIA framework by Stefan Grefen [grefen@convex.com]).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/com.c312
-rw-r--r--sys/dev/ic/i82365reg.h29
-rw-r--r--sys/dev/isa/com.c312
-rw-r--r--sys/dev/isa/files.isa47
-rw-r--r--sys/dev/isa/if_ed.c119
-rw-r--r--sys/dev/isa/if_ep.c123
-rw-r--r--sys/dev/isa/pcmcia_isa.c107
-rw-r--r--sys/dev/isa/pcmcia_pcic.c553
-rw-r--r--sys/dev/isa/wd.c25
-rw-r--r--sys/dev/pcmcia/files.pcmcia17
-rw-r--r--sys/dev/pcmcia/pcmcia.c904
-rw-r--r--sys/dev/pcmcia/pcmcia_conf.c190
-rw-r--r--sys/dev/pcmcia/pcmcia_ioctl.h6
-rw-r--r--sys/dev/pcmcia/pcmciareg.h136
-rw-r--r--sys/dev/pcmcia/pcmciavar.h (renamed from sys/dev/pcmcia/pcmciabus.h)113
15 files changed, 2132 insertions, 861 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index 77dd24748f4..5570f7ef424 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $OpenBSD: com.c,v 1.12 1996/04/29 14:16:15 hvozda Exp $ */
/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
@@ -81,6 +81,7 @@
struct com_softc {
struct device sc_dev;
void *sc_ih;
+ bus_chipset_tag_t sc_bc;
struct tty *sc_tty;
int sc_overflows;
@@ -94,7 +95,6 @@ struct com_softc {
int sc_hayespbase;
#endif
- bus_chipset_tag_t sc_bc;
bus_io_handle_t sc_ioh;
bus_io_handle_t sc_hayespioh;
@@ -102,6 +102,9 @@ struct com_softc {
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
#define COM_HW_HAYESP 0x04
+#define COM_HW_ABSENT_PENDING 0x08 /* reattached, awaiting close/reopen */
+#define COM_HW_ABSENT 0x10 /* configure actually failed, or removed */
+#define COM_HW_REATTACH 0x20 /* reattaching */
#define COM_HW_CONSOLE 0x40
u_char sc_swflags;
#define COM_SW_SOFTCAR 0x01
@@ -125,6 +128,8 @@ int comintr __P((void *));
void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
+void com_absent_notify __P((struct com_softc *sc));
+void comstart_pending __P((void *arg));
/*
* XXX the following two cfattach structs should be different, and possibly
@@ -145,12 +150,17 @@ struct cfattach com_commulti_ca = {
};
#endif
+
struct cfdriver com_cd = {
NULL, "com", DV_TTY
};
int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+#ifndef CONSPEED
+#define CONSPEED B9600
+#endif
+
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
#else
@@ -181,49 +191,201 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-/*#include "pcmciabus.h"*/
-#if NPCMCIABUS >0
+#if NCOM_PCMCIA
+#include <dev/pcmcia/pcmciavar.h>
+
+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 cfattach com_pcmcia_ca = {
+ sizeof(struct com_softc), com_pcmcia_match, comattach,
+ com_pcmcia_detach
+};
+
+int
+com_pcmcia_mod __P((struct pcmcia_link *pc_link,
+ struct device *self,
+ struct pcmcia_conf *pc_cf,
+ struct cfdata *cf));
+
/* additional setup needed for pcmcia devices */
-#include <dev/pcmcia/pcmciabus.h>
/* modify config entry */
-static int
-commod(pc_link,self,pc_cf,cf)
+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;
- struct pcmciadevs *dev=pc_link->device;
+ struct pcmciadevs *dev = pc_link->device;
struct ed_softc *sc = (void *)self;
- if(!(err=pc_link->adapter->bus_link->bus_config(pc_link,self,pc_cf,cf))) {
- pc_cf->memwin=0;
- if(pc_cf->cfgtype==0)
- pc_cf->cfgtype=CFGENTRYID; /* determine from ioaddr */
+ 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 */
}
return err;
}
+
+int com_pcmcia_isa_attach __P((struct device *, void *, void *,
+ struct pcmcia_link *));
+int com_pcmcia_remove __P((struct pcmcia_link *, struct device *));
+
static struct pcmcia_com {
struct pcmcia_device pcd;
-} pcmcia_com= {
- "PCMCIA Modem card",commod,NULL,NULL,NULL
+} pcmcia_com = {
+ {"PCMCIA Modem card", com_pcmcia_mod, com_pcmcia_isa_attach,
+ NULL, com_pcmcia_remove}
};
-struct pcmciadevs pcmcia_com_devs[]={
- { "com", 0,
+
+
+struct pcmciadevs pcmcia_com_devs[] = {
+ { "com", 0,
NULL, "*MODEM*", NULL, NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "com", 0,
NULL, NULL, "*MODEM*", NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "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
+com_pcmcia_isa_attach(parent, match, aux, pc_link)
+ struct device *parent;
+ void *match;
+ void *aux;
+ struct pcmcia_link *pc_link;
+{
+ struct isa_attach_args *ia = aux;
+ struct com_softc *sc = match;
+
+ int rval;
+ if (rval = comprobe(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);
+#endif
+ sc->sc_hwflags = COM_HW_REATTACH |
+ (sc->sc_hwflags & (COM_HW_ABSENT_PENDING|COM_HW_CONSOLE));
+ } else
+ sc->sc_hwflags = 0;
+ }
+ return rval;
+}
+
+
+/*
+ * 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;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ /* don't let it really be detached, it is still open */
+ return EBUSY;
+ }
+ return 0; /* OK! */
+}
+
+/*
+ * 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;
+{
+ 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_bc, sc->sc_ih);
+ sc->sc_ih = NULL;
+ SET(sc->sc_hwflags, COM_HW_ABSENT);
+ return 0; /* OK! */
+ }
+ /*
+ * 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
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+
+ return 0;
+}
+
+#if 0
+void
+com_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ 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");
+ }
+}
#endif
+#endif
+
+/*
+ * must be called at spltty() or higher.
+ */
+void
+com_absent_notify(sc)
+ struct com_softc *sc;
+{
+ struct tty *tp;
+ if (tp = sc->sc_tty) {
+ CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
+ ttyflush(tp, FREAD|FWRITE);
+ }
+}
int
comspeed(speed)
@@ -351,13 +513,21 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+#if NCOM_ISA || NCOM_PCMCIA
+#define IS_ISA(parent) \
+ (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
+#elif NCOM_ISA
+#define IS_ISA(parent) \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
+#endif
/*
* XXX should be broken out into functions for isa probe and
* XXX for commulti probe, with a helper function that contains
* XXX most of the interesting stuff.
*/
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
@@ -393,8 +563,8 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
-#if NCOM_ISA
- if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (rv && IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
@@ -425,10 +595,16 @@ comattach(parent, self, aux)
* XXX for commulti attach, with a helper function that contains
* XXX most of the interesting stuff.
*/
- sc->sc_hwflags = 0;
+ if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
+ int s;
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ } else
+ sc->sc_hwflags = 0;
sc->sc_swflags = 0;
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
/*
@@ -457,7 +633,7 @@ comattach(parent, self, aux)
irq = IRQUNK;
if (ca->ca_noien)
- sc->sc_hwflags |= COM_HW_NOIEN;
+ SET(sc->sc_hwflags, COM_HW_NOIEN);
} else
#endif
panic("comattach: impossible");
@@ -522,8 +698,8 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_mcr, 0);
if (irq != IRQUNK) {
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
@@ -576,7 +752,7 @@ comopen(dev, flag, mode, p)
if (unit >= com_cd.cd_ndevs)
return ENXIO;
sc = com_cd.cd_devs[unit];
- if (!sc)
+ if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
return ENXIO;
if (!sc->sc_tty)
@@ -716,19 +892,30 @@ comclose(dev, flag, mode, p)
(*linesw[tp->t_line].l_close)(tp, flag);
s = spltty();
- CLR(sc->sc_lcr, LCR_SBREAK);
- bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
- bus_io_write_1(bc, ioh, com_ier, 0);
- if (ISSET(tp->t_cflag, HUPCL) &&
- !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
- /* XXX perhaps only clear DTR */
- bus_io_write_1(bc, ioh, com_mcr, 0);
+ if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /* can't do any of this stuff .... */
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ bus_io_write_1(bc, ioh, com_ier, 0);
+ if (ISSET(tp->t_cflag, HUPCL) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+ /* XXX perhaps only clear DTR */
+ bus_io_write_1(bc, ioh, com_mcr, 0);
+ }
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (--comsopen == 0)
untimeout(compoll, NULL);
splx(s);
ttyclose(tp);
+#ifdef COM_DEBUG
+ /* mark it ready for more use if reattached earlier */
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ printf("comclose pending cleared\n");
+ }
+#endif
+ CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
+
#ifdef notyet /* XXXX */
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
ttyfree(tp);
@@ -747,6 +934,13 @@ comread(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -759,6 +953,13 @@ comwrite(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
@@ -800,6 +1001,13 @@ comioctl(dev, cmd, data, flag, p)
bus_io_handle_t ioh = sc->sc_ioh;
int error;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return error;
@@ -914,6 +1122,13 @@ comparam(tp, t)
tcflag_t oldcflag;
int s;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
/* check requested parameters */
if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
return EINVAL;
@@ -1042,6 +1257,18 @@ comparam(tp, t)
}
void
+comstart_pending(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int s;
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+}
+
+void
comstart(tp)
struct tty *tp;
{
@@ -1051,6 +1278,16 @@ comstart(tp)
int s;
s = spltty();
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /*
+ * not quite good enough: if caller is ttywait() it will
+ * go to sleep immediately, so hang out a bit and then
+ * prod caller again.
+ */
+ com_absent_notify(sc);
+ timeout(comstart_pending, sc, 1);
+ goto out;
+ }
if (ISSET(tp->t_state, TS_BUSY))
goto out;
if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
@@ -1236,6 +1473,9 @@ comintr(arg)
} iter[32];
#endif
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+ return 0; /* can't do squat. */
+
#ifdef COM_DEBUG
n = 0;
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
diff --git a/sys/dev/ic/i82365reg.h b/sys/dev/ic/i82365reg.h
index fb05f10c0c2..1f0a8f77858 100644
--- a/sys/dev/ic/i82365reg.h
+++ b/sys/dev/ic/i82365reg.h
@@ -8,7 +8,7 @@
* Support is included for Intel 82365SL PCIC controllers and clones
* thereof.
*
- * $Id: i82365reg.h,v 1.1 1996/01/15 00:08:50 hvozda Exp $
+ * $Id: i82365reg.h,v 1.2 1996/04/29 14:15:58 hvozda Exp $
***********************************************************************/
/*
@@ -30,6 +30,7 @@
*/
#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */
+#define PCIC_NPORTS 2 /* pcic takes 2 ports */
/* First, all the registers */
#define PCIC_ID_REV 0x00 /* Identification and Revision */
@@ -107,6 +108,8 @@
#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */
#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */
#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */
+#define PCIC_146FC6 0x84 /* VL82C146FC6; Both Memory and I/O */
+#define PCIC_146FC7 0x85 /* VL82C146FC7; Both Memory and I/O */
/* For Interface Status register (PCIC_STATUS) */
#define PCIC_VPPV 0x80 /* Vpp_valid */
@@ -128,7 +131,7 @@
/* For the Interrupt and General Control register (PCIC_INT_GEN) */
#define PCIC_INT_MASK 0x0f
#define PCIC_INT_FLAGMASK 0x0f
-#define PCIC_INTR_ENA 0x10
+#define PCIC_INTR_ENA 0x10 /* clr bit means CSC interrupt goes via IRQ */
#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */
#define PCIC_IOCARD 0x20
#define PCIC_MEMCARD 0x00
@@ -136,12 +139,20 @@
#define PCIC_RINGIND 0x80
/* For the Card Status Change register (PCIC_STAT_CHG) */
+#define PCIC_GPICH 0x10 /* General Purpose Input (GPI) Change */
#define PCIC_CDTCH 0x08 /* Card Detect Change */
#define PCIC_RDYCH 0x04 /* Ready Change */
#define PCIC_BATWRN 0x02 /* Battery Warning */
#define PCIC_BATDED 0x01 /* Battery Dead */
#define PCIC_STCH 0x01 /* Status Change */
+/* For the Card Status Change interrupt config register (PCIC_STAT_INT) */
+#define PCIC_CDT_ENA 0x08 /* Card Detect Enable */
+#define PCIC_RDY_ENA 0x04 /* Ready Enable */
+#define PCIC_BATWRN_ENA 0x02 /* Battery Warning */
+#define PCIC_BATDED_ENA 0x01 /* Battery Dead */
+#define PCIC_ST_ENA 0x01 /* Status Change */
+
/* For the Address Window Enable Register (PCIC_ADDRWINE) */
#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */
#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */
@@ -194,7 +205,7 @@
/* For Card Detect and General Control register (PCIC_CDGC) */
#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */
#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */
-#define PCIC_GPI_EN 0x04 /* GPI Enable */
+#define PCIC_GPI_EN 0x04 /* General Purpose Input (GPI) Enable */
#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */
#define PCIC_CDRES_EN 0x10 /* card detect resume enable */
#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */
@@ -206,12 +217,16 @@ struct pcic_register {
};
struct pcic_regs {
u_short chip_vers;
-#define PCMICA_CHIP_82365_0 1
-#define PCMICA_CHIP_82365_1 2
-#define PCMICA_CHIP_IBM_1 3
-#define PCMICA_CHIP_IBM_2 4
+#define PCMICA_CHIP_82365_0 1
+#define PCMICA_CHIP_82365_1 2
+#define PCMICA_CHIP_IBM_1 3
+#define PCMICA_CHIP_IBM_2 4
+#define PCMICA_CHIP_146FC6 5
+#define PCMICA_CHIP_146FC7 6
u_short cnt;
struct pcic_register reg[128];
};
/* DON'T ADD ANYTHING AFTER THIS #endif */
#endif /* __82365_H__ */
+#ifndef __82365_H__
+#define __82365_H__
diff --git a/sys/dev/isa/com.c b/sys/dev/isa/com.c
index 77dd24748f4..5570f7ef424 100644
--- a/sys/dev/isa/com.c
+++ b/sys/dev/isa/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.11 1996/04/21 22:23:15 deraadt Exp $ */
+/* $OpenBSD: com.c,v 1.12 1996/04/29 14:16:15 hvozda Exp $ */
/* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
/*-
@@ -81,6 +81,7 @@
struct com_softc {
struct device sc_dev;
void *sc_ih;
+ bus_chipset_tag_t sc_bc;
struct tty *sc_tty;
int sc_overflows;
@@ -94,7 +95,6 @@ struct com_softc {
int sc_hayespbase;
#endif
- bus_chipset_tag_t sc_bc;
bus_io_handle_t sc_ioh;
bus_io_handle_t sc_hayespioh;
@@ -102,6 +102,9 @@ struct com_softc {
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
#define COM_HW_HAYESP 0x04
+#define COM_HW_ABSENT_PENDING 0x08 /* reattached, awaiting close/reopen */
+#define COM_HW_ABSENT 0x10 /* configure actually failed, or removed */
+#define COM_HW_REATTACH 0x20 /* reattaching */
#define COM_HW_CONSOLE 0x40
u_char sc_swflags;
#define COM_SW_SOFTCAR 0x01
@@ -125,6 +128,8 @@ int comintr __P((void *));
void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
+void com_absent_notify __P((struct com_softc *sc));
+void comstart_pending __P((void *arg));
/*
* XXX the following two cfattach structs should be different, and possibly
@@ -145,12 +150,17 @@ struct cfattach com_commulti_ca = {
};
#endif
+
struct cfdriver com_cd = {
NULL, "com", DV_TTY
};
int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
+#ifndef CONSPEED
+#define CONSPEED B9600
+#endif
+
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED; /* XXX why set default? */
#else
@@ -181,49 +191,201 @@ extern int kgdb_debug_init;
#define CLR(t, f) (t) &= ~(f)
#define ISSET(t, f) ((t) & (f))
-/*#include "pcmciabus.h"*/
-#if NPCMCIABUS >0
+#if NCOM_PCMCIA
+#include <dev/pcmcia/pcmciavar.h>
+
+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 cfattach com_pcmcia_ca = {
+ sizeof(struct com_softc), com_pcmcia_match, comattach,
+ com_pcmcia_detach
+};
+
+int
+com_pcmcia_mod __P((struct pcmcia_link *pc_link,
+ struct device *self,
+ struct pcmcia_conf *pc_cf,
+ struct cfdata *cf));
+
/* additional setup needed for pcmcia devices */
-#include <dev/pcmcia/pcmciabus.h>
/* modify config entry */
-static int
-commod(pc_link,self,pc_cf,cf)
+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;
- struct pcmciadevs *dev=pc_link->device;
+ struct pcmciadevs *dev = pc_link->device;
struct ed_softc *sc = (void *)self;
- if(!(err=pc_link->adapter->bus_link->bus_config(pc_link,self,pc_cf,cf))) {
- pc_cf->memwin=0;
- if(pc_cf->cfgtype==0)
- pc_cf->cfgtype=CFGENTRYID; /* determine from ioaddr */
+ 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 */
}
return err;
}
+
+int com_pcmcia_isa_attach __P((struct device *, void *, void *,
+ struct pcmcia_link *));
+int com_pcmcia_remove __P((struct pcmcia_link *, struct device *));
+
static struct pcmcia_com {
struct pcmcia_device pcd;
-} pcmcia_com= {
- "PCMCIA Modem card",commod,NULL,NULL,NULL
+} pcmcia_com = {
+ {"PCMCIA Modem card", com_pcmcia_mod, com_pcmcia_isa_attach,
+ NULL, com_pcmcia_remove}
};
-struct pcmciadevs pcmcia_com_devs[]={
- { "com", 0,
+
+
+struct pcmciadevs pcmcia_com_devs[] = {
+ { "com", 0,
NULL, "*MODEM*", NULL, NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "com", 0,
NULL, NULL, "*MODEM*", NULL,
NULL, (void *)&pcmcia_com
},
- { "com", 0,
+ { "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
+com_pcmcia_isa_attach(parent, match, aux, pc_link)
+ struct device *parent;
+ void *match;
+ void *aux;
+ struct pcmcia_link *pc_link;
+{
+ struct isa_attach_args *ia = aux;
+ struct com_softc *sc = match;
+
+ int rval;
+ if (rval = comprobe(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);
+#endif
+ sc->sc_hwflags = COM_HW_REATTACH |
+ (sc->sc_hwflags & (COM_HW_ABSENT_PENDING|COM_HW_CONSOLE));
+ } else
+ sc->sc_hwflags = 0;
+ }
+ return rval;
+}
+
+
+/*
+ * 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;
+
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ /* don't let it really be detached, it is still open */
+ return EBUSY;
+ }
+ return 0; /* OK! */
+}
+
+/*
+ * 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;
+{
+ 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_bc, sc->sc_ih);
+ sc->sc_ih = NULL;
+ SET(sc->sc_hwflags, COM_HW_ABSENT);
+ return 0; /* OK! */
+ }
+ /*
+ * 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
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+
+ return 0;
+}
+
+#if 0
+void
+com_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ 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");
+ }
+}
#endif
+#endif
+
+/*
+ * must be called at spltty() or higher.
+ */
+void
+com_absent_notify(sc)
+ struct com_softc *sc;
+{
+ struct tty *tp;
+ if (tp = sc->sc_tty) {
+ CLR(tp->t_state, TS_CARR_ON|TS_BUSY);
+ ttyflush(tp, FREAD|FWRITE);
+ }
+}
int
comspeed(speed)
@@ -351,13 +513,21 @@ comprobe(parent, match, aux)
int iobase, needioh;
int rv = 1;
+#if NCOM_ISA || NCOM_PCMCIA
+#define IS_ISA(parent) \
+ (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
+#elif NCOM_ISA
+#define IS_ISA(parent) \
+ !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
+#endif
/*
* XXX should be broken out into functions for isa probe and
* XXX for commulti probe, with a helper function that contains
* XXX most of the interesting stuff.
*/
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
bc = ia->ia_bc;
@@ -393,8 +563,8 @@ comprobe(parent, match, aux)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
-#if NCOM_ISA
- if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (rv && IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
@@ -425,10 +595,16 @@ comattach(parent, self, aux)
* XXX for commulti attach, with a helper function that contains
* XXX most of the interesting stuff.
*/
- sc->sc_hwflags = 0;
+ if (ISSET(sc->sc_hwflags, COM_HW_REATTACH)) {
+ int s;
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ } else
+ sc->sc_hwflags = 0;
sc->sc_swflags = 0;
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
/*
@@ -457,7 +633,7 @@ comattach(parent, self, aux)
irq = IRQUNK;
if (ca->ca_noien)
- sc->sc_hwflags |= COM_HW_NOIEN;
+ SET(sc->sc_hwflags, COM_HW_NOIEN);
} else
#endif
panic("comattach: impossible");
@@ -522,8 +698,8 @@ comattach(parent, self, aux)
bus_io_write_1(bc, ioh, com_mcr, 0);
if (irq != IRQUNK) {
-#if NCOM_ISA
- if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
+#if NCOM_ISA || NCOM_PCMCIA
+ if (IS_ISA(parent)) {
struct isa_attach_args *ia = aux;
sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
@@ -576,7 +752,7 @@ comopen(dev, flag, mode, p)
if (unit >= com_cd.cd_ndevs)
return ENXIO;
sc = com_cd.cd_devs[unit];
- if (!sc)
+ if (!sc || ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING))
return ENXIO;
if (!sc->sc_tty)
@@ -716,19 +892,30 @@ comclose(dev, flag, mode, p)
(*linesw[tp->t_line].l_close)(tp, flag);
s = spltty();
- CLR(sc->sc_lcr, LCR_SBREAK);
- bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
- bus_io_write_1(bc, ioh, com_ier, 0);
- if (ISSET(tp->t_cflag, HUPCL) &&
- !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
- /* XXX perhaps only clear DTR */
- bus_io_write_1(bc, ioh, com_mcr, 0);
+ if (!ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /* can't do any of this stuff .... */
+ CLR(sc->sc_lcr, LCR_SBREAK);
+ bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
+ bus_io_write_1(bc, ioh, com_ier, 0);
+ if (ISSET(tp->t_cflag, HUPCL) &&
+ !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
+ /* XXX perhaps only clear DTR */
+ bus_io_write_1(bc, ioh, com_mcr, 0);
+ }
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (--comsopen == 0)
untimeout(compoll, NULL);
splx(s);
ttyclose(tp);
+#ifdef COM_DEBUG
+ /* mark it ready for more use if reattached earlier */
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT_PENDING)) {
+ printf("comclose pending cleared\n");
+ }
+#endif
+ CLR(sc->sc_hwflags, COM_HW_ABSENT_PENDING);
+
#ifdef notyet /* XXXX */
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
ttyfree(tp);
@@ -747,6 +934,13 @@ comread(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -759,6 +953,13 @@ comwrite(dev, uio, flag)
struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
struct tty *tp = sc->sc_tty;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
@@ -800,6 +1001,13 @@ comioctl(dev, cmd, data, flag, p)
bus_io_handle_t ioh = sc->sc_ioh;
int error;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return error;
@@ -914,6 +1122,13 @@ comparam(tp, t)
tcflag_t oldcflag;
int s;
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ int s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+ return EIO;
+ }
+
/* check requested parameters */
if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
return EINVAL;
@@ -1042,6 +1257,18 @@ comparam(tp, t)
}
void
+comstart_pending(arg)
+ void *arg;
+{
+ struct com_softc *sc = arg;
+ int s;
+
+ s = spltty();
+ com_absent_notify(sc);
+ splx(s);
+}
+
+void
comstart(tp)
struct tty *tp;
{
@@ -1051,6 +1278,16 @@ comstart(tp)
int s;
s = spltty();
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT|COM_HW_ABSENT_PENDING)) {
+ /*
+ * not quite good enough: if caller is ttywait() it will
+ * go to sleep immediately, so hang out a bit and then
+ * prod caller again.
+ */
+ com_absent_notify(sc);
+ timeout(comstart_pending, sc, 1);
+ goto out;
+ }
if (ISSET(tp->t_state, TS_BUSY))
goto out;
if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
@@ -1236,6 +1473,9 @@ comintr(arg)
} iter[32];
#endif
+ if (ISSET(sc->sc_hwflags, COM_HW_ABSENT) || !sc->sc_tty)
+ return 0; /* can't do squat. */
+
#ifdef COM_DEBUG
n = 0;
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index f145e7b4d30..6303824ce85 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.10 1996/04/27 18:39:07 niklas Exp $
+# $OpenBSD: files.isa,v 1.11 1996/04/29 14:16:22 hvozda Exp $
# $NetBSD: files.isa,v 1.17 1996/03/29 20:53:30 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
@@ -19,27 +19,6 @@ file dev/isa/isa.c isa needs-flag
define isadma
file dev/isa/isadma.c isadma needs-flag
-# PCMCIA
-# XXX What is this?
-#config problems
-#device pcic at isa
-#file dev/isa/pcmcia_pcic.c pcic pcmciabus
-
-define pcicbus {[iomem = -1], [iosiz = 0]}
-
-device pcic: pcicbus
-attach pcic at isa
-file dev/isa/pcmcia_pcic.c pcic
-
-file dev/isa/pcmcia_isa.c pcmcia
-
-#
-# PCMCIA-only drivers
-#
-
-include "../../../dev/pcmcia/files.pcmcia"
-
-
#
# 8250/16[45]50-based multi-port serial boards
#
@@ -69,7 +48,8 @@ file dev/isa/rtfps.c rtfps
device com: tty
attach com at isa with com_isa
attach com at commulti with com_commulti
-file dev/isa/com.c com & (com_isa | com_commulti) needs-flag
+attach com at pcmcia with com_pcmcia
+file dev/isa/com.c com & (com_isa | com_commulti | com_pcmcia) needs-flag
# Cyclades Cyclom multiport serial cards
# XXX currently broken
@@ -167,9 +147,10 @@ file dev/isa/elink.c elink
# National Semiconductor DS8390/WD83C690-based boards
# (WD/SMC 80x3 family, SMC Ultra [8216], 3Com 3C503, NE[12]000, and clones)
# XXX conflicts with amiga if_ed.c
-#device ed: ether, ifnet
-#attach ed at isa
-#file dev/isa/if_ed.c ed needs-flag
+device ed: ether, ifnet
+attach ed at isa with ed_isa
+attach ed at pcmcia with ed_pcmcia
+file dev/isa/if_ed.c ed & (ed_isa | ed_pcmcia) needs-flag
# 3Com 3C505
device eg: ether, ifnet
@@ -185,7 +166,8 @@ file dev/isa/if_el.c el
device ep: ether, ifnet, elink
attach ep at isa with ep_isa
attach ep at pci with ep_pci
-file dev/isa/if_ep.c ep needs-flag
+attach ep at pcmcia with ep_pcmcia
+file dev/isa/if_ep.c ep & (ep_isa | ep_pci | ep_pcmcia) needs-flag
# Fujitsu MB8696[05]-based boards
# (Allied Telesis AT1700)
@@ -265,3 +247,14 @@ file dev/isa/wss.c wss needs-flag
device gus: audio, isadma, ics2101, ad1848, mulaw
attach gus at isa
file dev/isa/gus.c gus needs-flag
+
+#
+# PCMCIA PCIC (i82365SL and compatibles):
+#
+device pcicmaster { [irq = -1], [iomem = -1], [iosiz = 0] }
+attach pcicmaster at isa
+device pcic: pcmciabus
+attach pcic at pcicmaster
+file dev/isa/pcmcia_pcic.c pcic | pcicmaster
+
+file dev/isa/pcmcia_isa.c pcmcia
diff --git a/sys/dev/isa/if_ed.c b/sys/dev/isa/if_ed.c
index d770c80a73e..8f2499c9d18 100644
--- a/sys/dev/isa/if_ed.c
+++ b/sys/dev/isa/if_ed.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ed.c,v 1.11 1996/04/27 22:19:59 niklas Exp $ */
+/* $OpenBSD: if_ed.c,v 1.12 1996/04/29 14:16:31 hvozda Exp $ */
/* $NetBSD: if_ed.c,v 1.93 1996/04/11 22:28:55 cgd Exp $ */
/*
@@ -19,6 +19,7 @@
*/
#include "bpfilter.h"
+#include "ed.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -154,9 +155,11 @@ void ed_pio_readmem __P((struct ed_softc *, u_short, caddr_t, u_short));
void ed_pio_writemem __P((struct ed_softc *, caddr_t, u_short, u_short));
u_short ed_pio_write_mbufs __P((struct ed_softc *, struct mbuf *, u_short));
-struct cfattach ed_ca = {
+#if NED_ISA > 0
+struct cfattach ed_isa_ca = {
sizeof(struct ed_softc), edprobe, edattach
};
+#endif
struct cfdriver ed_cd = {
NULL, "ed", DV_IFNET
@@ -166,17 +169,19 @@ struct cfdriver ed_cd = {
#define ETHER_MAX_LEN 1518
#define ETHER_ADDR_LEN 6
-#define NIC_PUT(bc, ioh, nic, reg, val) \
- bus_io_write_1((bc), (ioh), ((nic) + (reg)), (val))
-#define NIC_GET(bc, ioh, nic, reg) \
- bus_io_read_1((bc), (ioh), ((nic) + (reg)))
+#if NED_PCMCIA > 0
+#include <dev/pcmcia/pcmciavar.h>
-/*#include "pcmciabus.h"*/
-#if NPCMCIABUS > 0
+int ed_pcmcia_match __P((struct device *, void *, void *));
+void ed_pcmcia_attach __P((struct device *, struct device *, void *));
+int ed_pcmcia_detach __P((struct device *));
-#include <dev/pcmcia/pcmciabus.h>
-static int ed_probe_pcmcia_ne __P((struct device *, void *,
- void *, struct pcmcia_link *));
+struct cfattach ed_pcmcia_ca = {
+ sizeof(struct ed_softc), ed_pcmcia_match, edattach, ed_pcmcia_detach
+};
+
+static int ed_pcmcia_isa_attach __P((struct device *, void *,
+ void *, struct pcmcia_link *));
static int edmod __P((struct pcmcia_link *, struct device *,
struct pcmcia_conf *, struct cfdata *cf));
@@ -185,7 +190,7 @@ static int ed_remove __P((struct pcmcia_link *, struct device *));
/* additional setup needed for pcmcia devices */
static int
-ed_probe_pcmcia_ne(parent, match, aux, pc_link)
+ed_pcmcia_isa_attach(parent, match, aux, pc_link)
struct device *parent;
void *match;
void *aux;
@@ -199,17 +204,18 @@ ed_probe_pcmcia_ne(parent, match, aux, pc_link)
extern int ifqmaxlen;
u_char enaddr[ETHER_ADDR_LEN];
- if ((int)dev->param >= 0)
+ if ((int)dev->param != -1)
err = pcmcia_read_cis(pc_link, enaddr,
(int) dev->param, ETHER_ADDR_LEN);
else
err = 0;
if (err)
- printf("Cannot read cis info %d\n", err);
+ printf("%s: attaching ed: cannot read cis info %d\n",
+ parent->dv_xname, err);
- if (ed_probe_Novell(sc, cf, ia)) {
+ if (ed_find_Novell(sc, cf, ia)) {
delay(100);
- if ((int)dev->param >= 0) {
+ if ((int)dev->param != -1) {
err = pcmcia_read_cis(pc_link, sc->sc_arpcom.ac_enaddr,
(int) dev->param, ETHER_ADDR_LEN);
if (err) {
@@ -229,8 +235,8 @@ ed_probe_pcmcia_ne(parent, match, aux, pc_link)
sc->type_str = dev->model;
sc->sc_arpcom.ac_if.if_snd.ifq_maxlen=ifqmaxlen;
return 1;
- }
- return 0;
+ } else
+ return 0;
}
/* modify config entry */
@@ -242,16 +248,20 @@ edmod(pc_link, self, pc_cf, cf)
struct cfdata *cf;
{
int err;
- struct pcmciadevs *dev=pc_link->device;
- struct ed_softc *sc = (void *)self;
- int svec_card = strcmp(dev->manufacturer, "SVEC") == 0;
+/* struct pcmciadevs *dev=pc_link->device;*/
+/* struct ed_softc *sc = (void *)self;*/
+ int svec_card = pc_cf->memwin == 5;
int de650_0 = (pc_cf->memwin != 0) && !svec_card;
- err = pc_link->adapter->bus_link->bus_config(pc_link, self, pc_cf, cf);
+ err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self, pc_cf, cf);
if (err)
return err;
if (svec_card) {
pc_cf->memwin = 0;
+#if 0
+ pc_cf->cfgid = 32; /* Try this if it still doesn't work */
+ pc_cf->cfgid |= 32; /* or Try this if it still doesn't work */
+#endif
}
if (de650_0) {
pc_cf->io[0].flags =
@@ -281,13 +291,15 @@ ed_remove(pc_link,self)
shutdownhook_disestablish(sc->sc_sh);
ifp->if_flags &= ~(IFF_RUNNING|IFF_UP);
sc->spec_flags |= ED_NOTPRESENT;
- return pc_link->adapter->bus_link->bus_unconfig(pc_link);
+ isa_intr_disestablish(sc->sc_bc, sc->sc_ih);
+ return PCMCIA_BUS_UNCONFIG(pc_link->adapter, pc_link);
}
static struct pcmcia_dlink {
struct pcmcia_device pcd;
-} pcmcia_dlink= {
- "PCMCIA Novell compatible", edmod, ed_probe_pcmcia_ne, NULL, ed_remove
+} pcmcia_dlink = {
+ {"PCMCIA Novell compatible", edmod, ed_pcmcia_isa_attach,
+ NULL, ed_remove}
};
struct pcmciadevs pcmcia_ed_devs[]={
@@ -303,16 +315,61 @@ struct pcmciadevs pcmcia_ed_devs[]={
"Socket EA PCMCIA LAN Adapter Revision D", "Ethernet ID 000000000000",
NULL, (void *) -1,
(void *)&pcmcia_dlink },
- /* probably not right for ethernet address--card does not seem to
- have it anywhere. */
+ /* something screwed up in ports requested */
{ "ed", 0, "SVEC", "FD605 PCMCIA EtherNet Card", "V1-1", NULL,
- (void *)0xb4, (void *)&pcmcia_dlink },
- { "ed", 0, "PMX ", "PE-200", "ETHERNET", "R01", (void *) 0x110,
- (void *)&pcmcia_dlink }, /* 0x110 is a guess */
+ (void *)-1, (void *)&pcmcia_dlink },
+#if 0
+ /* not quite right for ethernet adress */
+ { "ed", 0, "PMX ", "PE-200", "ETHERNET", "R01", (void *)-1,
+ (void *)&pcmcia_dlink },
+#endif
{ NULL }
};
+
+#define ned_pcmcia_devs sizeof(pcmcia_ed_devs)/sizeof(pcmcia_ed_devs[0])
+
+int
+ed_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ return pcmcia_slave_match(parent, match, aux, pcmcia_ed_devs,
+ ned_pcmcia_devs);
+}
+
+void
+ed_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_attach_args *paa = aux;
+
+ printf("ed_pcmcia_attach %p %p %p\n", parent, self, aux);
+ delay(2000000);
+ if (!pcmcia_configure(parent, self, paa->paa_link)) {
+ struct ed_softc *sc = (void *)self;
+ sc->spec_flags |= ED_NOTPRESENT;
+ printf(": not attached\n");
+ }
+}
+
+/*
+ * No detach; network devices are too well linked into the rest of the
+ * kernel.
+ */
+int
+ed_pcmcia_detach(self)
+ struct device *self;
+{
+ return EBUSY;
+}
+
#endif
+#define NIC_PUT(bc, ioh, nic, reg, val) \
+ bus_io_write_1((bc), (ioh), ((nic) + (reg)), (val))
+#define NIC_GET(bc, ioh, nic, reg) \
+ bus_io_read_1((bc), (ioh), ((nic) + (reg)))
/*
* Determine if the device is present.
@@ -1499,7 +1556,6 @@ edinit(sc)
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
int i;
- u_char command;
u_long mcaf[2];
/*
@@ -2412,7 +2468,6 @@ ed_pio_write_mbufs(sc, m, dst)
bus_io_handle_t ioh = sc->sc_ioh;
int nicbase = sc->nic_base, asicbase = sc->asic_base;
u_short len;
- struct mbuf *mp;
int maxwait = 100; /* about 120us */
len = m->m_pkthdr.len;
diff --git a/sys/dev/isa/if_ep.c b/sys/dev/isa/if_ep.c
index 4102ad294e4..f9eab4b8368 100644
--- a/sys/dev/isa/if_ep.c
+++ b/sys/dev/isa/if_ep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ep.c,v 1.11 1996/04/21 22:23:52 deraadt Exp $ */
+/* $OpenBSD: if_ep.c,v 1.12 1996/04/29 14:16:41 hvozda Exp $ */
/* $NetBSD: if_ep.c,v 1.90 1996/04/11 22:29:15 cgd Exp $ */
/*
@@ -31,8 +31,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*#include "pcmciabus.h"*/
+#include "pcmcia.h"
#include "bpfilter.h"
+#include "ep.h"
#include <sys/param.h>
#include <sys/mbuf.h>
@@ -42,6 +43,7 @@
#include <sys/syslog.h>
#include <sys/select.h>
#include <sys/device.h>
+#include <sys/systm.h>
#include <net/if.h>
#include <net/netisr.h>
@@ -114,26 +116,34 @@ struct ep_softc {
#define EP_BUS_PCI 0x3
#define EP_IS_BUS_32(a) ((a) & 0x2)
+
+ u_char pcmcia_flags;
+#define EP_REATTACH 0x01
+#define EP_ABSENT 0x02
};
static int epprobe __P((struct device *, void *, void *));
static void epattach __P((struct device *, struct device *, void *));
/* XXX the following two structs should be different. */
+#if NEP_ISA > 0
struct cfattach ep_isa_ca = {
sizeof(struct ep_softc), epprobe, epattach
};
+#endif
+#if NEP_PCI > 0
struct cfattach ep_pci_ca = {
sizeof(struct ep_softc), epprobe, epattach
};
+#endif
+
struct cfdriver ep_cd = {
NULL, "ep", DV_IFNET
};
int epintr __P((void *));
-static void epxstat __P((struct ep_softc *));
static int epstatus __P((struct ep_softc *));
void epinit __P((struct ep_softc *));
int epioctl __P((struct ifnet *, u_long, caddr_t));
@@ -142,7 +152,7 @@ void epwatchdog __P((int));
void epreset __P((struct ep_softc *));
void epread __P((struct ep_softc *));
struct mbuf *epget __P((struct ep_softc *, int));
-void epmbuffill __P((struct ep_softc *));
+void epmbuffill __P((void *));
void epmbufempty __P((struct ep_softc *));
void epstop __P((struct ep_softc *));
void epsetfilter __P((struct ep_softc *));
@@ -177,31 +187,39 @@ epaddcard(iobase, irq, bustype)
epcards[nepcards].bustype = bustype;
nepcards++;
}
+
+#if NEP_PCMCIA > 0
+#include <dev/pcmcia/pcmciavar.h>
+
+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 *));
-#if NPCMCIABUS > 0
-#include <dev/pcmcia/pcmciabus.h>
-static int ep_probe_pcmcia __P((struct device *, void *,
+static int ep_pcmcia_isa_attach __P((struct device *, void *,
void *, struct pcmcia_link *));
static int epmod __P((struct pcmcia_link *, struct device *,
struct pcmcia_conf *, struct cfdata * cf));
static int ep_remove __P((struct pcmcia_link *, struct device *));
+struct cfattach ep_pcmcia_ca = {
+ sizeof(struct ep_softc), ep_pcmcia_match, epattach, ep_pcmcia_detach
+};
+
/* additional setup needed for pcmcia devices */
static int
-ep_probe_pcmcia(parent, match, aux, pc_link)
+ep_pcmcia_isa_attach(parent, match, aux, pc_link)
struct device *parent;
void *match;
void *aux;
struct pcmcia_link *pc_link;
{
struct ep_softc *sc = (void *) match;
- struct cfdata *cf = sc->sc_dev.dv_cfdata;
+/* struct cfdata *cf = sc->sc_dev.dv_cfdata;*/
struct isa_attach_args *ia = aux;
- struct pcmciadevs *dev = pc_link->device;
+/* struct pcmciadevs *dev = pc_link->device;*/
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int i;
extern int ifqmaxlen;
- short addr[3];
outw(ia->ia_iobase + EP_COMMAND, WINDOW_SELECT | 0);
outw(ia->ia_iobase + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
@@ -211,16 +229,15 @@ ep_probe_pcmcia(parent, match, aux, pc_link)
* ok til here. Now try to figure out which link we have.
* try coax first...
*/
- sc->bustype = EP_BUS_PCMCIA;
#ifdef EP_COAX_DEFAULT
outw(ia->ia_iobase + EP_W0_ADDRESS_CFG, 0xC000);
#else
- /* COAX as default is reportet to be a problem */
+ /* COAX as default is reported to be a problem */
outw(ia->ia_iobase + EP_W0_ADDRESS_CFG, 0x0000);
#endif
ifp->if_snd.ifq_maxlen = ifqmaxlen;
- epaddcard(ia->ia_iobase, ia->ia_irq, 0);
+ epaddcard(ia->ia_iobase, ia->ia_irq, EP_BUS_PCMCIA);
for (i = 0; i < nepcards; i++) {
if (epcards[i].available == 0)
@@ -243,10 +260,11 @@ good:
ia->ia_iosize = 0x10;
ia->ia_msize = 0;
+ sc->bustype = epcards[i].bustype;
+ sc->pcmcia_flags = (pc_link->flags & PCMCIA_REATTACH) ? EP_REATTACH:0;
return 1;
}
-
/* modify config entry */
static int
epmod(pc_link, self, pc_cf, cf)
@@ -256,11 +274,11 @@ epmod(pc_link, self, pc_cf, cf)
struct cfdata *cf;
{
int err;
- struct pcmciadevs *dev = pc_link->device;
- struct ep_softc *sc = (void *) self;
+/* struct pcmciadevs *dev = pc_link->device;*/
+/* struct ep_softc *sc = (void *) self;*/
- if ((err = pc_link->adapter->bus_link->bus_config(pc_link, self,
- pc_cf, cf)) != 0) {
+ if ((err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self,
+ pc_cf, cf)) != 0) {
printf("bus_config failed %d\n", err);
return err;
}
@@ -285,13 +303,14 @@ ep_remove(pc_link, self)
if_down(ifp);
epstop(sc);
ifp->if_flags &= ~(IFF_RUNNING | IFF_UP);
- return pc_link->adapter->bus_link->bus_unconfig(pc_link);
+ sc->pcmcia_flags = EP_ABSENT;
+ return PCMCIA_BUS_UNCONFIG(pc_link->adapter, pc_link);
}
static struct pcmcia_3com {
struct pcmcia_device pcd;
} pcmcia_3com = {
- "PCMCIA 3COM 3C589", epmod, ep_probe_pcmcia, NULL, ep_remove
+ {"PCMCIA 3COM 3C589", epmod, ep_pcmcia_isa_attach, NULL, ep_remove}
};
struct pcmciadevs pcmcia_ep_devs[] = {
@@ -312,8 +331,47 @@ struct pcmciadevs pcmcia_ep_devs[] = {
#endif
{ NULL }
};
+#define nep_pcmcia_devs sizeof(pcmcia_ep_devs)/sizeof(pcmcia_ep_devs[0])
+
+int
+ep_pcmcia_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ return pcmcia_slave_match(parent, match, aux, pcmcia_ep_devs,
+ nep_pcmcia_devs);
+}
+
+void
+ep_pcmcia_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcmcia_attach_args *paa = aux;
+
+ printf("ep_pcmcia_attach %p %p %p\n", parent, self, aux);
+ delay(2000000);
+ if (!pcmcia_configure(parent, self, paa->paa_link)) {
+ struct ep_softc *sc = (void *)self;
+ sc->pcmcia_flags |= EP_ABSENT;
+ printf(": not attached\n");
+ }
+}
+
+/*
+ * No detach; network devices are too well linked into the rest of the
+ * kernel.
+ */
+int
+ep_pcmcia_detach(self)
+ struct device *self;
+{
+ return EBUSY;
+}
+
#endif
+
/*
* 3c579 cards on the EISA bus are probed by their slot number. 3c509
* cards on the ISA bus are probed in ethernet address order. The probe
@@ -513,14 +571,15 @@ epconfig(sc, conn)
ifp->if_flags =
IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
- if_attach(ifp);
- ether_ifattach(ifp);
+ if ((sc->pcmcia_flags & EP_REATTACH) == 0) {
+ if_attach(ifp);
+ ether_ifattach(ifp);
#if NBPFILTER > 0
- bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
- sizeof(struct ether_header));
+ bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
+ sizeof(struct ether_header));
#endif
-
+ }
sc->tx_start_thresh = 20; /* probably a good starting point. */
}
@@ -1219,6 +1278,13 @@ epioctl(ifp, cmd, data)
int s, error = 0;
s = splnet();
+ if (sc->bustype == EP_BUS_PCMCIA &&
+ (sc->pcmcia_flags & EP_ABSENT)) {
+ if_down(ifp);
+ printf("%s: device offline\n", sc->sc_dev.dv_xname);
+ splx(s);
+ return ENXIO;
+ }
switch (cmd) {
@@ -1412,9 +1478,10 @@ epbusyeeprom(sc)
}
void
-epmbuffill(sc)
- struct ep_softc *sc;
+epmbuffill(arg)
+ void *arg;
{
+ struct ep_softc *sc = arg;
int s, i;
s = splnet();
diff --git a/sys/dev/isa/pcmcia_isa.c b/sys/dev/isa/pcmcia_isa.c
index d2fd46ee66f..5a485ca8b7a 100644
--- a/sys/dev/isa/pcmcia_isa.c
+++ b/sys/dev/isa/pcmcia_isa.c
@@ -1,4 +1,6 @@
+/* $Id: pcmcia_isa.c,v 1.2 1996/04/29 14:16:47 hvozda Exp $ */
/*
+ * Copyright (c) 1995,1996 John T. Kohl. All rights reserved.
* Copyright (c) 1994 Stefan Grefen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +28,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcmcia_isa.c,v 1.1 1996/01/16 20:13:01 hvozda Exp $
*/
/* TODO add modload support and loadable lists of devices */
@@ -36,9 +37,10 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/device.h>
+#include <vm/vm.h>
-#include <dev/pcmcia/pcmcia.h>
-#include <dev/pcmcia/pcmciabus.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciareg.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
@@ -49,14 +51,20 @@
#define PCMCIA_ISA_DEBUG
#endif
-static int pcmcia_isa_init __P((struct device *, struct cfdata *,
+#ifdef PCMCIA_ISA_DEBUG
+#define STATIC
+#else
+#define STATIC static
+#endif
+
+STATIC int pcmcia_isa_init __P((struct device *, struct cfdata *,
void *, struct pcmcia_adapter *, int));
-static int pcmcia_isa_search __P((struct device *, void *, cfprint_t));
-static int pcmcia_isa_probe __P((struct device *, void *,
+STATIC int pcmcia_isa_search __P((struct device *, void *, cfprint_t));
+STATIC int pcmcia_isa_probe __P((struct device *, void *,
void *, struct pcmcia_link *));
-static int pcmcia_isa_config __P((struct pcmcia_link *, struct device *,
+STATIC int pcmcia_isa_config __P((struct pcmcia_link *, struct device *,
struct pcmcia_conf *, struct cfdata *));
-static int pcmcia_isa_unconfig __P((struct pcmcia_link *));
+STATIC int pcmcia_isa_unconfig __P((struct pcmcia_link *));
struct pcmciabus_link pcmcia_isa_link = {
pcmcia_isa_config,
@@ -67,7 +75,7 @@ struct pcmciabus_link pcmcia_isa_link = {
};
/* copy out the addr and length from machine specific attach struct */
-static int
+STATIC int
pcmcia_isa_init(parent, cf, aux, pca, flag)
struct device *parent;
struct cfdata *cf;
@@ -75,22 +83,34 @@ pcmcia_isa_init(parent, cf, aux, pca, flag)
struct pcmcia_adapter *pca;
int flag;
{
- struct isa_attach_args *ia = aux;
+ struct pcmciabus_attach_args *pa = aux;
+ bus_mem_handle_t memh;
+ vm_offset_t physaddr;
#ifdef PCMCIA_ISA_DEBUG
if (parent != NULL)
printf("PARENT %s\n", parent->dv_xname);
#endif
- if (flag) { /* attach */
- pca->scratch_mem = (caddr_t) ISA_HOLE_VADDR(ia->ia_maddr);
- pca->scratch_memsiz = ia->ia_msize;
+ if (flag == 0) { /* match */
+ if (bus_mem_map(pa->pba_bc, pa->pba_maddr, pa->pba_msize, 0,
+ &memh))
+ return 0;
+ pca->scratch_memsiz = pa->pba_msize;
+ pca->scratch_memh = memh;
+ pca->pa_bc = pa->pba_bc;
+#ifdef PCMCIA_ISA_DEBUG
+ printf("pbaaddr %p maddr %x msize %x\n",
+ pa, pa->pba_maddr, pa->pba_msize);
+ printf("PCA %p mem %p size %d chip %x memh %x\n",
+ pca, pca->scratch_mem, pca->scratch_memsiz,
+ pca->scratch_chipset, pca->scratch_memh);
+#endif
}
- ia->ia_iosize = 0;
return 1;
}
/* probe and attach a device, the has to be configured already */
-static int
+STATIC int
pcmcia_isa_probe(parent, match, aux, pc_link)
struct device *parent;
void *match;
@@ -103,23 +123,39 @@ pcmcia_isa_probe(parent, match, aux, pc_link)
struct pcmciadevs *pcs = pc_link->device;
int (*probe) () = (pcs != NULL) ? pcs->dev->pcmcia_probe : NULL;
+ if (cf->cf_loc[6] != -1 && cf->cf_loc[6] != pc_link->slot) {
+#ifdef PCMCIA_ISA_DEBUG
+ printf("- isa probe slot mismatch: cf %d <> link %d\n",
+ cf->cf_loc[6], pc_link->slot);
+#endif
+ return 0;
+ }
+#if 0
+ if (pcs == NULL || pcs->dev->pcmcia_probe == NULL) {
+#ifdef PCMCIA_ISA_DEBUG
+ printf("- isa probe null proberoutine %p\n", pcs);
+#endif
+ return 0;
+ }
+#endif
ia.ia_iobase = cf->cf_loc[0];
- ia.ia_iosize = 0x666;
+ ia.ia_iosize = cf->cf_loc[1] == -1 ? 0x666 : cf->cf_loc[1];
ia.ia_maddr = cf->cf_loc[2];
ia.ia_msize = cf->cf_loc[3];
- ia.ia_irq = cf->cf_loc[4];
+ ia.ia_irq = cf->cf_loc[4] == 2 ? 9 : cf->cf_loc[4] ;
ia.ia_drq = cf->cf_loc[5];
+ ia.ia_bc = pc_link->bus->sc_bc;
if (probe == NULL)
- probe = cf->cf_driver->cd_match;
+ probe = cf->cf_attach->ca_match;
#ifdef PCMCIA_ISA_DEBUG
- printf("pcmcia probe %x %x %x\n", ia.ia_iobase, ia.ia_irq, probe);
+ printf("pcmcia probe %x %x %p\n", ia.ia_iobase, ia.ia_irq, probe);
printf("parentname = %s\n", parent->dv_xname);
printf("devname = %s\n", dev->dv_xname);
printf("driver name = %s\n", cf->cf_driver->cd_name);
#endif
if ((*probe) (parent, dev, &ia, pc_link) > 0) {
- extern isaprint();
+ extern isaprint();
config_attach(parent, dev, &ia, isaprint);
#ifdef PCMCIA_ISA_DEBUG
printf("biomask %x netmask %x ttymask %x\n",
@@ -128,7 +164,7 @@ pcmcia_isa_probe(parent, match, aux, pc_link)
#endif
return 1;
}
- else
+ else if (parent->dv_cfdata->cf_driver->cd_indirect == 0)
free(dev, M_DEVBUF);
return 0;
}
@@ -140,7 +176,7 @@ pcmcia_isa_probe(parent, match, aux, pc_link)
* contiguous windows and shift according to the offset for the first not
* fixed window
*/
-static int
+STATIC int
pcmcia_isa_config(pc_link, self, pc_cf, cf)
struct pcmcia_link *pc_link;
struct device *self;
@@ -148,6 +184,7 @@ pcmcia_isa_config(pc_link, self, pc_cf, cf)
struct cfdata *cf;
{
struct isa_attach_args ia;
+ struct pcmciadevs *pcs = pc_link->device;
ia.ia_iobase = cf->cf_loc[0];
ia.ia_iosize = 0x666;
@@ -156,11 +193,19 @@ pcmcia_isa_config(pc_link, self, pc_cf, cf)
ia.ia_irq = cf->cf_loc[4];
ia.ia_drq = cf->cf_loc[5];
#ifdef PCMCIA_ISA_DEBUG
- printf("pcmcia_isa_config iobase=%x maddr=%x msize=%x irq=%x drq=%x\n",
+ printf("pcmcia_isa_config iobase=%x maddr=%x msize=%x irq=%d drq=%d slot=%d\n",
ia.ia_iobase, ISA_HOLE_VADDR(ia.ia_maddr), ia.ia_msize,
- ia.ia_irq, ia.ia_drq);
+ ia.ia_irq, ia.ia_drq, cf->cf_loc[6]);
#endif
+ if (pcs && strcmp(pcs->devname, self->dv_cfdata->cf_driver->cd_name)) {
+#ifdef PCMCIA_ISA_DEBUG
+ printf("- wrong driver %s vs %s\n", pcs->devname,
+ self->dv_cfdata->cf_driver->cd_name);
+#endif
+ return ENODEV;
+ }
+
if (ia.ia_irq != IRQUNK) {
int irq = 1 << ia.ia_irq;
/*
@@ -177,7 +222,10 @@ pcmcia_isa_config(pc_link, self, pc_cf, cf)
if (irq == (1 << 9) || irq == (1 << 2))
irq = (1 << 9) | (1 << 2);
if ((irq & pc_cf->irq_mask) == 0) {
- printf("irq %d mask %x\n", ia.ia_irq,
+ printf("%s: slot %d requested irq %d, avail_mask %x\n",
+ self->dv_parent->dv_xname,
+ pc_link->slot,
+ ia.ia_irq,
pc_cf->irq_mask);
return ENODEV;
}
@@ -247,24 +295,27 @@ pcmcia_isa_config(pc_link, self, pc_cf, cf)
}
-static int
+STATIC int
pcmcia_isa_unconfig(pc_link)
struct pcmcia_link *pc_link;
{
+#if 0
if (pc_link && pc_link->intr > 0) {
/* THIS IS A GUESS ... TODO check all possible drivers */
struct softc {
struct device sc_dev;
void *sc_ih;
+ bus_chipset_tag_t sc_bc;
} *sc = pc_link->devp;
if (sc)
- isa_intr_disestablish(sc->sc_ih);
+ isa_intr_disestablish(sc->sc_bc, sc->sc_ih);
}
+#endif
return 0;
}
/* Searches for for configured devices on the pcmciabus */
-static int
+STATIC int
pcmcia_isa_search(parent, aux, print)
struct device *parent;
void *aux;
diff --git a/sys/dev/isa/pcmcia_pcic.c b/sys/dev/isa/pcmcia_pcic.c
index 8e8f16f1594..dfcf2ea4a81 100644
--- a/sys/dev/isa/pcmcia_pcic.c
+++ b/sys/dev/isa/pcmcia_pcic.c
@@ -1,3 +1,32 @@
+/* $Id: pcmcia_pcic.c,v 1.5 1996/04/29 14:16:53 hvozda Exp $ */
+/*
+ * Copyright (c) 1995, 1996 John T. Kohl
+ * 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. 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.
+ *
+ */
/*
* Device Driver for Intel 82365 based pcmcia slots
*
@@ -20,13 +49,16 @@
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/user.h>
+#include <sys/cpu.h>
#include <machine/pio.h>
#include <dev/isa/isavar.h>
#include <dev/ic/i82365reg.h>
-#include <dev/pcmcia/pcmciabus.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciareg.h>
+
#ifdef IBM_WD
#define PCIC_DEBUG 0xf
#endif
@@ -36,13 +68,13 @@
#define PCDINTR 0x04
#define PCDSERV 0x08
#define PCDRW 0x10
+#define PCDCONF 0x20
int pcic_debug = PCIC_DEBUG;
#define DEBUG(a) (pcic_debug & (a))
#else
#define DEBUG(a) (0)
#endif
-
/*
* pcic_softc: per line info and status
*/
@@ -69,20 +101,26 @@ struct slot {
struct pcmcia_link *link;
struct pcic_softc *chip;
};
+
struct pcic_softc {
- struct device sc_dev;
+ struct device sc_dev;
+ bus_chipset_tag_t sc_bc;
+ struct pcmcia_adapter sc_adapter;
void *sc_ih;
int sc_polltimo;
int sc_pcic_irq;
- u_short pcic_base; /* base port for each board */
- u_char slot_id;
- u_char chip_inf;
- struct slot slot[2];
-} pcic_softc[4];
+ bus_io_handle_t sc_ioh;
+ bus_mem_handle_t sc_memh;
+ u_short pcic_base; /* base port for each board */
+ u_char chip_inf;
+ struct slot slot[4]; /* treat up to 4 as on the same pcic */
+};
+#define pcic_parent(sc) ((struct pcicmaster_softc *)(sc)->sc_dev.dv_parent)
static int pcic_map_io __P((struct pcmcia_link *, u_int, u_int, int));
-static int pcic_map_mem __P((struct pcmcia_link *, caddr_t,
+static int pcic_map_mem __P((struct pcmcia_link *, bus_chipset_tag_t,
+ bus_mem_handle_t,
u_int, u_int, int));
static int pcic_map_intr __P((struct pcmcia_link *, int, int));
static int pcic_service __P((struct pcmcia_link *, int, void *, int));
@@ -94,15 +132,53 @@ static struct pcmcia_funcs pcic_funcs = {
pcic_service
};
-int pcicprobe __P((struct device *, void *, void *));
-void pcicattach __P((struct device *, struct device *, void *));
+int pcic_probe __P((struct device *, void *, void *));
+void pcic_attach __P((struct device *, struct device *, void *));
+int pcic_print __P((void *, char *));
+
+int pcicmaster_probe __P((struct device *, void *, void *));
+void pcicmaster_attach __P((struct device *, struct device *, void *));
+int pcicmaster_print __P((void *, char *));
extern struct pcmciabus_link pcmcia_isa_link;
-struct cfdriver pciccd = {
- NULL, "pcic", pcicprobe, pcicattach, DV_DULL, sizeof(struct pcic_softc)
+struct cfattach pcic_ca = {
+ sizeof(struct pcic_softc), pcic_probe, pcic_attach,
};
+struct cfdriver pcic_cd = {
+ NULL, "pcic", DV_DULL
+};
+
+struct pcicmaster_softc {
+ struct device sc_dev;
+ bus_chipset_tag_t sc_bc;
+ bus_io_handle_t sc_ioh;
+ struct pcic_softc *sc_ctlrs[2];
+ char sc_slavestate[2];
+#define SLAVE_NOTPRESENT 0
+#define SLAVE_FOUND 1
+#define SLAVE_CONFIGURED 2
+};
+
+struct cfattach pcicmaster_ca = {
+ sizeof(struct pcicmaster_softc), pcicmaster_probe, pcicmaster_attach,
+};
+
+struct cfdriver pcicmaster_cd = {
+ NULL, "pcicmaster", DV_DULL, 1
+};
+
+struct pcic_attach_args {
+ int pia_ctlr; /* pcic ctlr number */
+ bus_chipset_tag_t pia_bc; /* bus chipset tag */
+ bus_io_handle_t pia_ioh; /* base i/o address */
+ int pia_iosize; /* span of ports used */
+ int pia_irq; /* interrupt request */
+ int pia_drq; /* DMA request */
+ int pia_maddr; /* physical i/o mem addr */
+ u_int pia_msize; /* size of i/o memory */
+};
static u_char pcic_rd __P((struct slot *, int));
static void pcic_wr __P((struct slot *, int, int));
@@ -114,12 +190,13 @@ pcic_rd(slot, reg)
int reg;
{
u_char res;
+ bus_chipset_tag_t bc = slot->chip->sc_bc;
+ bus_io_handle_t ioh = slot->chip->sc_ioh;
if (DEBUG(PCDRW))
- printf("pcic_rd(%x [%x %x]) = ", reg, slot->reg_off,
- slot->chip->pcic_base);
- outb(slot->chip->pcic_base, slot->reg_off + reg);
+ printf("pcic_rd(%x [%x %x]) = ", reg, slot->reg_off, ioh);
+ bus_io_write_1(bc, ioh, 0, slot->reg_off + reg);
delay(1);
- res = inb(slot->chip->pcic_base + 1);
+ res = bus_io_read_1(bc, ioh, 1);
if (DEBUG(PCDRW))
printf("%x\n", res);
return res;
@@ -130,15 +207,17 @@ pcic_wr(slot, reg, val)
struct slot *slot;
int reg, val;
{
- outb(slot->chip->pcic_base, slot->reg_off + reg);
+ bus_chipset_tag_t bc = slot->chip->sc_bc;
+ bus_io_handle_t ioh = slot->chip->sc_ioh;
+ bus_io_write_1(bc, ioh, 0, slot->reg_off + reg);
delay(1);
- outb(slot->chip->pcic_base + 1, val);
+ bus_io_write_1(bc, ioh, 1, val);
if (DEBUG(PCDRW)) {
int res;
delay(1);
- outb(slot->chip->pcic_base, slot->reg_off + reg);
+ bus_io_write_1(bc, ioh, 0, slot->reg_off + reg);
delay(1);
- res = inb(slot->chip->pcic_base + 1);
+ res = bus_io_read_1(bc, ioh, 1);
printf("pcic_wr(%x %x) = %x\n", reg, val, res);
}
}
@@ -154,121 +233,214 @@ pcic_wait(slot, i)
}
int
-pcicprobe(parent, self, aux)
+pcic_probe(parent, self, aux)
struct device *parent;
void *self;
void *aux;
{
- struct pcic_softc *pcic = (void *) self;
- struct isa_attach_args *ia = aux;
- struct cfdata *cf = pcic->sc_dev.dv_cfdata;
- u_int chip_inf = 0;
- int i;
+ struct pcic_softc *pcic = self;
+ struct pcicmaster_softc *pcicm = (struct pcicmaster_softc *) parent;
+ struct pcic_attach_args *pia = aux;
+ bus_mem_handle_t memh;
+ u_int chip_inf = 0, ochip_inf = 0;
+ int first = 1;
+ int i, j, maxslot;
- pcic->pcic_base = ia->ia_iobase;
- pcic->slot_id = 0; /* XXX */
bzero(pcic->slot, sizeof(pcic->slot));
- pcic->slot[0].chip = pcic;
- pcic->slot[0].reg_off = (pcic->slot_id & 1) * 0x80;
- pcic->slot[1].chip = pcic;
- pcic->slot[1].reg_off = ((pcic->slot_id & 1) * 0x80) + 0x40;
- chip_inf = pcic_rd(&pcic->slot[0], PCIC_ID_REV);
- switch (chip_inf) {
- case PCIC_INTEL0:
+
+ if (DEBUG(PCDCONF)) {
+ printf("pcic_probe controller %d unit %d\n", pia->pia_ctlr,
+ pcic->sc_dev.dv_unit);
+ delay(2000000);
+ }
+ if (pcicm->sc_slavestate[pia->pia_ctlr] != SLAVE_FOUND)
+ return 0;
+ if (pcic->sc_dev.dv_cfdata->cf_loc[1] == -1 ||
+ pcic->sc_dev.dv_cfdata->cf_loc[2] == 0)
+ return 0;
+
+ /*
+ * select register offsets based on which controller we are.
+ * 2 pcic controllers (w/ 2 slots each) possible at each
+ * IO port location, for a total of 8 possible PCMCIA slots.
+ *
+ * for VLSI controllers, we probe up to 4 slots for the same chip type,
+ * and handle them on one controller. This is slightly
+ * cheating (two separate pcic's are required for 4 slots, according
+ * to the i82365 spec).
+ *
+ * For other controllers, we only take up to 2 slots.
+ */
+ pcic->sc_ioh = pia->pia_ioh;
+ pcic->sc_bc = pia->pia_bc;
+ pcic->sc_adapter.nslots = 0;
+ maxslot = 2;
+ for (i = j = 0; i < maxslot; i++) {
+ pcic->slot[j].reg_off = 0x80 * pia->pia_ctlr + 0x40 * i;
+ pcic->slot[j].chip = pcic;
+
+ chip_inf = pcic_rd(&pcic->slot[j], PCIC_ID_REV);
+ if (DEBUG(PCDCONF)) {
+ printf("pcic_probe read info %x\n", chip_inf);
+ delay(2000000);
+ }
+ if (!first && ochip_inf != chip_inf)
+ continue; /* don't attach, it's different */
+ ochip_inf = chip_inf;
+ switch (chip_inf) {
+ case PCIC_INTEL0:
pcic->chip_inf = PCMICA_CHIP_82365_0;
goto ok;
- case PCIC_INTEL1:
+ case PCIC_INTEL1:
pcic->chip_inf = PCMICA_CHIP_82365_1;
goto ok;
- case PCIC_IBM1:
+ case PCIC_IBM1:
pcic->chip_inf = PCMICA_CHIP_IBM_1;
goto ok;
- case PCIC_IBM2:
+ case PCIC_146FC6:
+ pcic->chip_inf = PCMICA_CHIP_146FC6;
+ maxslot = 4;
+ goto ok;
+ case PCIC_146FC7:
+ pcic->chip_inf = PCMICA_CHIP_146FC7;
+ maxslot = 4;
+ goto ok;
+ case PCIC_IBM2:
pcic->chip_inf = PCMICA_CHIP_IBM_2;
-ok:
- ia->ia_msize = 0;
- ia->ia_iosize = 2;
- pcmcia_register(pcic, &pcmcia_isa_link, &pcic_funcs,
- pcic->slot_id);
+ ok:
+ if (first) {
+ pcic->sc_adapter.adapter_softc = (void *)pcic;
+ pcic->sc_adapter.chip_link = &pcic_funcs;
+ pcic->sc_adapter.bus_link = &pcmcia_isa_link;
+ pcicm->sc_ctlrs[pia->pia_ctlr] = pcic;
+ pcicm->sc_slavestate[pia->pia_ctlr] = SLAVE_CONFIGURED;
+ first = 0;
+ }
+ pcic->sc_adapter.nslots++;
+ j++;
+ default:
+ if (DEBUG(PCDCONF)) {
+ printf("found ID %x at pcic%d position\n",
+ chip_inf & 0xff, pcic->sc_dev.dv_unit);
+ }
+ continue;
+ }
+ }
+ if (pcic->sc_adapter.nslots != 0) {
+ pcic->sc_memh = memh;
return 1;
- default:
- printf("found ID %x at pcic position\n", chip_inf & 0xff);
- break;
}
- /* reset mappings .... */
- pcic_wr(&pcic->slot[0], PCIC_POWER, pcic->slot[0].pow=PCIC_DISRST);
- pcic_wr(&pcic->slot[1], PCIC_POWER, pcic->slot[1].pow=PCIC_DISRST);
-
- delay(1000);
-
- for (i = PCIC_INT_GEN; i < 0x40; i++) {
- pcic_wr(&pcic->slot[0], i, 0);
- pcic_wr(&pcic->slot[1], i, 0);
+ if (DEBUG(PCDCONF)) {
+ printf("pcic_probe failed\n");
+ delay(2000000);
}
- delay(10000);
+ bus_mem_unmap(pia->pia_bc, memh, pia->pia_msize);
return 0;
}
int
pcic_intr __P((void *));
+int
+pcic_print(aux, name)
+ void *aux;
+ char *name;
+{
+ if (name != NULL)
+ printf("%s: pcmciabus ", name);
+ return UNCONF;
+}
void
-pcicattach(parent, self, aux)
+pcic_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct pcic_softc *pcic = (void *) self;
- struct isa_attach_args *ia = aux;
+ struct pcic_attach_args *pia = aux;
+ struct pcmciabus_attach_args pba;
struct slot *slot;
int i;
static char *pcic_names[] = {
"Intel 82365sl Rev. 0",
"Intel 82365sl Rev. 1",
"IBM 82365sl clone Rev. 1",
- "IBM 82365sl clone Rev. 2"};
- printf(": %s slots %d-%d (%x %x)\n", pcic_names[pcic->chip_inf -
- PCMICA_CHIP_82365_0], pcic->slot_id * 2, pcic->slot_id * 2 + 1,
- &pcic->slot[0], &pcic->slot[1]);
+ "IBM 82365sl clone Rev. 2",
+ "VL82146 (82365sl clone) Rev. 6",
+ "VL82146 (82365sl clone) Rev. 7" };
+ if (DEBUG(PCDCONF)) {
+ printf("pcic_attach found\n");
+ delay(2000000);
+ }
+ pia->pia_irq = self->dv_cfdata->cf_loc[0];
+ pia->pia_maddr = self->dv_cfdata->cf_loc[1];
+ pia->pia_msize = self->dv_cfdata->cf_loc[2];
+
+ printf(": %s slots %d-%d iomem %x-%x",
+ pcic_names[pcic->chip_inf - PCMICA_CHIP_82365_0],
+ pcic->sc_dev.dv_unit * 2,
+ pcic->sc_dev.dv_unit * 2 + pcic->sc_adapter.nslots - 1,
+ pia->pia_maddr, pia->pia_maddr + pia->pia_msize - 1);
+ if (pia->pia_irq != IRQUNK)
+ printf(" irq %d\n", pia->pia_irq);
+ else
+ printf("\n");
+ if (DEBUG(PCDCONF))
+ delay(2000000);
+
+#ifdef PCMCIA_ISA_DEBUG
+ printf("pcic %p slots %p,%p\nisaaddr %p ports %x size %d irq %d drq %d maddr %x msize %x\n",
+ pcic, &pcic->slot[0], &pcic->slot[1],
+ pia, pia->pia_ioh, pia->pia_iosize,
+ pia->pia_irq, pia->pia_drq, pia->pia_maddr, pia->pia_msize);
+ if (DEBUG(PCDCONF))
+ delay(2000000);
+#endif
+
/* enable interrupts on events */
- if (ia->ia_irq != IRQUNK)
- pcic->sc_pcic_irq = ia->ia_irq;
+ if (pia->pia_irq != IRQUNK)
+ pcic->sc_pcic_irq = pia->pia_irq;
else
pcic->sc_pcic_irq = 0;
- for (i = 0; i < 2; i++) {
- slot = &pcic->slot[i];
- slot->irq = pcic->sc_pcic_irq | PCIC_INTR_ENA;
- pcic_wr(slot, PCIC_STAT_INT,
- (pcic->sc_pcic_irq << 4) |PCIC_CDTCH | PCIC_STCH);
- pcic_wr(&pcic->slot[i], PCIC_INT_GEN, slot->irq);
- (void) pcic_rd(&pcic->slot[i], PCIC_STAT_CHG);
+ for (i = 0; i < pcic->sc_adapter.nslots; i++) {
+ slot = &pcic->slot[i];
+ /*
+ * Arrange for card status change interrupts
+ * to be steered to specified IRQ.
+ * Treat all cards as I/O cards for the moment so we get
+ * sensible card change interrupt codes (besides, we don't
+ * support memory cards :)
+ */
+ pcic_wr(slot, PCIC_STAT_INT,
+ (pcic->sc_pcic_irq << 4) |
+ PCIC_CDTCH | PCIC_IOCARD);
+ slot->irq = pcic_rd(slot, PCIC_INT_GEN) & ~PCIC_INTR_ENA;
+ pcic_wr(slot, PCIC_INT_GEN, slot->irq);
+ (void) pcic_rd(slot, PCIC_STAT_CHG);
}
- if (ia->ia_irq == IRQUNK) {
+ if (pia->pia_irq == IRQUNK) {
pcic->sc_polltimo = hz/2;
timeout((void (*)(void *))pcic_intr, pcic, pcic->sc_polltimo);
} else {
- pcic->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE,
- IPL_NET, pcic_intr, pcic, pcic->sc_dev.dv_xname);
+ pcic->sc_ih = isa_intr_establish(pia->pia_bc,
+ pia->pia_irq, IST_EDGE,
+ IPL_PCMCIA, pcic_intr, pcic, pcic->sc_dev.dv_xname);
pcic->sc_polltimo = 0;
}
-}
-
-#ifdef DDB
-int pcic_intr_test(slot)
-struct slot *slot;
-{
- printf("CSC interrupt state: %x\n", pcic_rd(slot, PCIC_STAT_INT));
- printf("General interrupt state: %x\n", pcic_rd(slot, PCIC_INT_GEN));
-}
-
-int pcic_intr_set(slot)
-struct slot *slot;
-{
- pcic_wr(slot, PCIC_INT_GEN, pcic_rd(slot, PCIC_INT_GEN)|PCIC_INTR_ENA);
- pcic_intr_test(slot);
-}
+ /*
+ * Probe the pcmciabus at this controller.
+ */
+ pba.pba_bc = pia->pia_bc;
+ pba.pba_maddr = pia->pia_maddr;
+ pba.pba_msize = pia->pia_msize;
+ pba.pba_aux = &pcic->sc_adapter;
+#ifdef PCMCIA_DEBUG
+ printf("config_found(%p, %p, %p)\n",
+ self, &pba, pcic_print);
#endif
+ config_found(self, (void *)&pba, pcic_print);
+}
int
pcic_intr(arg)
@@ -278,14 +450,17 @@ void *arg;
u_char statchg, intgen;
register int i;
+#ifdef PCMCIA_PCIC_DEBUG
if (pcic->sc_polltimo == 0)
printf("%s: interrupt:", pcic->sc_dev.dv_xname);
- for (i = 0; i < 2; i++) {
+#endif
+ for (i = 0; i < pcic->sc_adapter.nslots; i++) {
struct pcmcia_link *link = pcic->slot[i].link;
statchg = pcic_rd(&pcic->slot[i], PCIC_STAT_CHG);
if (statchg == 0)
continue;
intgen = pcic_rd(&pcic->slot[i], PCIC_INT_GEN);
+#ifdef PCMCIA_PCIC_DEBUG
if (intgen & PCIC_IOCARD) {
printf("%s: slot %d iocard status %s%s\n",
pcic->sc_dev.dv_xname, i,
@@ -295,6 +470,7 @@ void *arg;
printf("%s: slot %d memcard status %x\n",
pcic->sc_dev.dv_xname, i, statchg);
}
+#endif
if ((statchg & PCIC_CDTCH) &&
(link->flags & PCMCIA_SLOT_OPEN) == 0) {
#if 0
@@ -330,7 +506,10 @@ pcic_map_io(link, start, len, flags)
int flags;
{
struct pcic_softc *sc = link->adapter->adapter_softc;
- struct slot *slot = &sc->slot[link->slot & 1];
+ struct slot *slot;
+ if (link->slot >= sc->sc_adapter.nslots)
+ return ENXIO;
+ slot = &sc->slot[link->slot];
len--;
if (DEBUG(PCDIO)) {
@@ -403,10 +582,8 @@ pcic_map_io(link, start, len, flags)
delay(1000);
return 0;
} else {
- u_int stop;
int window;
int winid;
- int ioflags;
if (flags & PCMCIA_LAST_WIN) {
window = MAX_IOSECTION - 1;
} else if (flags & PCMCIA_FIRST_WIN) {
@@ -440,26 +617,33 @@ pcic_map_io(link, start, len, flags)
slot->io_addr[window] = start;
slot->io_len[window] = len;
+ return 0;
}
-
}
+
static int
-pcic_map_mem(link, haddr, start, len, flags)
+pcic_map_mem(link, bc, ioh, start, len, flags)
struct pcmcia_link *link;
- caddr_t haddr;
+ bus_chipset_tag_t bc;
+ bus_mem_handle_t ioh;
u_int start, len;
int flags;
{
- struct pcic_softc *sc = link->adapter->adapter_softc;
- struct slot *slot = &sc->slot[link->slot & 1];
vm_offset_t physaddr;
+ struct pcic_softc *sc = link->adapter->adapter_softc;
+ struct slot *slot;
+ caddr_t haddr = ioh; /* XXX */
+ if (link->slot >= sc->sc_adapter.nslots)
+ return ENXIO;
+
+ slot = &sc->slot[link->slot];
if (flags & PCMCIA_PHYSICAL_ADDR)
physaddr = (vm_offset_t) haddr;
else
physaddr = pmap_extract(pmap_kernel(), (vm_offset_t) haddr);
if (DEBUG(PCDMEM))
- printf("pcic_map_mem %x %x %x %x %x\n", haddr, physaddr,
+ printf("pcic_map_mem %p %lx %x %x %x\n", haddr, physaddr,
start, len, flags);
(u_long) physaddr >>= 12;
@@ -491,7 +675,7 @@ pcic_map_mem(link, haddr, start, len, flags)
offs = (start - (u_long) physaddr) & 0x3fff;
if (DEBUG(PCDMEM))
- printf("mapmem 2:%x %x %x\n", offs, physaddr + offs,
+ printf("mapmem 2:%x %lx %x\n", offs, physaddr + offs,
start);
stop = (u_long) physaddr + len;
@@ -503,7 +687,7 @@ pcic_map_mem(link, haddr, start, len, flags)
(u_long) physaddr & 0xff);
pcic_wr(slot, winid | PCIC_START | PCIC_ADDR_HIGH,
(((u_long) physaddr >> 8) & 0x3f) |
- /* PCIC_ZEROWS|/* */
+ /* PCIC_ZEROWS| */
((flags & PCMCIA_MAP_16) ? PCIC_DATA16 : 0));
pcic_wr(slot, winid | PCIC_END | PCIC_ADDR_LOW,
@@ -527,8 +711,6 @@ pcic_map_mem(link, haddr, start, len, flags)
delay(1000);
return 0;
} else {
- u_int offs;
- u_int stop;
int window;
int winid;
@@ -571,20 +753,24 @@ pcic_map_mem(link, haddr, start, len, flags)
return 0;
}
}
+
static int
pcic_map_intr(link, irq, flags)
struct pcmcia_link *link;
int irq, flags;
{
struct pcic_softc *sc = link->adapter->adapter_softc;
- struct slot *slot = &sc->slot[link->slot & 1];
+ struct slot *slot;
+ if (link->slot >= sc->sc_adapter.nslots)
+ return ENXIO;
+
+ slot = &sc->slot[link->slot];
if (DEBUG(PCDINTR))
printf("pcic_map_intr %x %x\n", irq, flags);
if (flags & PCMCIA_UNMAP) {
- slot->irq &= ~PCIC_INT_MASK;
- slot->irq |= sc->sc_pcic_irq | PCIC_INTR_ENA;
+ slot->irq &= ~(PCIC_INT_MASK|PCIC_INTR_ENA);
pcic_wr(slot, PCIC_INT_GEN, slot->irq);
}
else {
@@ -592,8 +778,8 @@ pcic_map_intr(link, irq, flags)
return EINVAL;
if(irq==2)
irq=9;
- slot->irq = (slot->irq & PCIC_INT_FLAGMASK) |
- irq | PCIC_INTR_ENA;
+ slot->irq &= ~(PCIC_INTR_ENA|PCIC_INT_MASK);
+ slot->irq |= irq | PCIC_CARDRESET; /* reset is inverted */
pcic_wr(slot, PCIC_INT_GEN, slot->irq);
}
return 0;
@@ -608,7 +794,11 @@ pcic_service(link, opcode, arg, flags)
int flags;
{
struct pcic_softc *sc = link->adapter->adapter_softc;
- struct slot *slot = &sc->slot[link->slot & 1];
+ struct slot *slot;
+ if (link->slot >= sc->sc_adapter.nslots)
+ return ENXIO;
+
+ slot = &sc->slot[link->slot];
slot->link = link; /* save it for later :) */
switch (opcode) {
@@ -656,7 +846,10 @@ pcic_service(link, opcode, arg, flags)
if (DEBUG(PCDSERV))
printf("pcic_service(reset)\n");
- slot->irq |= flags ? PCIC_IOCARD : 0;
+ if (flags)
+ slot->irq |= PCIC_IOCARD;
+ else
+ slot->irq &= ~PCIC_IOCARD; /* XXX? */
pcic_wr(slot, PCIC_POWER, slot->pow &= ~PCIC_DISRST);
slot->irq &= ~PCIC_CARDRESET;
pcic_wr(slot, PCIC_INT_GEN, slot->irq);
@@ -683,7 +876,8 @@ pcic_service(link, opcode, arg, flags)
printf("pcic_service(power): ");
if (flags & PCMCIA_POWER_ON) {
int nv = (PCIC_DISRST|PCIC_OUTENA);
- pcic_wr(slot, PCIC_INT_GEN, slot->irq = 0);
+ pcic_wr(slot, PCIC_INT_GEN,
+ slot->irq = PCIC_IOCARD);
if(flags & PCMCIA_POWER_3V)
nv |= PCIC_VCC3V;
if(flags & PCMCIA_POWER_5V)
@@ -731,3 +925,136 @@ pcic_service(link, opcode, arg, flags)
return EINVAL;
}
}
+
+/*
+ * Handle I/O space mapping for children. Thin layer.
+ */
+int
+pcicmaster_probe(parent, self, aux)
+ struct device *parent;
+ void *self;
+ void *aux;
+{
+ struct pcicmaster_softc *pcicm = self;
+ struct isa_attach_args *ia = aux;
+ struct cfdata *cf = pcicm->sc_dev.dv_cfdata;
+ bus_chipset_tag_t bc;
+ bus_io_handle_t ioh;
+
+ u_int chip_inf = 0;
+ int i, j;
+ int rval = 0;
+ struct pcic_softc pcic; /* faked up for probing only */
+
+ if (DEBUG(PCDCONF)) {
+ printf("pcicmaster_probe\n");
+ delay(2000000);
+ }
+ bc = ia->ia_bc;
+ if (bus_io_map(bc, ia->ia_iobase, PCIC_NPORTS, &ioh))
+ return (0);
+ /*
+ * Probe the slots for each of the possible child controllers,
+ * and if any are there we return a positive indication.
+ */
+ pcic.sc_ioh = ioh;
+ for (i = 0; i < 2; i++) {
+ bzero(pcic.slot, sizeof(pcic.slot));
+ pcic.slot[0].chip = &pcic;
+ pcic.slot[0].reg_off = i * 0x80;
+ chip_inf = pcic_rd(&pcic.slot[0], PCIC_ID_REV);
+ switch (chip_inf) {
+ case PCIC_INTEL0:
+ case PCIC_INTEL1:
+ case PCIC_IBM1:
+ case PCIC_146FC6:
+ case PCIC_146FC7:
+ case PCIC_IBM2:
+ if (DEBUG(PCDCONF)) {
+ printf("pcicmaster_probe found, cf=%p\n", cf);
+ delay(2000000);
+ }
+ pcicm->sc_slavestate[i] = SLAVE_FOUND;
+ rval++;
+ break;
+ default:
+ pcicm->sc_slavestate[i] = SLAVE_NOTPRESENT;
+ if (DEBUG(PCDCONF)) {
+ printf("found ID %x at slave %d\n",
+ chip_inf & 0xff, i);
+ }
+ break;
+ }
+ if (pcicm->sc_slavestate[i] != SLAVE_FOUND) {
+ /* reset mappings .... */
+ pcic_wr(&pcic.slot[0], PCIC_POWER,
+ pcic.slot[0].pow=PCIC_DISRST);
+ delay(1000);
+ for (j = PCIC_INT_GEN; j < 0x40; j++) {
+ pcic_wr(&pcic.slot[0], j, 0);
+ }
+ delay(10000);
+ }
+ }
+ if (rval) {
+ ia->ia_iosize = 2;
+ pcicm->sc_bc = bc;
+ pcicm->sc_ioh = ioh;
+ } else
+ bus_io_unmap(bc, ioh, PCIC_NPORTS);
+ return rval;
+}
+
+void
+pcicmaster_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcicmaster_softc *pcicm = (void *) self;
+ struct isa_attach_args *ia = aux;
+ struct pcic_attach_args pia;
+ int i;
+ printf("\n");
+ if (DEBUG(PCDCONF)) {
+ printf("pcicmaster_attach\n");
+ delay(2000000);
+ }
+#ifdef PCMCIA_ISA_DEBUG
+ printf("pcicm %p isaaddr %p ports %x size %d irq %d drq %d maddr %x msize %x\n",
+ pcicm, ia, ia->ia_iobase, ia->ia_iosize,
+ ia->ia_irq, ia->ia_drq, ia->ia_maddr, ia->ia_msize);
+ if (DEBUG(PCDCONF))
+ delay(2000000);
+#endif
+ /* attach up to two PCICs at this I/O address */
+ for (i = 0; i < 2; i++) {
+ if (pcicm->sc_slavestate[i] == SLAVE_FOUND) {
+ pia.pia_ctlr = i;
+ /*
+ * share the I/O space and memory mapping space.
+ */
+ pia.pia_bc = pcicm->sc_bc;
+ pia.pia_ioh = pcicm->sc_ioh;
+ pia.pia_iosize = ia->ia_iosize;
+ pia.pia_drq = ia->ia_drq;
+#if 0
+ pia.pia_irq = ia->ia_irq;
+ pia.pia_irq = cf->cf_loc[0]; /* irq from master attach */
+ pia.pia_maddr = ia->ia_maddr + (ia->ia_msize / 2) * i;
+ pia.pia_msize = ia->ia_msize / 2;
+#endif
+
+ config_found(self, &pia, pcicmaster_print);
+ }
+ }
+}
+
+int
+pcicmaster_print(aux, name)
+ void *aux;
+ char *name;
+{
+ if (name != NULL)
+ printf("%s: master controller ", name);
+ return UNCONF;
+}
diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c
index 76267053725..293048e8981 100644
--- a/sys/dev/isa/wd.c
+++ b/sys/dev/isa/wd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wd.c,v 1.10 1996/04/21 22:24:40 deraadt Exp $ */
+/* $OpenBSD: wd.c,v 1.11 1996/04/29 14:17:00 hvozda Exp $ */
/* $NetBSD: wd.c,v 1.148 1996/04/11 22:30:31 cgd Exp $ */
/*
@@ -57,7 +57,8 @@
#include <dev/isa/isadmavar.h>
#include <dev/isa/wdreg.h>
-#define WAITTIME (4 * hz) /* time to wait for a completion */
+#define WAITTIME (8 * hz) /* time to wait for a completion
+ (long enough for disk spin-ups) */
#define RECOVERYTIME (hz / 2) /* time to recover from an error */
#define WDCDELAY 100
@@ -67,7 +68,7 @@
#define WDCNDELAY_DEBUG 10
#endif
-#define WDIORETRIES 5 /* number of retries before giving up */
+#define WDIORETRIES 3 /* number of retries before giving up */
#define WDUNIT(dev) DISKUNIT(dev)
#define WDPART(dev) DISKPART(dev)
@@ -587,7 +588,7 @@ loop:
wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
} else {
#ifdef WDDEBUG
- printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts));
+ printf(" %d)%x", wd->sc_skip, inb(wdc->sc_iobase+wd_altsts));
#endif
}
@@ -696,7 +697,7 @@ loop:
#ifdef WDDEBUG
printf("sector %d cylin %d head %d addr %x sts %x\n", sector,
- cylin, head, bp->b_data, inb(wd->sc_iobase+wd_altsts));
+ cylin, head, bp->b_data, inb(wdc->sc_iobase+wd_altsts));
#endif
} else if (wd->sc_nblks > 1) {
/* The number of blocks in the last stretch may be smaller. */
@@ -743,11 +744,9 @@ wdcintr(arg)
struct wd_softc *wd;
struct buf *bp;
- if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
- /* Clear the pending interrupt and abort. */
- (void) inb(wdc->sc_iobase+wd_status);
+ if ((wdc->sc_flags & WDCF_ACTIVE) == 0)
+ /* leave it alone if we didn't ask for this interrupt */
return 0;
- }
wdc->sc_flags &= ~WDCF_ACTIVE;
untimeout(wdctimeout, wdc);
@@ -756,7 +755,7 @@ wdcintr(arg)
bp = wd->sc_q.b_actf;
#ifdef WDDEBUG
- printf("I%d ", ctrlr);
+ printf("I%s ", wdc->sc_dev.dv_xname);
#endif
if (wait_for_unbusy(wdc) < 0) {
@@ -781,7 +780,6 @@ wdcintr(arg)
/* Have we an error? */
if (wdc->sc_status & WDCS_ERR) {
- lose:
#ifdef WDDEBUG
wderror(wd, NULL, "wdcintr");
#endif
@@ -795,8 +793,9 @@ wdcintr(arg)
goto bad;
#endif
- if (++wdc->sc_errors < WDIORETRIES)
- goto restart;
+ wdcunwedge(wdc);
+ if (wdc->sc_errors < WDIORETRIES)
+ return 1;
wderror(wd, bp, "hard error");
bad:
diff --git a/sys/dev/pcmcia/files.pcmcia b/sys/dev/pcmcia/files.pcmcia
index 3429486e007..a32bef3b0e6 100644
--- a/sys/dev/pcmcia/files.pcmcia
+++ b/sys/dev/pcmcia/files.pcmcia
@@ -1,14 +1,21 @@
-# $OpenBSD: files.pcmcia,v 1.3 1996/04/21 22:25:58 deraadt Exp $
+# $OpenBSD: files.pcmcia,v 1.4 1996/04/29 14:17:10 hvozda Exp $
+# $Id: files.pcmcia,v 1.4 1996/04/29 14:17:10 hvozda Exp $
#
-# Config file and device description for machine-independent PCMCIA code.
+# 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: isa
-attach pcmcia at pcicbus
+#
+# needs all the parameters available on isa, so devices can attach here.
+#
+
+device pcmcia {[port = -1], [size = 0],
+ [iomem = -1], [iosiz = 0],
+ [irq = -1], [drq = -1], [slot = -1]}
+attach pcmcia at pcmciabus
-file dev/pcmcia/pcmcia.c pcmcia needs-count
+file dev/pcmcia/pcmcia.c pcmcia needs-flag
file dev/pcmcia/pcmcia_conf.c pcmcia
diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c
index 7729774be59..f37de3ef3a4 100644
--- a/sys/dev/pcmcia/pcmcia.c
+++ b/sys/dev/pcmcia/pcmcia.c
@@ -1,4 +1,6 @@
+/* $Id: pcmcia.c,v 1.3 1996/04/29 14:17:15 hvozda Exp $ */
/*
+ * Copyright (c) 1996 John T. Kohl. All rights reserved.
* Copyright (c) 1994 Stefan Grefen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,9 +29,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcmcia.c,v 1.2 1996/01/26 21:27:31 hvozda Exp $
*/
+/* 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>
@@ -39,15 +46,13 @@
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/cpu.h>
-#include <dev/pcmcia/pcmcia.h>
-#include <dev/pcmcia/pcmciabus.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciareg.h>
#include <dev/pcmcia/pcmcia_ioctl.h>
-#include "ed.h"
-#include "com.h"
-#include "ep.h"
-
#ifdef IBM_WD
#define PCMCIA_DEBUG
#endif
@@ -57,107 +62,57 @@
# define PPRINTF(a)
#endif
-static void pcmciadumpcf __P((struct pcmcia_conf *));
-static int pcmcia_strcmp __P((char *, char *, int, char *));
-
-void pcmcia_shuthook __P((void *));
-
-static struct pcmcia_adapter pcmcia_drivers[4];
-static int pcmcia_cntrl = 0;
-static int probed = 0;
-static struct device **deldevs = NULL;
-static int ndeldevs = 0;
-
-/* I've decided to re-ifdef these. It makes making a kernel easier
- until I either get config(8) modified to deal somehow
- or figure out a better to way declare the prototypes and
- build up the knowndevs struct. Stefan may have ideas...
-*/
-
-#if NED > 0
-extern struct pcmciadevs pcmcia_ed_devs[];
-#endif
-#if NCOM > 0
-extern struct pcmciadevs pcmcia_com_devs[];
-#endif
-#if NEP > 0
-extern struct pcmciadevs pcmcia_ep_devs[];
-#endif
-
-static struct pcmciadevs *knowndevs[] = {
-#if NED > 0
- pcmcia_ed_devs,
-#endif
-#if NCOM > 0
- pcmcia_com_devs,
-#endif
-#if NEP > 0
- pcmcia_ep_devs,
+#ifdef PCMCIA_DEBUG
+void pcmciadumpcf __P((struct pcmcia_conf *));
#endif
- NULL
-};
-#ifdef notyet
-static struct pcmciadevs *knowndevs[10] = { NULL };
-#define KNOWNSIZE (sizeof(knowndevs) / sizeof(knowndevs[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))
-#define PCMCIA_MAP_MEM(a,b,c,d,e,f) ((a)->chip_link->pcmcia_map_mem(b,c,d,e,f))
-
-#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)))
+/* 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) ((a)->scratch_mem)
+#define SCRATCH_MEM(a) ((a)->scratch_memh)
+#define SCRATCH_BC(a) ((a)->pa_bc)
#define SCRATCH_SIZE(a) ((a)->scratch_memsiz)
#define SCRATCH_INUSE(a)((a)->scratch_inuse)
/*
* Declarations
*/
-struct pcmciadevs *pcmcia_probedev __P((struct pcmcia_link *));
-struct pcmciadevs *pcmcia_selectdev __P((char *, char *, char *, char *));
-int pcmcia_probe_bus __P((struct pcmcia_link *, int, int,
- struct pcmcia_conf *));
+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 *));
-struct cfdriver pcmciabuscd = {
- NULL, "pcmcia", pcmciabusmatch, pcmciabusattach, DV_DULL,
- sizeof(struct pcmciabus_softc), 1
-};
-
-#ifdef notyet
-int
-pcmcia_add_device(devs)
- struct pcmciadevs *devs;
-{
- int i;
-
- if (devs == NULL)
- return 0;
+int pcmcia_unconfigure __P((struct pcmcia_link *));
+int pcmcia_unmapcard __P((struct pcmcia_link *));
- for (i = 0; i < KNOWNSIZE; i++)
- if (knowndevs[i] == NULL)
- break;
+int pcmcia_print __P((void *, char *));
+int pcmcia_submatch __P((struct device *, void *, void *));
+void pcmcia_probe_link __P((struct pcmcia_link *));
- if (i == KNOWNSIZE)
- panic("Too many pcmcia devices");
+struct cfattach pcmcia_ca = {
+ sizeof(struct pcmciabus_softc), pcmciabusmatch, pcmciabusattach,
+};
- knowndevs[i] = devs;
- for (; devs->devname != NULL; devs++)
- printf("added %s\n", devs->devname);
- return i;
-}
-#endif
+struct cfdriver pcmcia_cd = {
+ NULL, "pcmcia", DV_DULL, 1
+};
+#if 0
int
pcmcia_register(adapter_softc, bus_link, chip_link, slot)
void *adapter_softc;
@@ -178,6 +133,7 @@ pcmcia_register(adapter_softc, bus_link, chip_link, slot)
}
return 0;
}
+#endif
int
pcmciabusmatch(parent, self, aux)
@@ -187,18 +143,16 @@ pcmciabusmatch(parent, self, aux)
{
struct pcmciabus_softc *sc = (void *)self;
struct cfdata *cf = sc->sc_dev.dv_cfdata;
- int i, found = 0;
+ struct pcmciabus_attach_args *pba = aux;
+ struct pcmcia_adapter *pca = pba->pba_aux;
+ int found = 0;
- PPRINTF(("- pcmciabusmatch\n"));
- if (pcmcia_cntrl <= 0)
- return 0;
+ PPRINTF(("- pcmciabusmatch %p %p\n", pba, pca));
- for (i = 0; i < 4; i++)
- if (pcmcia_drivers[i].bus_link) {
- if (PCMCIA_BUS_INIT(&pcmcia_drivers[i], parent, cf,
- aux, &pcmcia_drivers[i], 0))
- found++;
- }
+ if (pca->bus_link) {
+ if (PCMCIA_BUS_INIT(pca, parent, cf, aux, pca, 0))
+ found++;
+ }
return found != 0;
}
@@ -214,19 +168,18 @@ pcmciabusattach(parent, self, aux)
{
struct pcmciabus_softc *sc = (struct pcmciabus_softc *) self;
struct cfdata *cf = self->dv_cfdata;
- int i, found = 0;
+ struct pcmciabus_attach_args *pba = aux;
+ struct pcmcia_adapter *pca = pba->pba_aux;
PPRINTF(("- pcmciabusattach\n"));
- for (i = 0; i < 4; i++)
- if (pcmcia_drivers[i].bus_link) {
- if (PCMCIA_BUS_INIT(&pcmcia_drivers[i], parent, cf,
- aux, &pcmcia_drivers[i], 1))
- found++;
- }
-
+ if (pca->bus_link) {
+ PCMCIA_BUS_INIT(pca, parent, cf, aux, pca, 1);
+ }
printf("\n");
- pcmcia_probe_bus(NULL, sc->sc_dev.dv_unit, -1, NULL);
+ sc->sc_driver = pca;
+ sc->sc_bc = pba->pba_bc;
+ pcmcia_probe_bus(sc->sc_dev.dv_unit, -1);
}
/*
@@ -239,52 +192,52 @@ pcmcia_probe_busses(bus, slot)
{
PPRINTF(("- pcmcia_probe_busses\n"));
if (bus == -1) {
- for (bus = 0; bus < pcmciabuscd.cd_ndevs; bus++)
- if (pcmciabuscd.cd_devs[bus])
- pcmcia_probe_bus(NULL, bus, slot, NULL);
+ 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(NULL, bus, slot, NULL);
+ return pcmcia_probe_bus(bus, slot);
}
}
+/* 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(link, bus, slot, cf)
- struct pcmcia_link *link;
+pcmcia_probe_bus(bus, slot)
int bus, slot;
- struct pcmcia_conf *cf;
{
struct pcmciabus_softc *pcmcia;
- int maxslot, minslot, maxlun, minlun;
- struct pcmciadevs *bestmatch = NULL;
- int spec_probe = (link != NULL);
+ int maxslot, minslot;
+ struct pcmcia_link *link;
PPRINTF(("- pcmcia_probe_bus\n"));
- if (bus < 0 || bus >= pcmciabuscd.cd_ndevs)
+ if (bus < 0 || bus >= pcmciabus_cd.cd_ndevs)
return ENXIO;
- pcmcia = pcmciabuscd.cd_devs[bus];
- if (!pcmcia)
+ pcmcia = pcmciabus_cd.cd_devs[bus];
+ if (!pcmcia || pcmcia->sc_driver == NULL) /* bus is not configured */
return ENXIO;
if (slot == -1) {
- maxslot = 7;
+ maxslot = pcmcia->sc_driver->nslots - 1;
minslot = 0;
} else {
- if (slot < 0 || slot > 7)
+ if (slot < 0 || slot >= pcmcia->sc_driver->nslots)
return EINVAL;
maxslot = minslot = slot;
}
for (slot = minslot; slot <= maxslot; slot++) {
- if (link = pcmcia->sc_link[slot]) {
+ if ((link = pcmcia->sc_link[slot])) {
if (link->devp)
continue;
}
- if (pcmcia_drivers[slot >> 1].adapter_softc == NULL)
- continue;
/*
* If we presently don't have a link block
@@ -297,88 +250,91 @@ pcmcia_probe_bus(link, bus, slot, cf)
return ENOMEM;
bzero(link, sizeof(*link));
link->opennings = 1;
- link->adapter = &pcmcia_drivers[slot >> 1];
+ link->adapter = pcmcia->sc_driver;
+ link->bus = pcmcia;
link->slot = slot;
}
- bestmatch = pcmcia_probedev(link);
- /*
- * We already know what the device is. We use a
- * special matching routine which insists that the
- * cfdata is of the right type rather than putting
- * more intelligence in individual match routines for
- * each high-level driver.
- * We must have the final probe do all of the comparisons,
- * or we could get stuck in an infinite loop trying the same
- * device repeatedly. We use the `fordriver' field of
- * the pcmcia_link for now, rather than inventing a new
- * structure just for the config_search().
- */
- if (link->fordriver == NULL) {
- if (bestmatch)
- link->fordriver = bestmatch->devname;
- else {
- if (!spec_probe) {
- link->device = NULL;
- link->devp = NULL;
- PCMCIA_SERVICE(link->adapter,
- link, PCMCIA_OP_POWER,
- 0, 0);
- }
- }
- }
+ (void) pcmcia_probe_link(link);
+ }
+ return 0;
+}
- if (spec_probe) {
- if (cf && pcmcia_mapcard(link, -1, cf) != 0)
- link->fordriver = NULL;
- }
+void
+pcmcia_probe_link(link)
+ struct pcmcia_link *link;
+{
+ struct pcmcia_cardinfo cardinfo;
+ struct pcmcia_attach_args paa;
+ struct pcmciabus_softc *pcmcia = link->bus;
+ int i;
- if (link->fordriver != NULL) {
- int i;
- struct device **delp = deldevs;
- int found = 0;
- link->device = bestmatch;
- link->flags = (link->flags &
- ~(PCMCIA_ATTACH_TYPE)) |
- PCMCIA_REATTACH;
- for (i = 0; i < ndeldevs; i++, delp++) {
- if (*delp &&
- pcmcia_configure((*delp)->dv_parent, *delp,
- link)) {
- link->flags = (link->flags &
- ~PCMCIA_ATTACH_TYPE)
- | PCMCIA_SLOT_INUSE;
- found = 1;
- *delp = NULL;
- break;
- }
- }
- if (!found) {
- link->flags = (link->flags &
- ~PCMCIA_ATTACH_TYPE) | PCMCIA_ATTACH;
- if (PCMCIA_BUS_SEARCH(link->adapter,
- &pcmcia->sc_dev,
- link, NULL)) {
- link->flags = (link->flags &
- ~PCMCIA_ATTACH_TYPE)
- | PCMCIA_SLOT_INUSE;
- } else {
- link->flags &= ~(PCMCIA_ATTACH_TYPE |
- PCMCIA_SLOT_INUSE);
- link->device = NULL;
- printf(
- "No matching config entry %s.\n",
- link->fordriver ?
- link->fordriver : "(NULL)");
- if (!spec_probe)
- PCMCIA_SERVICE(link->adapter,
- link,
- PCMCIA_OP_POWER,
- 0, 0);
- }
+ PPRINTF(("- pcmcia_probe_link %p\n", link));
+ /*
+ * Set up card and fetch card info.
+ */
+ 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;
+ }
+
+ /*
+ * 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;
}
}
}
- return 0;
+
+
+ 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);
+
+ /* 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.
+ */
+ (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;
}
/*
@@ -386,16 +342,13 @@ pcmcia_probe_bus(link, bus, slot, cf)
* it is, and find the correct driver table
* entry.
*/
-struct pcmciadevs *
-pcmcia_probedev(link)
+int
+pcmcia_probedev(link, cardinfo)
struct pcmcia_link *link;
+ struct pcmcia_cardinfo *cardinfo;
{
struct pcmcia_adapter *pca = link->adapter;
u_char scratch[CIS_MAXSIZE];
- char manu[MAX_CIS_NAMELEN];
- char model[MAX_CIS_NAMELEN];
- char add_inf1[MAX_CIS_NAMELEN];
- char add_inf2[MAX_CIS_NAMELEN];
int card_stat;
int err;
int pow = 0;
@@ -403,22 +356,22 @@ pcmcia_probedev(link)
PPRINTF(("- pcmcia_probe_dev\n"));
- printf("%s slot %d:",
- ((struct device *) link->adapter->adapter_softc)->dv_xname,
- slot & 1);
+ 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 ((card_stat & PCMCIA_CARD_PRESENT) == 0) {
- printf(" <slot empty>\n");
+ if (ISSET(card_stat, PCMCIA_CARD_PRESENT) == 0) {
+ printf("is empty\n");
return NULL;
}
- if (!(card_stat & PCMCIA_POWER)) {
+ if (!ISSET(card_stat, PCMCIA_POWER)) {
pow = 1;
if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 10000,
PCMCIA_POWER_ON|
@@ -428,7 +381,7 @@ pcmcia_probedev(link)
}
}
- if (!(link->flags & (PCMCIA_SLOT_INUSE | CARD_IS_MAPPED))) {
+ 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);
@@ -446,127 +399,25 @@ pcmcia_probedev(link)
}
if ((err = pcmcia_get_cisver1(link, scratch, sizeof(scratch),
- manu, model, add_inf1,
- add_inf2)) != 0) {
+ cardinfo->manufacturer,
+ cardinfo->model, cardinfo->add_info1,
+ cardinfo->add_info2)) != 0) {
printf("failed to get cis info %d\n", err);
goto bad;
}
- printf(" <%s, %s", manu, model);
- if (add_inf1[0])
- printf(", %s", add_inf1);
- if (add_inf2[0])
- printf(", %s", add_inf2);
+ printf("contains <%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");
-
- /*
- * Try make as good a match as possible with
- * available sub drivers
- */
- return pcmcia_selectdev(manu, model, add_inf1, add_inf2);
+ return 1;
bad:
if (!pow)
PCMCIA_SERVICE(pca, link, PCMCIA_OP_POWER, 0, 0);
- return NULL;
-}
-
-/*
- * Try make as good a match as possible with
- * available sub drivers
- */
-struct pcmciadevs *
-pcmcia_selectdev(manu, model, add_inf1, add_inf2)
- char *manu, *model, *add_inf1, *add_inf2;
-{
- u_int bestmatches = 0;
- struct pcmciadevs *bestmatch = (struct pcmciadevs *) 0;
- struct pcmciadevs **dlist, *dentry;
-
- PPRINTF(("- pcmcia_selectdev\n"));
- for (dlist = knowndevs; *dlist; dlist++)
- for (dentry = *dlist; dentry &&
- dentry->devname != NULL; dentry++) {
- int match = 0;
-
-#ifdef PCMCIA_DEBUG
- dentry->flags |= PC_SHOWME;
-#endif
- match|=pcmcia_strcmp(dentry->manufacturer,
- manu,dentry->flags,"manufacturer")<<6;
- match|=pcmcia_strcmp(dentry->model,
- model,dentry->flags,"model")<<4;
- match|=pcmcia_strcmp(dentry->add_inf1,
- add_inf1,dentry->flags,"info1")<<2;
- match|=pcmcia_strcmp(dentry->add_inf2,
- add_inf2,dentry->flags,"info2");
-/* the following was replaced by the wildcard function called above */
-#if 0
- if (dentry->flags & PC_SHOWME)
- printf("manufacturer = `%s'-`%s'\n",
- dentry->manufacturer ?
- dentry->manufacturer :
- "X",
- manu);
- if (dentry->manufacturer) {
- if (strcmp(dentry->manufacturer, manu) == 0) {
- match |= 8;
- } else {
- continue;
- }
- }
-
- if (dentry->flags & PC_SHOWME)
- printf("model = `%s'-`%s'\n",
- dentry->model ? dentry->model :
- "X",
- model);
- if (dentry->model) {
- if (strcmp(dentry->model, model) == 0) {
- match |= 4;
- } else {
- continue;
- }
- }
-
-
- if (dentry->flags & PC_SHOWME)
- printf("info1 = `%s'-`%s'\n",
- dentry->add_inf1 ? dentry->add_inf1 :
- "X",
- add_inf1);
- if (dentry->add_inf1) {
- if (strcmp(dentry->add_inf1, add_inf1) == 0) {
- match |= 2;
- } else {
- continue;
- }
- }
-
- if (dentry->flags & PC_SHOWME)
- printf("info2 = `%s'-`%s'\n",
- dentry->add_inf2 ? dentry->add_inf2 :
- "X",
- add_inf2);
- if (dentry->add_inf2) {
- if (strcmp(dentry->add_inf2, add_inf2) == 0) {
- match |= 1;
- } else {
- continue;
- }
- }
-#endif
-#ifdef PCMCIA_DEBUG
- printf("match == %d [%d]\n",match,bestmatches);
-#endif
-
- if(match > bestmatches) {
- bestmatches = match;
- bestmatch = dentry;
- }
- }
-
- return bestmatch;
+ return 0;
}
int
@@ -579,26 +430,29 @@ pcmcia_configure(parent, self, aux)
struct pcmcia_link *link = aux;
struct cfdata *cf = dev->dv_cfdata;
struct cfdriver *cd = cf->cf_driver;
- char *devname = (char *) link->fordriver;
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 (strcmp(devname, cd->cd_name) || !pca)
+ 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: %x\n", pcd));
- if (!(link->flags & CARD_IS_MAPPED)) {
+ 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)
@@ -615,8 +469,9 @@ pcmcia_configure(parent, self, aux)
#endif
/* and modify it (device specific) */
if (pcd && pcd->pcmcia_config) {
- PPRINTF(("pcmcia_configure: calling config\n"));
- if (pcd->pcmcia_config(link, dev, &pc_cf, cf))
+ 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) {
@@ -649,7 +504,7 @@ pcmcia_configure(parent, self, aux)
}
link->devp = dev;
- PPRINTF(("pcmcia_configure: calling bus probe\n"));
+ 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;
@@ -660,39 +515,34 @@ pcmcia_configure(parent, self, aux)
goto bad;
}
- link->shuthook = shutdownhook_establish(pcmcia_shuthook,
- (void *)link);
return 1;
bad:
link->devp = NULL;
if (mymap)
pcmcia_unmapcard(link);
- printf("pcmcia_configure: configuration error\n");
+ PPRINTF(("pcmcia_configure: configuration error\n"));
return 0;
}
void
-pcmcia_shuthook(arg)
-void *arg;
+pcmcia_detach(dev, arg)
+ struct device *dev;
+ void *arg;
{
- struct pcmcia_link *link = (struct pcmcia_link *)arg;
- if (pcmcia_unconfigure(link) == 0) {
- /*
- * turn off power too.
- */
- PCMCIA_SERVICE(link->adapter, link, PCMCIA_OP_RESET, 500000, 0);
- PCMCIA_SERVICE(link->adapter, link, PCMCIA_OP_POWER, 0, 0);
- }
+ struct pcmcia_link *link = arg;
+
+ link->devp = NULL;
+ printf("%s: device %s at slot %d detached/really\n",
+ dev->dv_parent->dv_xname,
+ dev->dv_xname, link->slot);
}
int
pcmcia_unconfigure(link)
struct pcmcia_link *link;
{
- int status;
- int i, err;
- struct device **delp;
+ int i;
struct device *dev;
struct pcmcia_adapter *pca = link->adapter;
struct pcmcia_device *pcd;
@@ -706,9 +556,9 @@ pcmcia_unconfigure(link)
else
pcd = NULL;
- if (link->flags & CARD_IS_MAPPED) {
+ if (ISSET(link->flags, CARD_IS_MAPPED)) {
if (pcd && pcd->pcmcia_remove) {
- if (pcd->pcmcia_remove(link, link->devp))
+ if ((*pcd->pcmcia_remove)(link, link->devp))
return EBUSY;
}
else {
@@ -718,39 +568,56 @@ pcmcia_unconfigure(link)
if (pcmcia_unmapcard(link) != 0)
return EBUSY;
}
- delp = deldevs;
- for (i = 0; delp && *delp && i < ndeldevs; i++, delp++)
- continue;
- if (i >= ndeldevs) {
- int sz = ndeldevs ? (ndeldevs * 2) :
- (MINALLOCSIZE / sizeof(void *));
- struct device **ndel = malloc(sz * sizeof(void *),
- M_DEVBUF, M_NOWAIT);
- if (!ndel) {
- PPRINTF(("pcmcia_delete: creating dev array"));
- return ENOMEM;
- }
- bzero(ndel, sz * sizeof(void *));
- if (ndeldevs) {
- bcopy(deldevs, ndel, ndeldevs * sizeof(void *));
- free(deldevs, M_DEVBUF);
+ 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 (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;
}
- ndeldevs = sz - 1;
- deldevs = ndel;
- delp = deldevs + i;
+ 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);
+ /*
+ * 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.
+ */
+/* dev->dv_cfdata->cf_fstate = FSTATE_NOTFOUND;*/
}
- dev = *delp = link->devp;
- link->devp = NULL;
- printf("device %s in pcmcia slot %d detached\n", dev->dv_xname,
- link->slot);
- shutdownhook_disestablish(link->shuthook);
- link->shuthook = 0;
return 0;
}
+/*
+ * Map the card into I/O and memory space, using the details provided
+ * with pc_cf.
+ */
+
int
pcmcia_mapcard(link, unit, pc_cf)
struct pcmcia_link *link;
+ int unit;
struct pcmcia_conf *pc_cf;
{
struct pcmcia_adapter *pca = link->adapter;
@@ -768,6 +635,7 @@ pcmcia_mapcard(link, unit, pc_cf)
splx(s);
for (i = 0; i < pc_cf->memwin; i++) {
if ((err = PCMCIA_MAP_MEM(pca, link,
+ pca->pa_bc,
(caddr_t) pc_cf->mem[i].start,
pc_cf->mem[i].caddr,
pc_cf->mem[i].len,
@@ -797,7 +665,7 @@ pcmcia_mapcard(link, unit, pc_cf)
}
}
/* Now we've mapped everything enable it */
- if ((err = PCMCIA_MAP_MEM(pca, link, SCRATCH_MEM(pca),
+ if ((err = PCMCIA_MAP_MEM(pca, link, SCRATCH_BC(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));
@@ -810,45 +678,59 @@ pcmcia_mapcard(link, unit, pc_cf)
goto error;
}
-#define GETMEM(x) SCRATCH_MEM(pca)[(pc_cf->cfg_off & \
- (SCRATCH_SIZE(pca) - 1)) + x]
- if ((pc_cf->cfgtype & DOSRESET)) {
- GETMEM(0) = PCMCIA_SRESET;
+#define GETMEM(x) bus_mem_read_1(pca->scratch_bc, SCRATCH_MEM(pca), \
+ (pc_cf->cfg_off & (SCRATCH_SIZE(pca)-1)) + x)
+#define PUTMEM(x,v) \
+ bus_mem_write_1(pca->scratch_bc, SCRATCH_MEM(pca), \
+ (pc_cf->cfg_off & (SCRATCH_SIZE(pca)-1)) + x, v)
+
+ if (ISSET(pc_cf->cfgtype, DOSRESET)) {
+ PUTMEM(0, PCMCIA_SRESET);
delay(50000);
}
- PPRINTF(("CMDR %x\n",((pc_cf->cfgtype & CFGENTRYID) ?
+ 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)
));
- GETMEM(0) = ((pc_cf->cfgtype & CFGENTRYID) ?
- pc_cf->cfgid |CFGENTRYID:
- (pc_cf->cfgtype & CFGENTRYMASK)|1)|
- (pc_cf->irq_level ? PCMCIA_LVLREQ : 0);
+ 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);
- if (pc_cf->cfg_regmask & (1 << (PCMCIA_SCR / 2)))
- GETMEM(PCMCIA_SCR) = (link->slot & 1) | 0x10;
+ if (ISSET(pc_cf->cfg_regmask, (1 << (PCMCIA_SCR / 2))))
+ PUTMEM(PCMCIA_SCR, (link->slot & 1) | 0x10);
#if 0
DPRINTF(("CCSR %x\n", GETMEM(PCMCIA_CCSR]));
- if (GETMEM(PCMCIA_CCSR] & PCMCIA_POWER_DOWN) {
- GETMEM(PCMCIA_CCSR] &= ~PCMCIA_POWER_DOWN;
- DPRINTF(("CCSR now %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)));
}
#endif
+
+ PPRINTF(("pcmcia_mapcard: about to initialize...\n"));
+
if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_WAIT,
- 500000, 0)) != 0)
+ 1000, 0)) != 0) {
PPRINTF(("failed to initialize %d\n", err));
+ err = 0; /* XXX */
+ }
error:
- PCMCIA_MAP_MEM(pca, link, 0, 0, 0, PCMCIA_LAST_WIN | PCMCIA_UNMAP);
+ PCMCIA_MAP_MEM(pca, link, SCRATCH_BC(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_bc,
(caddr_t) pc_cf->mem[i].start,
pc_cf->mem[i].caddr,
pc_cf->mem[i].len,
@@ -863,12 +745,12 @@ error:
PCMCIA_MAP_8)) | i | PCMCIA_UNMAP);
}
PCMCIA_MAP_INTR(pca, link, pc_cf->irq_num, PCMCIA_UNMAP);
- link->flags &= ~CARD_IS_MAPPED;
+ CLR(link->flags, CARD_IS_MAPPED);
link->iowin = 0;
link->memwin = 0;
link->intr = 0;
} else {
- link->flags |= CARD_IS_MAPPED;
+ SET(link->flags, CARD_IS_MAPPED);
link->iowin = pc_cf->iowin;
link->memwin = pc_cf->memwin;
link->intr = pc_cf->irq_num;
@@ -891,14 +773,15 @@ pcmcia_unmapcard(link)
return ENODEV;
for (i = 0; i < link->memwin; i++)
- PCMCIA_MAP_MEM(pca, link, 0, 0, 0, (i | PCMCIA_UNMAP));
+ PCMCIA_MAP_MEM(pca, link, pca->pa_bc, 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, 0, 0);
- link->flags &= ~(CARD_IS_MAPPED | PCMCIA_SLOT_INUSE);
+ 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;
@@ -906,30 +789,28 @@ pcmcia_unmapcard(link)
}
-static int
+int
pcmcia_mapcard_and_configure(link, unit, pc_cf)
struct pcmcia_link *link;
struct pcmcia_conf *pc_cf;
int unit;
{
- int err;
int mymap = 0;
+ int err;
PPRINTF(("- pcmcia_mapcard_and_configure\n"));
if (pc_cf->driver_name[0][0]) {
-#if 0
if ((err = pcmcia_mapcard(link, unit, pc_cf)) != 0) {
return err;
}
mymap=1;
-#endif
link->fordriver = pc_cf->driver_name[0];
- } else {
+ } else
link->fordriver = NULL;
- pc_cf = NULL;
- }
- pcmcia_probe_bus(link, 0, link->slot, pc_cf);
- if ((link->flags & PCMCIA_SLOT_INUSE) == 0) {
+
+ pcmcia_probe_link(link);
+
+ if (!ISSET(link->flags, PCMCIA_SLOT_INUSE)) {
if (mymap)
pcmcia_unmapcard(link);
return ENODEV;
@@ -952,7 +833,7 @@ pcmcia_read_cis(link, scratch, offs, len)
int size = SCRATCH_SIZE(pca);
volatile int *inuse = &SCRATCH_INUSE(pca);
- PPRINTF(("- pcmcia_read_cis\n"));
+ PPRINTF(("- pcmcia_read_cis: mem %p size %d\n", p, size));
if (pca == NULL)
return ENXIO;
@@ -968,15 +849,18 @@ pcmcia_read_cis(link, scratch, offs, len)
int tlen = min(len + toff, size / 2) - toff;
int i;
- if ((err = PCMCIA_MAP_MEM(pca, link, p, pgoff, size,
+ if ((err = PCMCIA_MAP_MEM(pca, link, pca->pa_bc, 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, p, 0, size,
+ PCMCIA_MAP_MEM(pca, link, pca->pa_bc, p, 0, size,
PCMCIA_LAST_WIN | PCMCIA_UNMAP);
len -= tlen;
}
@@ -986,21 +870,25 @@ error:
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&0x7)
-#define PCMCIABUS_CHIPIID(a) (a&0x3)
-#define PCMCIABUS_CHIP 0x10
-#define PCMCIABUS_BUS 0x20
+#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};
int
-pcmciabusopen(dev, flag, mode, p)
+pcmciaopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
@@ -1011,8 +899,6 @@ pcmciabusopen(dev, flag, mode, p)
struct pcmciabus_softc *pcmcia;
PPRINTF(("- pcmciabusopen\n"));
- if (pcmcia_cntrl == 0)
- return ENXIO;
switch (PCMCIABUS_DEVTYPE(unit)) {
case PCMCIABUS_BUS:
if (unit != PCMCIABUS_BUS)
@@ -1023,10 +909,11 @@ pcmciabusopen(dev, flag, mode, p)
break;
case PCMCIABUS_CHIP:
- chipid = PCMCIABUS_CHIPIID(unit);
- if (chipid > 3)
+ chipid = PCMCIABUS_CHIPID(unit);
+ if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
return ENXIO;
- if (pcmcia_drivers[chipid].adapter_softc == NULL)
+ pcmcia = pcmciabus_cd.cd_devs[chipid];
+ if (pcmcia == NULL || pcmcia->sc_driver == NULL)
return ENXIO;
if (chipopen[chipid])
@@ -1037,20 +924,22 @@ pcmciabusopen(dev, flag, mode, p)
case 0:
slot = PCMCIABUS_SLOT(unit);
- chipid = slot >> 1;
+ chipid = PCMCIABUS_CHIPNO(unit);
- if (chipid > 7)
+ if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
return ENXIO;
- if (pcmcia_drivers[chipid].adapter_softc == NULL)
+ pcmcia = pcmciabus_cd.cd_devs[chipid];
+ if (pcmcia == NULL || pcmcia->sc_driver == NULL)
return ENXIO;
- pcmcia = pcmciabuscd.cd_devs[0];
link = pcmcia->sc_link[slot];
+ if (!link)
+ return ENXIO;
- if (link->flags & PCMCIA_SLOT_OPEN)
+ if (ISSET(link->flags, PCMCIA_SLOT_OPEN))
return EBUSY;
- link->flags |= PCMCIA_SLOT_OPEN;
+ SET(link->flags, PCMCIA_SLOT_OPEN);
break;
default:
@@ -1062,7 +951,7 @@ pcmciabusopen(dev, flag, mode, p)
int
-pcmciabusclose(dev)
+pcmciaclose(dev)
{
int unit = PCMCIABUS_UNIT(dev);
int chipid, slot;
@@ -1071,25 +960,24 @@ pcmciabusclose(dev)
int s;
PPRINTF(("- pcmciabusclose\n"));
- if (pcmcia_cntrl == 0)
- return ENXIO;
switch (PCMCIABUS_DEVTYPE(unit)) {
case PCMCIABUS_BUS:
busopen = 0;
break;
case PCMCIABUS_CHIP:
- chipid = PCMCIABUS_CHIPIID(unit);
+ chipid = PCMCIABUS_CHIPID(unit);
chipopen[chipid] = 0;
break;
case 0:
slot = PCMCIABUS_SLOT(unit);
- pcmcia = pcmciabuscd.cd_devs[0];
+ chipid = PCMCIABUS_CHIPNO(unit);
+ pcmcia = pcmciabus_cd.cd_devs[chipid];
link = pcmcia->sc_link[slot];
s = splclock();
- link->flags &= ~(PCMCIA_SLOT_OPEN|PCMCIA_SLOT_EVENT);
+ CLR(link->flags, (PCMCIA_SLOT_OPEN|PCMCIA_SLOT_EVENT));
splx(s);
break;
@@ -1104,8 +992,8 @@ pcmciachip_ioctl(chipid, cmd, data)
int chipid, cmd;
caddr_t data;
{
- int err = 0;
- struct pcmcia_adapter *pca = &pcmcia_drivers[chipid];
+ 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;
@@ -1117,7 +1005,7 @@ pcmciachip_ioctl(chipid, cmd, data)
case PCMCIAIO_READ_REGS:
pi->chip = chipid;
link.adapter = pca;
- link.slot = chipid << 1;
+ link.slot = 0;
return PCMCIA_SERVICE(pca, &link, PCMCIA_OP_GETREGS,
pi->chip_data, 0);
}
@@ -1131,7 +1019,9 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
caddr_t data;
{
int err = 0;
- struct pcmcia_adapter *pca = &pcmcia_drivers[slotid >> 1];
+ 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 ||
@@ -1147,10 +1037,10 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
&pi->status, 0);
if (!err) {
- pi->status |= ((link->flags & CARD_IS_MAPPED) ?
- PCMCIA_CARD_IS_MAPPED : 0) |
- ((link->flags & PCMCIA_SLOT_INUSE) ?
- PCMCIA_CARD_INUSE : 0);
+ 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;
}
@@ -1163,7 +1053,7 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
if ((err = PCMCIA_SERVICE(pca, link, PCMCIA_OP_STATUS,
&status, 0)) != 0)
return err;
- if ((status & PCMCIA_CARD_PRESENT) == 0)
+ if (!ISSET(status, PCMCIA_CARD_PRESENT))
return ENODEV;
pi->slot = slotid;
return pcmcia_read_cis(link, pi->cis_data, 0,
@@ -1180,6 +1070,8 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
return pcmcia_unconfigure(link);
case PCMCIAIO_UNMAP:
+ if (ISSET(link->flags, PCMCIA_SLOT_INUSE))
+ return EBUSY;
return pcmcia_unmapcard(link);
case PCMCIAIO_SET_POWER:
@@ -1226,11 +1118,11 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
&status, 0);
if (err)
return err;
- if ((status & PCMCIA_CARD_PRESENT) == 0)
+ if (!ISSET(status, PCMCIA_CARD_PRESENT))
return ENODEV;
- if (status = pcmcia_read_cis(link, pi->cis_data, 0,
- CIS_MAXSIZE))
+ if ((status = pcmcia_read_cis(link, pi->cis_data, 0,
+ CIS_MAXSIZE)))
return status;
bzero(&pc_cf, sizeof(pc_cf));
@@ -1246,7 +1138,9 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
SCRATCH_INUSE(pca) = 1;
splx(s);
- if ((err = PCMCIA_MAP_MEM(pca, link, SCRATCH_MEM(pca),
+ if ((err = PCMCIA_MAP_MEM(pca, link,
+ SCRATCH_BC(pca),
+ SCRATCH_MEM(pca),
pc_cf.cfg_off &
~(SCRATCH_SIZE(pca)-1),
SCRATCH_SIZE(pca),
@@ -1264,7 +1158,9 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
}
*d++ = 0xff;
*d++ = 0xff;
- PCMCIA_MAP_MEM(pca, link, SCRATCH_MEM(pca),
+ PCMCIA_MAP_MEM(pca, link,
+ SCRATCH_BC(pca),
+ SCRATCH_MEM(pca),
0,SCRATCH_SIZE(pca),
PCMCIA_LAST_WIN|PCMCIA_UNMAP);
}
@@ -1281,49 +1177,56 @@ pcmciaslot_ioctl(link, slotid, cmd, data)
}
int
-pcmciabusioctl(dev, cmd, data, flag, p)
+pcmciaioctl(dev, cmd, data, flag, p)
dev_t dev;
int cmd;
caddr_t data;
int flag;
struct proc *p;
{
- int unit = PCMCIABUS_UNIT(dev);
+ int unit = PCMCIABUS_UNIT(dev);
+ int chipid = PCMCIABUS_CHIPNO(unit);
struct pcmciabus_softc *pcmcia;
struct pcmcia_link *link;
- PPRINTF(("- pcmciabus_ioctl\n"));
- pcmcia = pcmciabuscd.cd_devs[0];
- if (pcmcia_cntrl == 0 || pcmcia == NULL)
+ PPRINTF(("- pcmciabusioctl\n"));
+ if (chipid < 0 || chipid >= pcmciabus_cd.cd_ndevs)
return ENXIO;
+
+ pcmcia = pcmciabus_cd.cd_devs[chipid];
+ if (pcmcia == NULL)
+ return ENXIO;
+
switch (PCMCIABUS_DEVTYPE(unit)) {
#if 0
case PCMCIABUS_BUS:
- return pcmciabus_ioctl(0, cmd, data);
+ return pcmciabus_ioctl(PCMCIABUS_BUSID(unit), cmd, data);
#endif
case PCMCIABUS_CHIP:
- return pcmciachip_ioctl(PCMCIABUS_CHIPIID(unit), cmd, data);
+ return pcmciachip_ioctl(PCMCIABUS_CHIPID(unit), cmd, data);
case 0:
link = pcmcia->sc_link[PCMCIABUS_SLOT(unit)];
- return pcmciaslot_ioctl(link, PCMCIABUS_SLOT(unit), cmd, data);
+ return pcmciaslot_ioctl(link, PCMCIABUS_SLOTID(unit),
+ cmd, data);
default:
return ENXIO;
}
}
int
-pcmciabusselect(device, rw, p)
+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_ioctl\n"));
- pcmcia = pcmciabuscd.cd_devs[0];
+ PPRINTF(("- pcmciabus_select\n"));
+ pcmcia = pcmciabus_cd.cd_devs[chipid];
switch (PCMCIABUS_DEVTYPE(unit)) {
case 0:
@@ -1335,14 +1238,14 @@ pcmciabusselect(device, rw, p)
return 0;
}
- s = splclock(); /* XXX something higher than all devices that can plug in.... */
+ s = splpcmcia();
switch (rw) {
case FREAD:
case FWRITE:
break;
case 0:
- if (link->flags & PCMCIA_SLOT_EVENT) {
- link->flags &= ~PCMCIA_SLOT_EVENT;
+ if (ISSET(link->flags, PCMCIA_SLOT_EVENT)) {
+ CLR(link->flags, PCMCIA_SLOT_EVENT);
splx(s);
return 1;
}
@@ -1354,54 +1257,14 @@ pcmciabusselect(device, rw, p)
}
int
-pcmciabusmmap()
+pcmciammap()
{
return ENXIO;
}
-/* pcmcia template string match. A '*' matches any number of characters.
- A NULL template matches all strings.
- return-value
- 0 nomatch
- 1 wildcard match
- 2 excact match
- */
-static int
-pcmcia_strcmp(templ,val,flags,msg)
- char *templ;
- char *val;
- int flags;
- char *msg;
-{
- char *ltempl=NULL,*lval=NULL;
-
- if (flags & PC_SHOWME)
- printf("%s = `%s'-`%s'\n", msg, templ ? templ : "X", val);
-
- if(templ==NULL)
- return 1;
- while(*val) {
- while(*templ=='*') {
- ltempl=++templ;
- lval=val;
- }
- if(*templ==*val) {
- templ++;
- val++;
- } else {
- if(ltempl==NULL)
- return 0;
- val=++lval;
- templ=ltempl;
- }
- }
- if(*templ!=0 && *templ!='*')
- return 0;
- return ltempl?1:2;
-}
#ifdef PCMCIA_DEBUG
-static void
+void
pcmciadumpcf(cf)
struct pcmcia_conf * cf;
{
@@ -1414,6 +1277,7 @@ pcmciadumpcf(cf)
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++) {
@@ -1431,3 +1295,43 @@ pcmciadumpcf(cf)
}
}
#endif
+
+int
+pcmcia_print(aux, pnp)
+ void *aux;
+ char *pnp;
+{
+#if 0
+ struct pcmcia_attach_args *paa = aux;
+ printf(" slot %d", paa->paa_link->slot);
+#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;
+
+#if 0
+ printf("pcmcia_submatch: paa=%p link=%p, cf=%p\n", paa, link, cf);
+ delay(2000000);
+
+#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));
+}
diff --git a/sys/dev/pcmcia/pcmcia_conf.c b/sys/dev/pcmcia/pcmcia_conf.c
index ab0e5b0d741..3e09e0368bc 100644
--- a/sys/dev/pcmcia/pcmcia_conf.c
+++ b/sys/dev/pcmcia/pcmcia_conf.c
@@ -1,11 +1,50 @@
+/* $Id: pcmcia_conf.c,v 1.2 1996/04/29 14:17:21 hvozda Exp $ */
+/*
+ * Copyright (c) 1996 John T. Kohl. All rights reserved.
+ * Copyright (c) 1994 Stefan Grefen. 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 Charles Hannum.
+ * This product includes software developed by Stefan Grefen.
+ * 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.
+ *
+ */
+
+/*
+ * This file is shared between user and kernel space, so be careful with the
+ * coding conventions.
+ */
#include <errno.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/device.h>
+#include <sys/time.h>
+#include <sys/systm.h>
-#include <dev/pcmcia/pcmcia.h>
-#include <dev/pcmcia/pcmciabus.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <dev/pcmcia/pcmciareg.h>
#include <dev/pcmcia/pcmcia_ioctl.h>
#ifdef CFG_DEBUG
@@ -68,7 +107,7 @@ pcmcia_get_cf(pc_link, data, dlen, idx, pc_cf)
}
-int
+void
read_cfg_info(tbuf, len, pc_cf)
u_char *tbuf;
int len;
@@ -110,14 +149,15 @@ read_cfg_info(tbuf, len, pc_cf)
}
}
-int
+void
parse_cfent(tbuf, len, slotid, pc_cf)
u_char *tbuf;
int len;
int slotid;
struct pcmcia_conf *pc_cf;
{
- int i, idx, defp, iop, io_16, ios, ftrs, intface, k;
+ volatile int i, idx, defp, intface, k;
+ int ios, ftrs;
int host_addr_p, addr_size, len_size;
#ifdef CFG_DEBUG
@@ -164,7 +204,6 @@ parse_cfent(tbuf, len, slotid, pc_cf)
int io_16, io_block_len, io_block_size, io_lines;
int io_range;
- iop = 1;
io_lines = tbuf[i] & TPCE_FS_IO_LINES;
io_16 = tbuf[i] & TPCE_FS_IO_BUS16;
io_range = tbuf[i] &TPCE_FS_IO_RANGE;
@@ -178,6 +217,8 @@ parse_cfent(tbuf, len, slotid, pc_cf)
TPCE_FS_IO_SIZE_SHIFT;
ios = (tbuf[i] & TPCE_FS_IO_NUM) + 1;
i++;
+ elen=io_block_len+(io_block_len==3?1:0)+
+ io_block_size+(io_block_size==3?1:0);
if ((ftrs & TPCE_FS_IRQ) != 0) {
iptr=(ios * elen) + i;
#define IRQTYPE (TPCE_FS_IRQ_PULSE|TPCE_FS_IRQ_LEVEL)
@@ -249,7 +290,6 @@ parse_cfent(tbuf, len, slotid, pc_cf)
}
}
if (ftrs & TPCE_FS_IRQ) {
- int irq_mask, irqp, irq;
pc_cf->irq_level = (tbuf[i] & TPCE_FS_IRQ_LEVEL) != 0;
pc_cf->irq_pulse = (tbuf[i] & TPCE_FS_IRQ_PULSE) != 0;
pc_cf->irq_share = (tbuf[i] & TPCE_FS_IRQ_SHARE) != 0;
@@ -339,6 +379,10 @@ parse_cfent(tbuf, len, slotid, pc_cf)
mem_haddrs[j] <<= 8;
}
+ break;
+ default:
+ mems = 0;
+ break;
}
for (j = 0; j < mems; j++) {
pc_cf->mem[j].len = mem_lens[j];
@@ -384,7 +428,7 @@ parse_cfent(tbuf, len, slotid, pc_cf)
pc_cf->mem[i].start!=tmp_cf.mem[i].start)
return;
- /* *pc_cf = tmp_cf;/**/
+ /* *pc_cf = tmp_cf; */
pc_cf->cfgid = idx;
}
return;
@@ -472,6 +516,134 @@ pcmcia_get_cisver1(pc_link, data, len, manu, model, add_inf1, add_inf2)
}
p += clen + 2;
}
- printf("%x %x\n", p, end);
+#ifdef CFG_DEBUG
+ printf("get_cisver1 failed, buffer [%p,%p)\n", p, end);
+#endif
return ENODEV;
}
+
+#define NULLCP (void *)0
+
+/* pcmcia template string match. A '*' matches any number of characters.
+ A NULL template matches all strings.
+ return-value
+ 0 nomatch
+ 1 wildcard match
+ 2 excact match
+ */
+int
+pcmcia_strcmp(templ, val, flags, msg)
+ const char *templ;
+ const char *val;
+ int flags;
+ const char *msg;
+{
+ const char *ltempl = NULLCP;
+ const char *lval = NULLCP;
+
+ if (flags & PC_SHOWME)
+ printf("%s = `%s'-`%s'\n", msg, templ ? templ : "X", val);
+
+ if (templ == NULLCP) {
+ return 1;
+ }
+ while (*val) {
+ while (*templ == '*') {
+ ltempl = ++templ;
+ lval = val;
+ }
+ if (*templ == *val) {
+ templ++;
+ val++;
+ } else {
+ if (ltempl == NULLCP)
+ return 0;
+ val = ++lval;
+ templ = ltempl;
+ }
+ }
+ if (*templ != 0 && *templ != '*')
+ return 0;
+ return (ltempl ? 1 : 2);
+}
+
+/*
+ * Return a match value to estimate how good a match the specified driver
+ * is for this particular card.
+ */
+
+int
+pcmcia_matchvalue(card, dentry)
+ const struct pcmcia_cardinfo *card;
+ struct pcmciadevs *dentry;
+{
+ int match;
+
+#ifdef PCMCIA_DEBUG
+ dentry->flags |= PC_SHOWME;
+#endif
+ match = pcmcia_strcmp(dentry->manufacturer,
+ card->manufacturer,
+ dentry->flags, "manufacturer")<<6;
+ match |= pcmcia_strcmp(dentry->model,
+ card->model, dentry->flags, "model")<<4;
+ match |= pcmcia_strcmp(dentry->add_inf1,
+ card->add_info1, dentry->flags, "info1")<<2;
+ match |= pcmcia_strcmp(dentry->add_inf2,
+ card->add_info2, dentry->flags, "info2");
+#ifdef PCMCIA_DEBUG
+ printf("match == %d\n", match);
+#endif
+ return match;
+}
+
+int
+pcmcia_bestvalue(card, dentries, nentries, rmatch)
+ struct pcmcia_cardinfo *card;
+ struct pcmciadevs *dentries;
+ int nentries;
+ struct pcmciadevs **rmatch;
+{
+ int bestmatch, thismatch;
+ register int i;
+ for (i = 0, bestmatch = 0; i < nentries; i++) {
+ if ((thismatch = pcmcia_matchvalue(card, &dentries[i])) >
+ bestmatch) {
+ bestmatch = thismatch;
+ *rmatch = &dentries[i];
+ }
+ }
+ return bestmatch;
+}
+
+int
+pcmcia_slave_match(parent, match, aux, devs, ndevs)
+ struct device *parent;
+ void *match, *aux;
+ struct pcmciadevs *devs;
+ int ndevs;
+{
+ struct pcmcia_attach_args *paa = aux;
+ struct device *self = match;
+ struct pcmciadevs *devmatch;
+ int value;
+
+ if (paa->paa_link->fordriver &&
+ strcmp(paa->paa_link->fordriver,
+ self->dv_cfdata->cf_driver->cd_name))
+ return 0; /* wrong driver */
+ value = pcmcia_bestvalue(paa->paa_cardinfo, devs, ndevs, &devmatch);
+ if (value > paa->paa_bestmatch) {
+ paa->paa_bestmatch = value;
+ paa->paa_link->device = devmatch;
+#ifdef PCMCIA_DEBUG
+ printf("pcmcia_slave_match: best so far, %p->%p\n",
+ paa->paa_link, devmatch);
+ printf("pcmcia_slave_match returns %d\n", value);
+ delay(2000000);
+#endif
+ if (!paa->paa_matchonly)
+ return value;
+ }
+ return 0;
+}
diff --git a/sys/dev/pcmcia/pcmcia_ioctl.h b/sys/dev/pcmcia/pcmcia_ioctl.h
index 535e12241b7..dd8b9e6174e 100644
--- a/sys/dev/pcmcia/pcmcia_ioctl.h
+++ b/sys/dev/pcmcia/pcmcia_ioctl.h
@@ -1,3 +1,4 @@
+/* $Id: pcmcia_ioctl.h,v 1.2 1996/04/29 14:17:25 hvozda Exp $ */
/*
* Copyright (c) 1993, 1994 Stefan Grefen. All rights reserved.
*
@@ -52,8 +53,7 @@ struct pcmcia_regs {
#define PCMCIASIO_POWER_AUTO 0x7
#define PCMCIASIO_POWER_OFF 0x0
#define PCMCIAIO_CONFIGURE _IOW('s', 140, struct pcmcia_conf)
-#define PCMCIAIO_UNMAP _IOW('s', 141, int)
-#define PCMCIAIO_UNCONFIGURE _IOW('s', 142, int)
+#define PCMCIAIO_UNMAP _IO('s', 141)
+#define PCMCIAIO_UNCONFIGURE _IO('s', 142)
#define PCMCIAIO_READ_COR _IOR('s', 143, struct pcmcia_info)
#define PCMCIAIO_READ_REGS _IOWR('s', 160, struct pcmcia_regs)
-
diff --git a/sys/dev/pcmcia/pcmciareg.h b/sys/dev/pcmcia/pcmciareg.h
new file mode 100644
index 00000000000..f3f4446c37d
--- /dev/null
+++ b/sys/dev/pcmcia/pcmciareg.h
@@ -0,0 +1,136 @@
+/* $Id: pcmciareg.h,v 1.1 1996/04/29 14:17:35 hvozda Exp $ */
+/*
+ * This file was apparently first written by Stefan Grefen, although it
+ * contained no copyright notice at the time.
+ */
+#ifndef __PCMCIAREG_H__
+#define __PCMCIAREG_H__
+
+/*
+ * Configuration Registers
+ *
+ * These are the registers required by Release 2.0 of the standard
+ * (Section 4.15)
+ */
+
+/* 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. */
+
+/*
+ * CIS Tuple defines
+ */
+#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__ */
diff --git a/sys/dev/pcmcia/pcmciabus.h b/sys/dev/pcmcia/pcmciavar.h
index 4dceb987690..2e4f597b703 100644
--- a/sys/dev/pcmcia/pcmciabus.h
+++ b/sys/dev/pcmcia/pcmciavar.h
@@ -1,4 +1,6 @@
+/* $Id: pcmciavar.h,v 1.1 1996/04/29 14:17:39 hvozda Exp $ */
/*
+ * Copyright (c) 1995,1996 John T. Kohl. All rights reserved.
* Copyright (c) 1993, 1994 Stefan Grefen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,16 +28,16 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: pcmciabus.h,v 1.1 1996/01/15 00:05:13 hvozda Exp $
*/
/* derived from scsicconf.[ch] writenn by Julian Elischer et al */
-#ifndef _PCMCIA_PCMCIABUS_H_
-#define _PCMCIA_PCMCIABUS_H_ 1
+#ifndef _PCMCIA_PCMCIAVAR_H_
+#define _PCMCIA_PCMCIAVAR_H_ 1
#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
@@ -80,11 +82,11 @@ 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 *, caddr_t,
- u_int, u_int, int));
+ int (*pcmcia_map_mem) __P((struct pcmcia_link *, bus_chipset_tag_t,
+ caddr_t, u_int, u_int, int));
/*12 map interrupt */
int (*pcmcia_map_intr) __P((struct pcmcia_link *, int, int));
-/*26 power on/off etc */
+/*16 power on/off etc */
int (*pcmcia_service) __P((struct pcmcia_link *, int, void *, int));
};
@@ -94,22 +96,41 @@ struct pcmciabus_link { /* Link back to the bus we are on */
struct pcmcia_conf *, struct cfdata *));
/* Bus specific unconfigure */
int (*bus_unconfig) __P((struct pcmcia_link *));
- /* Bus specific probe */
+ /* Bus specific probe */
int (*bus_probe) __P((struct device *, void *,
- void *, struct pcmcia_link *));
+ 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));
};
+#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)))
+
+
+/*
+ * One of these goes at the front of each chip controller's softc, right
+ * after the struct device.
+ */
struct pcmcia_adapter {
struct pcmcia_funcs *chip_link;
struct pcmciabus_link *bus_link;
+ bus_chipset_tag_t pa_bc; /* bus chipset */
void * adapter_softc;
caddr_t scratch_mem; /* pointer to scratch window */
int scratch_memsiz; /* size of scratch window */
+ bus_mem_handle_t scratch_memh; /* bus memory handle */
int scratch_inuse; /* window in use */
+ int nslots; /* # of slots controlled */
};
#define PCMCIA_MAP_ATTR 0x0100 /* for memory only */
@@ -151,9 +172,9 @@ struct pcmcia_adapter {
* as well.
*/
struct pcmcia_link {
- char pcmciabus; /* the Nth pcmciabus */
- char slot; /* slot of this dev */
- char flags;
+ 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
@@ -161,17 +182,17 @@ struct pcmcia_link {
#define PCMCIA_ATTACH_TYPE (PCMCIA_ATTACH|PCMCIA_REATTACH)
#define PCMCIA_SLOT_EVENT 0x80
#define PCMCIA_SLOT_OPEN 0x40
- char opennings;
+ u_char opennings;
- char iowin;
- char memwin;
- char intr;
- char dummy;
+ 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. */
- void *devp; /* pointer to configured device */
+ struct pcmciabus_softc *bus; /* parent pcmcia bus */
+ struct device *devp; /* pointer to configured device */
void *fordriver; /* for private use by the driver */
- void *shuthook; /* shutdown hook handle */
struct selinfo pcmcialink_sel; /* for select users */
};
@@ -184,7 +205,9 @@ struct pcmcia_link {
*/
struct pcmciabus_softc {
struct device sc_dev;
- struct pcmcia_link *sc_link[8];
+ bus_chipset_tag_t sc_bc;
+ struct pcmcia_link *sc_link[4]; /* up to 4 slots per bus */
+ struct pcmcia_adapter *sc_driver;
};
struct pcmcia_conf {
@@ -233,6 +256,15 @@ struct pcmcia_device {
int (*pcmcia_remove) __P((struct pcmcia_link *, struct device *));
};
+#define MAX_CIS_NAMELEN 64 /* version info string len */
+
+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];
+};
+
struct pcmciadevs {
char *devname;
int flags; /* 1 show my comparisons during boot(debug) */
@@ -245,6 +277,24 @@ struct pcmciadevs {
struct pcmcia_device *dev;
};
+/*
+ * 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 */
+};
+
+struct pcmciabus_attach_args {
+ bus_chipset_tag_t pba_bc;
+ int pba_maddr;
+ int pba_msize;
+ void *pba_aux; /* driver specific */
+};
+
#ifdef _KERNEL
extern int pcmcia_add_device __P((struct pcmciadevs *));
extern int pcmcia_get_cf __P((struct pcmcia_link *, u_char *, int, int,
@@ -255,8 +305,23 @@ extern int pcmcia_targmatch __P((struct device *, struct cfdata *, void *));
/* 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 *));
-int parse_cfent __P((u_char *, int, int, struct pcmcia_conf *));
-int read_cfg_info __P((u_char *, int, struct pcmcia_conf *));
-void pcmcia_getstr __P((char *buf, u_char **, u_char *));
-
-#endif /* _PCMCIA_PCMCIABUS_H_ */
+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_ */