diff options
author | hvozda <hvozda@cvs.openbsd.org> | 1996-04-29 14:17:54 +0000 |
---|---|---|
committer | hvozda <hvozda@cvs.openbsd.org> | 1996-04-29 14:17:54 +0000 |
commit | 7a9ddc83f934914d39af72bf24b67290a9e5700f (patch) | |
tree | d4e40de8eec73b77be31c346455984224213ff31 /sys/dev | |
parent | fdecada6f88b495c1afc81ad3a15c0cedffa2338 (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.c | 312 | ||||
-rw-r--r-- | sys/dev/ic/i82365reg.h | 29 | ||||
-rw-r--r-- | sys/dev/isa/com.c | 312 | ||||
-rw-r--r-- | sys/dev/isa/files.isa | 47 | ||||
-rw-r--r-- | sys/dev/isa/if_ed.c | 119 | ||||
-rw-r--r-- | sys/dev/isa/if_ep.c | 123 | ||||
-rw-r--r-- | sys/dev/isa/pcmcia_isa.c | 107 | ||||
-rw-r--r-- | sys/dev/isa/pcmcia_pcic.c | 553 | ||||
-rw-r--r-- | sys/dev/isa/wd.c | 25 | ||||
-rw-r--r-- | sys/dev/pcmcia/files.pcmcia | 17 | ||||
-rw-r--r-- | sys/dev/pcmcia/pcmcia.c | 904 | ||||
-rw-r--r-- | sys/dev/pcmcia/pcmcia_conf.c | 190 | ||||
-rw-r--r-- | sys/dev/pcmcia/pcmcia_ioctl.h | 6 | ||||
-rw-r--r-- | sys/dev/pcmcia/pcmciareg.h | 136 | ||||
-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_ */ |