Pull marc-pcmcia branch down from trunk.
This commit is contained in:
parent
3664382e53
commit
c66b8643d1
156
sys/dev/pcmcia/aic_pcmcia.c
Normal file
156
sys/dev/pcmcia/aic_pcmcia.c
Normal file
@ -0,0 +1,156 @@
|
||||
/* $NetBSD: aic_pcmcia.c,v 1.2 1997/10/16 23:27:16 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsipiconf.h>
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
|
||||
#include <dev/ic/aic6360var.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
|
||||
#define PCMCIA_MANUFACTURER_ADAPTEC 0x012F
|
||||
#define PCMCIA_PRODUCT_ADAPTEC_APA1460_1 0x0001
|
||||
#define PCMCIA_PRODUCT_ADAPTEC_APA1460_2 0x0002
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int aic_pcmcia_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int aic_pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void aic_pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct aic_pcmcia_softc {
|
||||
struct aic_softc sc_aic; /* real "aic" softc */
|
||||
|
||||
/* PCMCIA-specific goo. */
|
||||
struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
|
||||
int sc_io_window; /* our i/o window */
|
||||
struct pcmcia_function *sc_pf; /* our PCMCIA function */
|
||||
void *sc_ih; /* interrupt handler */
|
||||
};
|
||||
|
||||
struct cfattach aic_pcmcia_ca = {
|
||||
sizeof(struct aic_pcmcia_softc), aic_pcmcia_match, aic_pcmcia_attach
|
||||
};
|
||||
|
||||
int
|
||||
aic_pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *cf;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
|
||||
if (pa->manufacturer == PCMCIA_MANUFACTURER_ADAPTEC) {
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_ADAPTEC_APA1460_1:
|
||||
case PCMCIA_PRODUCT_ADAPTEC_APA1460_2:
|
||||
if (pa->pf->number == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
aic_pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct aic_pcmcia_softc *psc = (void *)self;
|
||||
struct aic_softc *sc = &psc->sc_aic;
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
struct pcmcia_function *pf = pa->pf;
|
||||
|
||||
psc->sc_pf = pf;
|
||||
|
||||
for (cfe = pf->cfe_head.sqh_first; cfe; cfe = cfe->cfe_list.sqe_next) {
|
||||
if (cfe->num_memspace != 0 ||
|
||||
cfe->num_iospace != 1)
|
||||
continue;
|
||||
|
||||
if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
|
||||
cfe->iospace[0].length, 0, &psc->sc_pcioh) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cfe == 0) {
|
||||
printf(": can't alloc i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_iot = psc->sc_pcioh.iot;
|
||||
sc->sc_ioh = psc->sc_pcioh.ioh;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pf, cfe);
|
||||
if (pcmcia_function_enable(pf)) {
|
||||
printf(": function enable failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map in the io space */
|
||||
if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0, psc->sc_pcioh.size,
|
||||
&psc->sc_pcioh, &psc->sc_io_window)) {
|
||||
printf(": can't map i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aic_find(sc->sc_iot, sc->sc_ioh))
|
||||
printf(": coundn't find aic\n%s", sc->sc_dev.dv_xname);
|
||||
|
||||
printf(": APA-1460 SCSI Host Adapter\n");
|
||||
|
||||
aicattach(sc);
|
||||
|
||||
/* Establish the interrupt handler. */
|
||||
psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_BIO, aicintr, sc);
|
||||
if (psc->sc_ih == NULL)
|
||||
printf("%s: couldn't establish interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
235
sys/dev/pcmcia/com_pcmcia.c
Normal file
235
sys/dev/pcmcia/com_pcmcia.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* $NetBSD: com_pcmcia.c,v 1.2 1997/10/16 23:27:18 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994, 1995, 1996
|
||||
* Charles M. Hannum. All rights reserved.
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)com.c 7.5 (Berkeley) 5/16/91
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
|
||||
#include <dev/ic/comreg.h>
|
||||
#include <dev/ic/comvar.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
|
||||
#define PCMCIA_MANUFACTURER_3COM 0x101
|
||||
#define PCMCIA_PRODUCT_3COM_3C562 0x562
|
||||
|
||||
#define PCMCIA_MANUFACTURER_MOTOROLA 0x109
|
||||
#define PCMCIA_PRODUCT_MOTOROLA_POWER144 0x105
|
||||
|
||||
#define PCMCIA_MANUFACTURER_IBM 0xa4
|
||||
#define PCMCIA_PRODUCT_IBM_HOME_AND_AWAY 0x2e
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int com_pcmcia_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int com_pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void com_pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
void com_pcmcia_cleanup __P((void *));
|
||||
|
||||
struct com_pcmcia_softc {
|
||||
struct com_softc sc_com; /* real "com" softc */
|
||||
|
||||
/* PCMCIA-specific goo */
|
||||
struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
|
||||
int sc_io_window; /* our i/o window */
|
||||
struct pcmcia_function *sc_pf; /* our PCMCIA function */
|
||||
void *sc_ih; /* interrupt handler */
|
||||
};
|
||||
|
||||
struct cfattach com_pcmcia_ca = {
|
||||
sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach
|
||||
};
|
||||
|
||||
int
|
||||
com_pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *match;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
|
||||
if ((pa->manufacturer == PCMCIA_MANUFACTURER_3COM) &&
|
||||
(pa->product == PCMCIA_PRODUCT_3COM_3C562) &&
|
||||
(pa->pf->number == 1))
|
||||
return(1);
|
||||
|
||||
if ((pa->manufacturer == PCMCIA_MANUFACTURER_MOTOROLA) &&
|
||||
(pa->product == PCMCIA_PRODUCT_MOTOROLA_POWER144) &&
|
||||
(pa->pf->number == 0))
|
||||
return(1);
|
||||
|
||||
if ((pa->manufacturer == PCMCIA_MANUFACTURER_IBM) &&
|
||||
(pa->product == PCMCIA_PRODUCT_IBM_HOME_AND_AWAY) &&
|
||||
(pa->pf->number == 1))
|
||||
return(1);
|
||||
|
||||
/* find a cfe we can use (if it matches a standard COM port) */
|
||||
|
||||
for (cfe = pa->pf->cfe_head.sqh_first; cfe;
|
||||
cfe = cfe->cfe_list.sqe_next) {
|
||||
if (cfe->iospace[0].start == IO_COM1 ||
|
||||
cfe->iospace[0].start == IO_COM2 ||
|
||||
cfe->iospace[0].start == IO_COM3 ||
|
||||
cfe->iospace[0].start == IO_COM4)
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
com_pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct com_pcmcia_softc *psc = (void *) self;
|
||||
struct com_softc *sc = &psc->sc_com;
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
char *model;
|
||||
|
||||
psc->sc_pf = pa->pf;
|
||||
|
||||
/* find a cfe we can use */
|
||||
|
||||
for (cfe = pa->pf->cfe_head.sqh_first; cfe;
|
||||
cfe = cfe->cfe_list.sqe_next) {
|
||||
if (cfe->num_memspace != 0)
|
||||
continue;
|
||||
|
||||
if (cfe->num_iospace != 1)
|
||||
continue;
|
||||
|
||||
if (cfe->iomask == 3) {
|
||||
if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
|
||||
cfe->iospace[0].length, &psc->sc_pcioh)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
|
||||
cfe->iospace[0].length, 0, &psc->sc_pcioh)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cfe) {
|
||||
printf(": can't allocate i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_iot = psc->sc_pcioh.iot;
|
||||
sc->sc_ioh = psc->sc_pcioh.ioh;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pa->pf, cfe);
|
||||
if (pcmcia_function_enable(pa->pf))
|
||||
printf(": function enable failed\n");
|
||||
|
||||
/* turn off the bit which disables the ethernet */
|
||||
if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
|
||||
int reg;
|
||||
|
||||
reg = pcmcia_ccr_read(pa->pf, PCMCIA_CCR_OPTION);
|
||||
reg &= ~0x08;
|
||||
pcmcia_ccr_write(pa->pf, PCMCIA_CCR_OPTION, reg);
|
||||
}
|
||||
|
||||
/* map in the io space */
|
||||
|
||||
if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
|
||||
PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size,
|
||||
&psc->sc_pcioh, &psc->sc_io_window)) {
|
||||
printf(": can't map i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_iobase = -1;
|
||||
sc->sc_frequency = COM_FREQ;
|
||||
|
||||
com_attach_subr(sc);
|
||||
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_3COM_3C562:
|
||||
model = "3Com 3C562 Modem";
|
||||
break;
|
||||
case PCMCIA_PRODUCT_MOTOROLA_POWER144:
|
||||
model = "Motorola Power 14.4 Modem";
|
||||
break;
|
||||
default:
|
||||
model = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (model != NULL)
|
||||
printf(": %s\n", model);
|
||||
|
||||
/* establish the interrupt. */
|
||||
psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_SERIAL, comintr, sc);
|
||||
if (psc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
}
|
41
sys/dev/pcmcia/files.pcmcia
Normal file
41
sys/dev/pcmcia/files.pcmcia
Normal file
@ -0,0 +1,41 @@
|
||||
# Config.new file and device description for machine-independent PCMCIA code.
|
||||
# Included by ports that need it.
|
||||
|
||||
defopt PCMCIAVERBOSE
|
||||
|
||||
device pcmcia {[function = -1], [irq = -1]}
|
||||
file dev/pcmcia/pcmcia.c
|
||||
file dev/pcmcia/pcmcia_cis.c
|
||||
|
||||
# device declaration in sys/conf/files
|
||||
attach pcmcia at pcic
|
||||
|
||||
# 3Com 3c589 Ethernet and 3c562 multifunction Ethernet controllers
|
||||
# device declaration in sys/conf/files
|
||||
attach ep at pcmcia with ep_pcmcia
|
||||
file dev/pcmcia/if_ep_pcmcia.c ep_pcmcia
|
||||
|
||||
# National Semiconductor DS8390/WD83C690-based boards
|
||||
# (NE[12]000, and clones)
|
||||
attach ne at pcmcia with ne_pcmcia
|
||||
file dev/pcmcia/if_ne_pcmcia.c ne_pcmcia
|
||||
|
||||
# Adaptec APA-1460 SCSI Host Adapter
|
||||
attach aic at pcmcia with aic_pcmcia
|
||||
file dev/pcmcia/aic_pcmcia.c aic_pcmcia
|
||||
|
||||
attach com at pcmcia with com_pcmcia
|
||||
file dev/pcmcia/com_pcmcia.c com_pcmcia
|
||||
|
||||
# Digital RoamAbout / Lucent WaveLAN PCMCIA card
|
||||
device wl: arp, ether, ifnet
|
||||
attach wl at pcmcia with wl_pcmcia
|
||||
file dev/pcmcia/if_wl_pcmcia.c wl_pcmcia
|
||||
|
||||
# PCMCIA hard drive / cdrom (IDE) controller
|
||||
#attach wdc at pcmcia with wdc_pcmcia
|
||||
#file dev/pcmcia/wdc_pcmcia.c wdc_pcmcia
|
||||
|
||||
# SMC91Cxx Ethernet Controllers (i.e. Megahertz X-Jack)
|
||||
attach sm at pcmcia with sm_pcmcia
|
||||
file dev/pcmcia/if_sm_pcmcia.c sm_pcmcia
|
287
sys/dev/pcmcia/if_ep_pcmcia.c
Normal file
287
sys/dev/pcmcia/if_ep_pcmcia.c
Normal file
@ -0,0 +1,287 @@
|
||||
/* $NetBSD: if_ep_pcmcia.c,v 1.2 1997/10/16 23:27:22 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "bpfilter.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/if_inarp.h>
|
||||
#endif
|
||||
|
||||
#ifdef NS
|
||||
#include <netns/ns.h>
|
||||
#include <netns/ns_if.h>
|
||||
#endif
|
||||
|
||||
#if NBPFILTER > 0
|
||||
#include <net/bpf.h>
|
||||
#include <net/bpfdesc.h>
|
||||
#endif
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/ic/elink3var.h>
|
||||
#include <dev/ic/elink3reg.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
|
||||
#define PCMCIA_MANUFACTURER_3COM 0x101
|
||||
#define PCMCIA_PRODUCT_3COM_3C562 0x562
|
||||
#define PCMCIA_PRODUCT_3COM_3C589 0x589
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int ep_pcmcia_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int ep_pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void ep_pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
int ep_pcmcia_get_enaddr __P((struct pcmcia_tuple *, void *));
|
||||
int ep_pcmcia_enable __P((struct ep_softc *));
|
||||
void ep_pcmcia_disable __P((struct ep_softc *));
|
||||
|
||||
struct ep_pcmcia_softc {
|
||||
struct ep_softc sc_ep; /* real "ep" softc */
|
||||
|
||||
/* PCMCIA-specific goo */
|
||||
struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
|
||||
int sc_io_window; /* our i/o window */
|
||||
struct pcmcia_function *sc_pf; /* our PCMCIA function */
|
||||
};
|
||||
|
||||
struct cfattach ep_pcmcia_ca = {
|
||||
sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach
|
||||
};
|
||||
|
||||
int
|
||||
ep_pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *cf;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
|
||||
if (pa->manufacturer == PCMCIA_MANUFACTURER_3COM) {
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_3COM_3C562:
|
||||
case PCMCIA_PRODUCT_3COM_3C589:
|
||||
if (pa->pf->number == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ep_pcmcia_enable(sc)
|
||||
struct ep_softc *sc;
|
||||
{
|
||||
struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
|
||||
|
||||
/* establish the interrupt. */
|
||||
sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, epintr, sc);
|
||||
if (sc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (pcmcia_function_enable(psc->sc_pf));
|
||||
}
|
||||
|
||||
void
|
||||
ep_pcmcia_disable(sc)
|
||||
struct ep_softc *sc;
|
||||
{
|
||||
struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
|
||||
|
||||
pcmcia_function_disable(psc->sc_pf);
|
||||
|
||||
pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
|
||||
}
|
||||
|
||||
void
|
||||
ep_pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct ep_pcmcia_softc *psc = (void *) self;
|
||||
struct ep_softc *sc = &psc->sc_ep;
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
int i;
|
||||
u_int8_t myla[ETHER_ADDR_LEN];
|
||||
u_int8_t *enaddr;
|
||||
char *model;
|
||||
|
||||
psc->sc_pf = pa->pf;
|
||||
cfe = pa->pf->cfe_head.sqh_first;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pa->pf, cfe);
|
||||
if (pcmcia_function_enable(pa->pf))
|
||||
printf(": function enable failed\n");
|
||||
|
||||
sc->enabled = 1;
|
||||
/* turn off the bit which disables the modem */
|
||||
if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
|
||||
int reg;
|
||||
|
||||
reg = pcmcia_ccr_read(pa->pf, PCMCIA_CCR_OPTION);
|
||||
reg &= ~0x08;
|
||||
pcmcia_ccr_write(pa->pf, PCMCIA_CCR_OPTION, reg);
|
||||
}
|
||||
if (cfe->num_memspace != 0)
|
||||
printf(": unexpected number of memory spaces %d should be 0\n",
|
||||
cfe->num_memspace);
|
||||
|
||||
if (cfe->num_iospace != 1)
|
||||
printf(": unexpected number of I/O spaces %d should be 1\n",
|
||||
cfe->num_iospace);
|
||||
|
||||
/*
|
||||
* XXX there's a comment in the linux driver about the io address
|
||||
* having to be between 0x00 and 0x70 mod 0x100. weird.
|
||||
*/
|
||||
|
||||
if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
|
||||
bus_addr_t maxaddr = (pa->pf->sc->iobase + pa->pf->sc->iosize);
|
||||
|
||||
for (i = roundup(pa->pf->sc->iobase, 0x100); i < maxaddr;
|
||||
i += ((i % 0x100) == 0x70) ? 0x90 : 0x10) {
|
||||
if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
|
||||
0, &psc->sc_pcioh) == 0)
|
||||
break;
|
||||
}
|
||||
if (i >= maxaddr) {
|
||||
printf(": can't allocate i/o space\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
|
||||
cfe->iospace[0].length, &psc->sc_pcioh))
|
||||
printf(": can't allocate i/o space\n");
|
||||
}
|
||||
|
||||
sc->sc_iot = psc->sc_pcioh.iot;
|
||||
sc->sc_ioh = psc->sc_pcioh.ioh;
|
||||
|
||||
if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
|
||||
PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, cfe->iospace[0].length,
|
||||
&psc->sc_pcioh, &psc->sc_io_window)) {
|
||||
printf(": can't map i/o space\n");
|
||||
return;
|
||||
}
|
||||
if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
|
||||
if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla)) {
|
||||
printf(": can't read ethernet address from CIS\n");
|
||||
return;
|
||||
}
|
||||
enaddr = myla;
|
||||
} else {
|
||||
enaddr = NULL;
|
||||
}
|
||||
|
||||
sc->bustype = EP_BUS_PCMCIA;
|
||||
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_3COM_3C589:
|
||||
model = "3Com 3C589 Ethernet";
|
||||
break;
|
||||
case PCMCIA_PRODUCT_3COM_3C562:
|
||||
model = "3Com 3C562 Ethernet";
|
||||
break;
|
||||
default:
|
||||
model = "3Com Ethernet, model unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
printf(": %s\n", model);
|
||||
|
||||
sc->enable = ep_pcmcia_enable;
|
||||
sc->disable = ep_pcmcia_disable;
|
||||
|
||||
epconfig(sc, EP_CHIPSET_3C509, enaddr);
|
||||
|
||||
sc->enabled = 0;
|
||||
|
||||
pcmcia_function_disable(pa->pf);
|
||||
}
|
||||
|
||||
int
|
||||
ep_pcmcia_get_enaddr(tuple, arg)
|
||||
struct pcmcia_tuple *tuple;
|
||||
void *arg;
|
||||
{
|
||||
u_int8_t *myla = arg;
|
||||
int i;
|
||||
|
||||
/* this is 3c562 magic */
|
||||
|
||||
if (tuple->code == 0x88) {
|
||||
if (tuple->length < ETHER_ADDR_LEN)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
|
||||
myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
|
||||
myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
430
sys/dev/pcmcia/if_ne_pcmcia.c
Normal file
430
sys/dev/pcmcia/if_ne_pcmcia.c
Normal file
@ -0,0 +1,430 @@
|
||||
/* $NetBSD: if_ne_pcmcia.c,v 1.2 1997/10/16 23:27:26 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if_types.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_ether.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
|
||||
#include <dev/ic/dp8390reg.h>
|
||||
#include <dev/ic/dp8390var.h>
|
||||
|
||||
#include <dev/ic/ne2000reg.h>
|
||||
#include <dev/ic/ne2000var.h>
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int ne_pcmcia_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int ne_pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void ne_pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
int ne_pcmcia_enable __P((struct dp8390_softc *));
|
||||
void ne_pcmcia_disable __P((struct dp8390_softc *));
|
||||
|
||||
struct ne_pcmcia_softc {
|
||||
struct ne2000_softc sc_ne2000; /* real "ne2000" softc */
|
||||
|
||||
/* PCMCIA-specific goo */
|
||||
struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o information */
|
||||
int sc_asic_io_window; /* i/o window for ASIC */
|
||||
int sc_nic_io_window; /* i/o window for NIC */
|
||||
struct pcmcia_function *sc_pf; /* our PCMCIA function */
|
||||
void *sc_ih; /* interrupt handle */
|
||||
};
|
||||
|
||||
struct cfattach ne_pcmcia_ca = {
|
||||
sizeof(struct ne_pcmcia_softc), ne_pcmcia_match, ne_pcmcia_attach
|
||||
};
|
||||
|
||||
struct ne2000dev {
|
||||
char *name;
|
||||
int manufacturer;
|
||||
int product;
|
||||
char *cis1_info0;
|
||||
char *cis1_info1;
|
||||
int function;
|
||||
int enet_maddr;
|
||||
unsigned char enet_vendor[3];
|
||||
} ne2000devs[] = {
|
||||
{ "PreMax PE-200",
|
||||
0xffff, 0xffff, "PMX ", "PE-200", 0,
|
||||
0x07f0, { 0x00, 0x20, 0xe0 } },
|
||||
{ "National Semiconductor InfoMover",
|
||||
0x00a4, 0x0002, NULL, NULL, 0,
|
||||
0x0ff0, { 0x08, 0x00, 0x5a } },
|
||||
{ "DEC DEPCM-BA",
|
||||
0x0000, 0x0000, "DIGITAL", "DEPCM-XX", 0,
|
||||
0x0ff0, { 0x00, 0x00, 0xe8 } },
|
||||
/* this card might need pcic_alloc_iobase < 0x400, and/or
|
||||
CIRRUS_PD672X on TI TravelMate 5000 needs it: */
|
||||
{ "Linksys EthernetCard",
|
||||
0x0149, 0x0265, "LINKSYS", "E-CARD",
|
||||
0, -1, { 0x00, 0x80, 0xc8 } },
|
||||
{ "Planet SmartCOM 2000",
|
||||
0xffffffff, 0xffff, "PCMCIA", "UE2212", 0,
|
||||
0xff0, { 0x00, 0x00, 0xe8 } },
|
||||
#if 0
|
||||
/* the rest of these are stolen from the linux pcnet pcmcia device
|
||||
driver. Since I don't know the manfid or cis info strings for
|
||||
any of them, they're not compiled in until I do. */
|
||||
|
||||
{ "Accton EN2212",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x00, 0xe8 } },
|
||||
{ "Allied Telesis LA-PCM",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x00, 0xf4 } },
|
||||
{ "APEX MultiCard",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x03f4, { 0x00, 0x20, 0xe5 } },
|
||||
{ "ASANTE FriendlyNet",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x4910, { 0x00, 0x00, 0x94 } },
|
||||
{ "Danpex EN-6200P2",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0110, { 0x00, 0x40, 0xc7 } },
|
||||
{ "DataTrek NetCard",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x20, 0xe8 } },
|
||||
{ "Dayna CommuniCard E",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0110, { 0x00, 0x80, 0x19 } },
|
||||
{ "D-Link DE-650",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0040, { 0x00, 0x80, 0xc8 } },
|
||||
{ "EP-210 Ethernet",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0110, { 0x00, 0x40, 0x33 } },
|
||||
{ "Epson EEN10B",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x00, 0x48 } },
|
||||
{ "ELECOM Laneed LD-CDWA",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x00b8, { 0x08, 0x00, 0x42 } },
|
||||
{ "Grey Cell GCS2220",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0000, { 0x00, 0x47, 0x43 } },
|
||||
{ "Hypertec Ethernet",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x01c0, { 0x00, 0x40, 0x4c } },
|
||||
{ "IBM CCAE",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x08, 0x00, 0x5a } },
|
||||
{ "IBM CCAE",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x04, 0xac } },
|
||||
{ "IBM CCAE",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x06, 0x29 } },
|
||||
{ "IBM FME",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0374, { 0x00, 0x04, 0xac } },
|
||||
{ "IBM FME",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0374, { 0x08, 0x00, 0x5a } },
|
||||
{ "I-O DATA PCLA/T",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0xa0, 0xb0 } },
|
||||
{ "Katron PE-520",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0110, { 0x00, 0x40, 0xf6 } },
|
||||
{ "Kingston KNE-PCM/x",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0xc0, 0xf0 } },
|
||||
{ "Kingston KNE-PCM/x",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0xe2, 0x0c, 0x0f } },
|
||||
{ "Kingston KNE-PC2",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0180, { 0x00, 0xc0, 0xf0 } },
|
||||
{ "Longshine LCS-8534",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0000, { 0x08, 0x00, 0x00 } },
|
||||
{ "Maxtech PCN2000",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x5000, { 0x00, 0x00, 0xe8 } },
|
||||
{ "NDC Instant-Link",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x003a, { 0x00, 0x80, 0xc6 } },
|
||||
{ "NE2000 Compatible",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0xa0, 0x0c } },
|
||||
{ "Network General Sniffer",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x00, 0x65 } },
|
||||
{ "Panasonic VEL211",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x80, 0x45 } },
|
||||
{ "RPTI EP400",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0110, { 0x00, 0x40, 0x95 } },
|
||||
{ "SCM Ethernet",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0ff0, { 0x00, 0x20, 0xcb } },
|
||||
{ "Socket EA",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x4000, { 0x00, 0xc0, 0x1b } },
|
||||
{ "Volktek NPL-402CT",
|
||||
0x0000, 0x0000, NULL, NULL, 0,
|
||||
0x0060, { 0x00, 0x40, 0x05 } },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NE2000_NDEVS (sizeof(ne2000devs) / sizeof(ne2000devs[0]))
|
||||
|
||||
#define ne2000_match(card, fct, n) \
|
||||
((((((card)->manufacturer == ne2000devs[(n)].manufacturer) && \
|
||||
((card)->product == ne2000devs[(n)].product)) || \
|
||||
((ne2000devs[(n)].cis1_info0) && (ne2000devs[(n)].cis1_info1) && \
|
||||
(strcmp((card)->cis1_info[0], ne2000devs[(n)].cis1_info0) == 0) && \
|
||||
(strcmp((card)->cis1_info[1], ne2000devs[(n)].cis1_info1) == 0))) && \
|
||||
(pa->pf->number == ne2000devs[(n)].function))? \
|
||||
&ne2000devs[(n)]:NULL)
|
||||
|
||||
int
|
||||
ne_pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *cf;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NE2000_NDEVS; i++) {
|
||||
if (ne2000_match(pa->card, pa->pf->number, i))
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ne_pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct ne_pcmcia_softc *psc = (void *) self;
|
||||
struct ne2000_softc *nsc = &psc->sc_ne2000;
|
||||
struct dp8390_softc *dsc = &nsc->sc_dp8390;
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
struct ne2000dev *ne_dev;
|
||||
struct pcmcia_mem_handle pcmh;
|
||||
bus_addr_t offset;
|
||||
int i, j, mwindow;
|
||||
u_int8_t myea[6], *enaddr = NULL;
|
||||
|
||||
psc->sc_pf = pa->pf;
|
||||
cfe = pa->pf->cfe_head.sqh_first;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Some ne2000 driver's claim to have memory; others don't.
|
||||
* Since I don't care, I don't check.
|
||||
*/
|
||||
|
||||
if (cfe->num_memspace != 1) {
|
||||
printf(": unexpected number of memory spaces "
|
||||
" %d should be 1\n", cfe->num_memspace);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cfe->num_iospace == 1) {
|
||||
if (cfe->iospace[0].length != NE2000_NPORTS) {
|
||||
printf(": unexpected I/O space configuration\n");
|
||||
return;
|
||||
}
|
||||
} else if (cfe->num_iospace == 2) {
|
||||
/*
|
||||
* Some cards report a separate space for NIC and ASIC.
|
||||
* This make some sense, but we must allocate a single
|
||||
* NE2000_NPORTS-sized chunk, due to brain damaged
|
||||
* address decoders on some of these cards.
|
||||
*/
|
||||
if ((cfe->iospace[0].length + cfe->iospace[1].length) !=
|
||||
NE2000_NPORTS) {
|
||||
printf(": unexpected I/O space configuration\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
printf(": unexpected number of i/o spaces %d"
|
||||
" should be 1 or 2\n", cfe->num_iospace);
|
||||
}
|
||||
|
||||
if (pcmcia_io_alloc(pa->pf, 0, NE2000_NPORTS, NE2000_NPORTS,
|
||||
&psc->sc_pcioh)) {
|
||||
printf(": can't alloc i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dsc->sc_regt = psc->sc_pcioh.iot;
|
||||
dsc->sc_regh = psc->sc_pcioh.ioh;
|
||||
|
||||
nsc->sc_asict = psc->sc_pcioh.iot;
|
||||
if (bus_space_subregion(dsc->sc_regt, dsc->sc_regh,
|
||||
NE2000_ASIC_OFFSET, NE2000_ASIC_NPORTS,
|
||||
&nsc->sc_asich)) {
|
||||
printf(": can't get subregion for asic\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up power management hooks. */
|
||||
dsc->sc_enable = ne_pcmcia_enable;
|
||||
dsc->sc_disable = ne_pcmcia_disable;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pa->pf, cfe);
|
||||
if (pcmcia_function_enable(pa->pf)) {
|
||||
printf(": function enable failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* some cards claim to be io16, but they're lying. */
|
||||
if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO8,
|
||||
NE2000_NIC_OFFSET, NE2000_NIC_NPORTS,
|
||||
&psc->sc_pcioh, &psc->sc_nic_io_window)) {
|
||||
printf(": can't map NIC i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16,
|
||||
NE2000_ASIC_OFFSET, NE2000_ASIC_NPORTS,
|
||||
&psc->sc_pcioh, &psc->sc_asic_io_window)) {
|
||||
printf(": can't map ASIC i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
* Read the station address from the board.
|
||||
*/
|
||||
for (i = 0; i < NE2000_NDEVS; i++) {
|
||||
if ((ne_dev = ne2000_match(pa->card, pa->pf->number, i))
|
||||
!= NULL) {
|
||||
if (ne_dev->enet_maddr >= 0) {
|
||||
if (pcmcia_mem_alloc(pa->pf,
|
||||
ETHER_ADDR_LEN * 2, &pcmh)) {
|
||||
printf("%s: can't alloc mem for"
|
||||
" enet addr\n",
|
||||
dsc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
if (pcmcia_mem_map(pa->pf, PCMCIA_MEM_ATTR,
|
||||
ne_dev->enet_maddr, ETHER_ADDR_LEN * 2,
|
||||
&pcmh, &offset, &mwindow)) {
|
||||
printf("%s: can't map mem for"
|
||||
" enet addr\n",
|
||||
dsc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
for (j = 0; j < ETHER_ADDR_LEN; j++)
|
||||
myea[j] = bus_space_read_1(pcmh.memt,
|
||||
pcmh.memh, offset + (j * 2));
|
||||
pcmcia_mem_unmap(pa->pf, mwindow);
|
||||
pcmcia_mem_free(pa->pf, &pcmh);
|
||||
enaddr = myea;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enaddr != NULL) {
|
||||
/*
|
||||
* Make sure this is what we expect.
|
||||
*/
|
||||
if (enaddr[0] != ne_dev->enet_vendor[0] ||
|
||||
enaddr[1] != ne_dev->enet_vendor[1] ||
|
||||
enaddr[2] != ne_dev->enet_vendor[2]) {
|
||||
printf("\n%s: enet addr has incorrect vendor code\n",
|
||||
dsc->sc_dev.dv_xname);
|
||||
printf("%s: (%02x:%02x:%02x should be "
|
||||
"%02x:%02x:%02x)\n", dsc->sc_dev.dv_xname,
|
||||
enaddr[0], enaddr[1], enaddr[2],
|
||||
ne_dev->enet_vendor[0],
|
||||
ne_dev->enet_vendor[1],
|
||||
ne_dev->enet_vendor[2]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: %s Ethernet\n", dsc->sc_dev.dv_xname, ne_dev->name);
|
||||
|
||||
ne2000_attach(nsc, enaddr);
|
||||
|
||||
pcmcia_function_disable(pa->pf);
|
||||
}
|
||||
|
||||
int
|
||||
ne_pcmcia_enable(dsc)
|
||||
struct dp8390_softc *dsc;
|
||||
{
|
||||
struct ne_pcmcia_softc *psc = (struct ne_pcmcia_softc *)dsc;
|
||||
|
||||
/* set up the interrupt */
|
||||
psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, dp8390_intr,
|
||||
dsc);
|
||||
if (psc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt\n",
|
||||
dsc->sc_dev.dv_xname);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (pcmcia_function_enable(psc->sc_pf));
|
||||
}
|
||||
|
||||
void
|
||||
ne_pcmcia_disable(dsc)
|
||||
struct dp8390_softc *dsc;
|
||||
{
|
||||
struct ne_pcmcia_softc *psc = (struct ne_pcmcia_softc *)dsc;
|
||||
|
||||
pcmcia_function_disable(psc->sc_pf);
|
||||
|
||||
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
|
||||
}
|
273
sys/dev/pcmcia/if_sm_pcmcia.c
Normal file
273
sys/dev/pcmcia/if_sm_pcmcia.c
Normal file
@ -0,0 +1,273 @@
|
||||
/* $NetBSD: if_sm_pcmcia.c,v 1.2 1997/10/16 23:27:28 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "bpfilter.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/if_inarp.h>
|
||||
#endif
|
||||
|
||||
#ifdef NS
|
||||
#include <netns/ns.h>
|
||||
#include <netns/ns_if.h>
|
||||
#endif
|
||||
|
||||
#if NBPFILTER > 0
|
||||
#include <net/bpf.h>
|
||||
#include <net/bpfdesc.h>
|
||||
#endif
|
||||
|
||||
#include <machine/intr.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ic/smc91cxxreg.h>
|
||||
#include <dev/ic/smc91cxxvar.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
|
||||
#define PCMCIA_MANUFACTURER_MEGAHERTZ 0x128
|
||||
#define PCMCIA_PRODUCT_MEGAHERTZ_XJACK 0x103
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int sm_pcmcia_match __P((struct device *, void *, void *));
|
||||
#else
|
||||
int sm_pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void sm_pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct sm_pcmcia_softc {
|
||||
struct smc91cxx_softc sc_smc; /* real "smc" softc */
|
||||
|
||||
/* PCMCIA-specific goo. */
|
||||
struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
|
||||
int sc_io_window; /* our i/o window */
|
||||
void *sc_ih; /* interrupt cookie */
|
||||
struct pcmcia_function *sc_pf; /* our PCMCIA function */
|
||||
};
|
||||
|
||||
struct cfattach sm_pcmcia_ca = {
|
||||
sizeof(struct sm_pcmcia_softc), sm_pcmcia_match, sm_pcmcia_attach
|
||||
};
|
||||
|
||||
int sm_pcmcia_enable __P((struct smc91cxx_softc *));
|
||||
void sm_pcmcia_disable __P((struct smc91cxx_softc *));
|
||||
|
||||
int
|
||||
sm_pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *match;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
|
||||
if (pa->manufacturer == PCMCIA_MANUFACTURER_MEGAHERTZ) {
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_MEGAHERTZ_XJACK:
|
||||
if (pa->pf->number == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
sm_pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)self;
|
||||
struct smc91cxx_softc *sc = &psc->sc_smc;
|
||||
struct pcmcia_attach_args *pa = aux;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
u_int8_t myla[ETHER_ADDR_LEN], *enaddr = NULL;
|
||||
const char *model;
|
||||
|
||||
psc->sc_pf = pa->pf;
|
||||
cfe = pa->pf->cfe_head.sqh_first;
|
||||
|
||||
/* Enable the card. */
|
||||
pcmcia_function_init(pa->pf, cfe);
|
||||
if (pcmcia_function_enable(pa->pf)) {
|
||||
printf(": function enable failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX sanity check number of mem and i/o spaces */
|
||||
|
||||
/* Allocate and map i/o space for the card. */
|
||||
if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
|
||||
cfe->iospace[0].length, &psc->sc_pcioh)) {
|
||||
printf(": can't allocate i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_bst = psc->sc_pcioh.iot;
|
||||
sc->sc_bsh = psc->sc_pcioh.ioh;
|
||||
|
||||
sc->sc_enable = sm_pcmcia_enable;
|
||||
sc->sc_disable = sm_pcmcia_disable;
|
||||
|
||||
if (pcmcia_io_map(pa->pf, (cfe->flags & PCMCIA_CFE_IO16) ?
|
||||
PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8, 0, cfe->iospace[0].length,
|
||||
&psc->sc_pcioh, &psc->sc_io_window)) {
|
||||
printf(": can't map i/o space\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pa->product) {
|
||||
case PCMCIA_PRODUCT_MEGAHERTZ_XJACK:
|
||||
model = "Megahertz X-JACK Ethernet";
|
||||
break;
|
||||
|
||||
default:
|
||||
model = "Unknown SMC91Cxx Ethernet";
|
||||
}
|
||||
printf(": %s\n", model);
|
||||
|
||||
if (pa->product == PCMCIA_PRODUCT_MEGAHERTZ_XJACK) {
|
||||
char enaddr_str[12];
|
||||
int i = 0, j;
|
||||
|
||||
/*
|
||||
* The X-JACK's Ethernet address is stored in the fourth
|
||||
* CIS info string. We need to parse it and pass it to
|
||||
* the generic layer.
|
||||
*/
|
||||
if (strlen(pa->pf->sc->card.cis1_info[3]) != 12) {
|
||||
/* Bogus address! */
|
||||
goto out;
|
||||
}
|
||||
bcopy(pa->pf->sc->card.cis1_info[3], enaddr_str, 12);
|
||||
bzero(myla, sizeof(myla));
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
/* Convert to upper case. */
|
||||
if (enaddr_str[(i * 2) + j] >= 'a' &&
|
||||
enaddr_str[(i * 2) + j] <= 'z')
|
||||
enaddr_str[(i * 2) + j] -= 'a' - 'A';
|
||||
|
||||
/* Parse the digit. */
|
||||
if (enaddr_str[(i * 2) + j] >= '0' &&
|
||||
enaddr_str[(i * 2) + j] <= '9')
|
||||
myla[i] |= enaddr_str[(i * 2) + j]
|
||||
- '0';
|
||||
else if (enaddr_str[(i * 2) + j] >= 'A' &&
|
||||
enaddr_str[(i * 2) + j] <= 'F')
|
||||
myla[i] |= enaddr_str[(i * 2) + j]
|
||||
- 'A' + 10;
|
||||
else {
|
||||
/* Bogus digit!! */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Compensate for ordering of digits. */
|
||||
if (j == 0)
|
||||
myla[i] <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (i >= 6) {
|
||||
/* Successfully parsed. */
|
||||
enaddr = myla;
|
||||
} else {
|
||||
printf("%s: unable to read MAC address from CIS\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform generic intialization. */
|
||||
smc91cxx_attach(sc, enaddr);
|
||||
|
||||
pcmcia_function_disable(pa->pf);
|
||||
}
|
||||
|
||||
int
|
||||
sm_pcmcia_enable(sc)
|
||||
struct smc91cxx_softc *sc;
|
||||
{
|
||||
struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
|
||||
|
||||
/* Establish the interrupt handler. */
|
||||
psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, smc91cxx_intr,
|
||||
sc);
|
||||
if (psc->sc_ih == NULL) {
|
||||
printf("%s: couldn't establish interrupt handler\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (pcmcia_function_enable(psc->sc_pf));
|
||||
}
|
||||
|
||||
void
|
||||
sm_pcmcia_disable(sc)
|
||||
struct smc91cxx_softc *sc;
|
||||
{
|
||||
struct sm_pcmcia_softc *psc = (struct sm_pcmcia_softc *)sc;
|
||||
|
||||
pcmcia_function_disable(psc->sc_pf);
|
||||
|
||||
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
|
||||
}
|
727
sys/dev/pcmcia/pcmcia.c
Normal file
727
sys/dev/pcmcia/pcmcia.c
Normal file
@ -0,0 +1,727 @@
|
||||
/* $NetBSD: pcmcia.c,v 1.2 1997/10/16 23:27:30 thorpej Exp $ */
|
||||
|
||||
#define PCMCIADEBUG
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_pcmciaverbose.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
/* XXX only needed for intr debugging */
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciareg.h>
|
||||
#include <dev/pcmcia/pcmciachip.h>
|
||||
#include <dev/pcmcia/pcmciavar.h>
|
||||
|
||||
#ifdef PCMCIADEBUG
|
||||
int pcmcia_debug = 0;
|
||||
#define DPRINTF(arg) if (pcmcia_debug) printf arg
|
||||
#else
|
||||
#define DPRINTF(arg)
|
||||
#endif
|
||||
|
||||
#ifdef PCMCIAVERBOSE
|
||||
int pcmcia_verbose = 1;
|
||||
#else
|
||||
int pcmcia_verbose = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
int pcmcia_match __P((struct device *, void *, void *));
|
||||
int pcmcia_submatch __P((struct device *, void *, void *));
|
||||
#else
|
||||
int pcmcia_match __P((struct device *, struct cfdata *, void *));
|
||||
int pcmcia_submatch __P((struct device *, struct cfdata *, void *));
|
||||
#endif
|
||||
void pcmcia_attach __P((struct device *, struct device *, void *));
|
||||
int pcmcia_print __P((void *, const char *));
|
||||
|
||||
int pcmcia_card_intr __P((void *));
|
||||
|
||||
struct cfdriver pcmcia_cd = {
|
||||
NULL, "pcmcia", DV_DULL
|
||||
};
|
||||
|
||||
struct cfattach pcmcia_ca = {
|
||||
sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
|
||||
};
|
||||
|
||||
int
|
||||
pcmcia_ccr_read(pf, ccr)
|
||||
struct pcmcia_function *pf;
|
||||
int ccr;
|
||||
{
|
||||
|
||||
return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
|
||||
pf->pf_ccr_offset + ccr));
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_ccr_write(pf, ccr, val)
|
||||
struct pcmcia_function *pf;
|
||||
int ccr;
|
||||
int val;
|
||||
{
|
||||
|
||||
if ((pf->ccr_mask) & (1 << (ccr / 2))) {
|
||||
bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
|
||||
pf->pf_ccr_offset + ccr, val);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
void *match;
|
||||
#else
|
||||
struct cfdata *match;
|
||||
#endif
|
||||
void *aux;
|
||||
{
|
||||
|
||||
/* if the autoconfiguration got this far, there's a socket here */
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct pcmciabus_attach_args *paa = aux;
|
||||
struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
|
||||
|
||||
printf("\n");
|
||||
|
||||
sc->pct = paa->pct;
|
||||
sc->pch = paa->pch;
|
||||
sc->iobase = paa->iobase;
|
||||
sc->iosize = paa->iosize;
|
||||
|
||||
sc->ih = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_card_attach(dev)
|
||||
struct device *dev;
|
||||
{
|
||||
struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
|
||||
struct pcmcia_function *pf;
|
||||
struct pcmcia_attach_args paa;
|
||||
int attached;
|
||||
|
||||
/*
|
||||
* this is here so that when socket_enable calls gettype, trt happens
|
||||
*/
|
||||
sc->card.pf_head.sqh_first = NULL;
|
||||
|
||||
pcmcia_chip_socket_enable(sc->pct, sc->pch);
|
||||
|
||||
pcmcia_read_cis(sc);
|
||||
|
||||
pcmcia_chip_socket_disable(sc->pct, sc->pch);
|
||||
|
||||
/*
|
||||
* bail now if the card has no functions, or if there was an error in
|
||||
* the cis.
|
||||
*/
|
||||
|
||||
if (sc->card.error)
|
||||
return (1);
|
||||
if (sc->card.pf_head.sqh_first == NULL)
|
||||
return (1);
|
||||
|
||||
if (pcmcia_verbose)
|
||||
pcmcia_print_cis(sc);
|
||||
|
||||
attached = 0;
|
||||
|
||||
for (pf = sc->card.pf_head.sqh_first; pf != NULL;
|
||||
pf = pf->pf_list.sqe_next) {
|
||||
if (pf->cfe_head.sqh_first == NULL)
|
||||
continue;
|
||||
|
||||
pf->sc = sc;
|
||||
pf->cfe = NULL;
|
||||
pf->ih_fct = NULL;
|
||||
pf->ih_arg = NULL;
|
||||
}
|
||||
|
||||
for (pf = sc->card.pf_head.sqh_first; pf != NULL;
|
||||
pf = pf->pf_list.sqe_next) {
|
||||
if (pf->cfe_head.sqh_first == NULL)
|
||||
continue;
|
||||
|
||||
paa.manufacturer = sc->card.manufacturer;
|
||||
paa.product = sc->card.product;
|
||||
paa.card = &sc->card;
|
||||
paa.pf = pf;
|
||||
|
||||
if (config_found_sm(&sc->dev, &paa, pcmcia_print,
|
||||
pcmcia_submatch)) {
|
||||
attached++;
|
||||
|
||||
DPRINTF(("%s: function %d CCR at %d "
|
||||
"offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
|
||||
sc->dev.dv_xname, pf->number,
|
||||
pf->pf_ccr_window, pf->pf_ccr_offset,
|
||||
pcmcia_ccr_read(pf, 0x00),
|
||||
pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
|
||||
pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
|
||||
pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
|
||||
pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
|
||||
}
|
||||
}
|
||||
|
||||
return (attached ? 0 : 1);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_card_detach(dev)
|
||||
struct device *dev;
|
||||
{
|
||||
/* struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
|
||||
/* don't do anything yet */
|
||||
}
|
||||
|
||||
int
|
||||
#ifdef __BROKEN_INDIRECT_CONFIG
|
||||
pcmcia_submatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct cfdata *cf = match;
|
||||
#else
|
||||
pcmcia_submatch(parent, cf, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
#endif
|
||||
struct pcmcia_attach_args *paa = aux;
|
||||
|
||||
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
|
||||
return (0);
|
||||
|
||||
return ((*cf->cf_attach->ca_match)(parent, cf, aux));
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_print(arg, pnp)
|
||||
void *arg;
|
||||
const char *pnp;
|
||||
{
|
||||
struct pcmcia_attach_args *pa = arg;
|
||||
struct pcmcia_softc *sc = pa->pf->sc;
|
||||
struct pcmcia_card *card = &sc->card;
|
||||
int i;
|
||||
|
||||
if (pnp) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (card->cis1_info[i] == NULL)
|
||||
break;
|
||||
if (i)
|
||||
printf(", ");
|
||||
printf("%s", card->cis1_info[i]);
|
||||
}
|
||||
if (i)
|
||||
printf(" ");
|
||||
printf("(manufacturer 0x%x, product 0x%x)", card->manufacturer,
|
||||
card->product);
|
||||
}
|
||||
printf(" function %d", pa->pf->number);
|
||||
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_card_gettype(dev)
|
||||
struct device *dev;
|
||||
{
|
||||
struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
|
||||
|
||||
/*
|
||||
* set the iftype to memory if this card has no functions (not yet
|
||||
* probed), or only one function, and that is memory.
|
||||
*/
|
||||
if (sc->card.pf_head.sqh_first == NULL ||
|
||||
(sc->card.pf_head.sqh_first != NULL &&
|
||||
sc->card.pf_head.sqh_first->pf_list.sqe_next == NULL &&
|
||||
(sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
|
||||
PCMCIA_IFTYPE_MEMORY)))
|
||||
return (PCMCIA_IFTYPE_MEMORY);
|
||||
else
|
||||
return (PCMCIA_IFTYPE_IO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a PCMCIA function. May be called as long as the function is
|
||||
* disabled.
|
||||
*/
|
||||
void
|
||||
pcmcia_function_init(pf, cfe)
|
||||
struct pcmcia_function *pf;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
{
|
||||
|
||||
if (pf->pf_flags & PFF_ENABLED)
|
||||
panic("pcmcia_function_init: function is enabled");
|
||||
|
||||
/* Remember which configuration entry we are using. */
|
||||
pf->cfe = cfe;
|
||||
}
|
||||
|
||||
/* Enable a PCMCIA function */
|
||||
int
|
||||
pcmcia_function_enable(pf)
|
||||
struct pcmcia_function *pf;
|
||||
{
|
||||
struct pcmcia_function *tmp;
|
||||
int reg;
|
||||
|
||||
if (pf->cfe == NULL)
|
||||
panic("pcmcia_function_enable: function not initialized");
|
||||
|
||||
if (pf->pf_flags & PFF_ENABLED) {
|
||||
/*
|
||||
* Don't do anything if we're already enabled.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase the reference count on the socket, enabling power, if
|
||||
* necessary.
|
||||
*/
|
||||
if (pf->sc->sc_enabled_count++ == 0)
|
||||
pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
|
||||
|
||||
/*
|
||||
* it's possible for different functions' CCRs to be in the same
|
||||
* underlying page. Check for that.
|
||||
*/
|
||||
|
||||
for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
|
||||
tmp = tmp->pf_list.sqe_next) {
|
||||
if ((tmp->pf_flags & PFF_ENABLED) &&
|
||||
(pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
|
||||
((pf->ccr_base + PCMCIA_CCR_SIZE) <=
|
||||
(tmp->ccr_base - tmp->pf_ccr_offset +
|
||||
tmp->pf_ccr_realsize))) {
|
||||
pf->pf_ccrt = tmp->pf_ccrt;
|
||||
pf->pf_ccrh = tmp->pf_ccrh;
|
||||
pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
|
||||
|
||||
/*
|
||||
* pf->pf_ccr_offset = (tmp->pf_ccr_offset -
|
||||
* tmp->ccr_base) + pf->ccr_base;
|
||||
*/
|
||||
pf->pf_ccr_offset =
|
||||
(tmp->pf_ccr_offset + pf->ccr_base) -
|
||||
tmp->ccr_base;
|
||||
pf->pf_ccr_window = tmp->pf_ccr_window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp == NULL) {
|
||||
if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
|
||||
goto bad;
|
||||
|
||||
if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
|
||||
PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
|
||||
&pf->pf_ccr_window)) {
|
||||
pcmcia_mem_free(pf, &pf->pf_pcmh);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
DPRINTF(("%s: function %d CCR at %d offset %lx: "
|
||||
"%x %x %x %x, %x %x %x %x, %x\n",
|
||||
pf->sc->dev.dv_xname, pf->number,
|
||||
pf->pf_ccr_window, pf->pf_ccr_offset,
|
||||
pcmcia_ccr_read(pf, 0x00),
|
||||
pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
|
||||
pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
|
||||
pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
|
||||
pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
|
||||
|
||||
reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
|
||||
reg |= PCMCIA_CCR_OPTION_LEVIREQ;
|
||||
if (pcmcia_mfc(pf->sc))
|
||||
reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
|
||||
|
||||
reg = 0;
|
||||
|
||||
if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
|
||||
reg |= PCMCIA_CCR_STATUS_IOIS8;
|
||||
if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
|
||||
reg |= PCMCIA_CCR_STATUS_AUDIO;
|
||||
/* Not really needed, since we start with 0. */
|
||||
if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN)
|
||||
reg &= ~PCMCIA_CCR_STATUS_PWRDWN;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
|
||||
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
|
||||
|
||||
pf->pf_flags |= PFF_ENABLED;
|
||||
return (0);
|
||||
|
||||
bad:
|
||||
/*
|
||||
* Decrement the reference count, and power down the socket, if
|
||||
* necessary.
|
||||
*/
|
||||
if (pf->sc->sc_enabled_count-- == 1)
|
||||
pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Disable PCMCIA function. */
|
||||
void
|
||||
pcmcia_function_disable(pf)
|
||||
struct pcmcia_function *pf;
|
||||
{
|
||||
struct pcmcia_function *tmp;
|
||||
int reg;
|
||||
|
||||
if (pf->cfe == NULL)
|
||||
panic("pcmcia_function_enable: function not initialized");
|
||||
|
||||
if ((pf->pf_flags & PFF_ENABLED) == 0) {
|
||||
/*
|
||||
* Don't do anything if we're already disabled.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* Power down the function if the card supports it. */
|
||||
if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN) {
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
|
||||
reg |= PCMCIA_CCR_STATUS_PWRDWN;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* it's possible for different functions' CCRs to be in the same
|
||||
* underlying page. Check for that. Note we mark us as disabled
|
||||
* first to avoid matching ourself.
|
||||
*/
|
||||
|
||||
pf->pf_flags &= ~PFF_ENABLED;
|
||||
for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
|
||||
tmp = tmp->pf_list.sqe_next) {
|
||||
if ((tmp->pf_flags & PFF_ENABLED) &&
|
||||
(pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
|
||||
((pf->ccr_base + PCMCIA_CCR_SIZE) <=
|
||||
(tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Not used by anyone else; unmap the CCR. */
|
||||
if (tmp == NULL) {
|
||||
pcmcia_mem_unmap(pf, pf->pf_ccr_window);
|
||||
pcmcia_mem_free(pf, &pf->pf_pcmh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement the reference count, and power down the socket, if
|
||||
* necessary.
|
||||
*/
|
||||
if (--pf->sc->sc_enabled_count == 0)
|
||||
pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
|
||||
struct pcmcia_function *pf;
|
||||
int width;
|
||||
bus_addr_t offset;
|
||||
bus_size_t size;
|
||||
struct pcmcia_io_handle *pcihp;
|
||||
int *windowp;
|
||||
{
|
||||
bus_addr_t ioaddr;
|
||||
int reg;
|
||||
|
||||
if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
|
||||
width, offset, size, pcihp, windowp))
|
||||
return (1);
|
||||
|
||||
ioaddr = pcihp->addr + offset;
|
||||
|
||||
/*
|
||||
* XXX in the multifunction multi-iospace-per-function case, this
|
||||
* needs to cooperate with io_alloc to make sure that the spaces
|
||||
* don't overlap, and that the ccr's are set correctly
|
||||
*/
|
||||
|
||||
if (pcmcia_mfc(pf->sc)) {
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioaddr & 0xff);
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioaddr >> 8) & 0xff);
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
|
||||
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
|
||||
reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *
|
||||
pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
|
||||
struct pcmcia_function *pf;
|
||||
int ipl;
|
||||
int (*ih_fct) __P((void *));
|
||||
void *ih_arg;
|
||||
{
|
||||
void *ret;
|
||||
|
||||
/* behave differently if this is a multifunction card */
|
||||
|
||||
if (pcmcia_mfc(pf->sc)) {
|
||||
int s, ihcnt, hiipl, reg;
|
||||
struct pcmcia_function *pf2;
|
||||
|
||||
/* XXX splraise() use needs to go away! */
|
||||
|
||||
/*
|
||||
* mask all the ipl's which are already used by this card,
|
||||
* and find the highest ipl number (lowest priority)
|
||||
*/
|
||||
|
||||
ihcnt = 0;
|
||||
s = 0; /* this is only here to keep the compipler
|
||||
happy */
|
||||
hiipl = 0; /* this is only here to keep the compipler
|
||||
happy */
|
||||
|
||||
for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
|
||||
pf2 = pf2->pf_list.sqe_next) {
|
||||
if (pf2->ih_fct) {
|
||||
if (ihcnt == 0) {
|
||||
s = splraise(pf2->ih_ipl);
|
||||
hiipl = pf2->ih_ipl;
|
||||
ihcnt++;
|
||||
} else {
|
||||
splraise(pf2->ih_ipl);
|
||||
if (pf2->ih_ipl > hiipl)
|
||||
hiipl = pf2->ih_ipl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set up the handler for the new function */
|
||||
|
||||
pf->ih_fct = ih_fct;
|
||||
pf->ih_arg = ih_arg;
|
||||
pf->ih_ipl = ipl;
|
||||
|
||||
/*
|
||||
* establish the real interrupt, changing the ipl if
|
||||
* necessary
|
||||
*/
|
||||
|
||||
if (ihcnt == 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pf->sc->ih != NULL)
|
||||
panic("card has intr handler, but no function does");
|
||||
#endif
|
||||
|
||||
pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
|
||||
pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
|
||||
} else if (ipl > hiipl) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pf->sc->ih == NULL)
|
||||
panic("functions have ih, but the card does not");
|
||||
#endif
|
||||
|
||||
pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
|
||||
pf->sc->ih);
|
||||
pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
|
||||
pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
|
||||
}
|
||||
if (ihcnt)
|
||||
splx(s);
|
||||
|
||||
ret = pf->sc->ih;
|
||||
|
||||
if (ret != NULL) {
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
|
||||
reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
|
||||
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
|
||||
reg |= PCMCIA_CCR_STATUS_INTRACK;
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
|
||||
}
|
||||
} else {
|
||||
ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
|
||||
pf, ipl, ih_fct, ih_arg);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_intr_disestablish(pf, ih)
|
||||
struct pcmcia_function *pf;
|
||||
void *ih;
|
||||
{
|
||||
|
||||
/* behave differently if this is a multifunction card */
|
||||
|
||||
if (pcmcia_mfc(pf->sc)) {
|
||||
int s, ihcnt, hiipl;
|
||||
struct pcmcia_function *pf2;
|
||||
|
||||
/*
|
||||
* mask all the ipl's which are already used by this card,
|
||||
* and find the highest ipl number (lowest priority). Skip
|
||||
* the current function.
|
||||
*/
|
||||
|
||||
ihcnt = 0;
|
||||
s = 0; /* this is only here to keep the compipler
|
||||
happy */
|
||||
hiipl = 0; /* this is only here to keep the compipler
|
||||
happy */
|
||||
|
||||
for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
|
||||
pf2 = pf2->pf_list.sqe_next) {
|
||||
if (pf2 == pf)
|
||||
continue;
|
||||
|
||||
if (pf2->ih_fct) {
|
||||
if (ihcnt == 0) {
|
||||
s = splraise(pf2->ih_ipl);
|
||||
hiipl = pf2->ih_ipl;
|
||||
ihcnt++;
|
||||
} else {
|
||||
splraise(pf2->ih_ipl);
|
||||
if (pf2->ih_ipl > hiipl)
|
||||
hiipl = pf2->ih_ipl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* null out the handler for this function */
|
||||
|
||||
pf->ih_fct = NULL;
|
||||
pf->ih_arg = NULL;
|
||||
|
||||
/*
|
||||
* if the ih being removed is lower priority than the lowest
|
||||
* priority remaining interrupt, up the priority.
|
||||
*/
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (ihcnt == 0) {
|
||||
panic("can't remove a handler from a card which has none");
|
||||
} else
|
||||
#endif
|
||||
if (ihcnt == 1) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pf->sc->ih == NULL)
|
||||
panic("disestablishing last function, but card has no ih");
|
||||
#endif
|
||||
pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
|
||||
pf->sc->ih);
|
||||
pf->sc->ih = NULL;
|
||||
} else if (pf->ih_ipl > hiipl) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pf->sc->ih == NULL)
|
||||
panic("changing ih ipl, but card has no ih");
|
||||
#endif
|
||||
pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
|
||||
pf->sc->ih);
|
||||
pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
|
||||
pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc);
|
||||
}
|
||||
if (ihcnt)
|
||||
splx(s);
|
||||
} else {
|
||||
pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pcmcia_card_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct pcmcia_softc *sc = arg;
|
||||
struct pcmcia_function *pf;
|
||||
int reg, ret, ret2;
|
||||
|
||||
ret = 0;
|
||||
|
||||
for (pf = sc->card.pf_head.sqh_first; pf != NULL;
|
||||
pf = pf->pf_list.sqe_next) {
|
||||
#if 0
|
||||
printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
|
||||
sc->dev.dv_xname, pf->number,
|
||||
pmap_extract(pmap_kernel(),
|
||||
(vm_offset_t) pf->ccrh) + pf->ccr_offset,
|
||||
bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
|
||||
pf->pf_ccr_offset + PCMCIA_CCR_OPTION),
|
||||
bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
|
||||
pf->pf_ccr_offset + PCMCIA_CCR_STATUS),
|
||||
bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
|
||||
pf->pf_ccr_offset + PCMCIA_CCR_PIN));
|
||||
#endif
|
||||
if (pf->ih_fct != NULL &&
|
||||
(pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
|
||||
if (reg & PCMCIA_CCR_STATUS_INTR) {
|
||||
ret2 = (*pf->ih_fct)(pf->ih_arg);
|
||||
if (ret2 != 0 && ret == 0)
|
||||
ret = ret2;
|
||||
reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
|
||||
#if 0
|
||||
printf("; csr %02x->%02x",
|
||||
reg, reg & ~PCMCIA_CCR_STATUS_INTR);
|
||||
#endif
|
||||
pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
|
||||
reg & ~PCMCIA_CCR_STATUS_INTR);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
1158
sys/dev/pcmcia/pcmcia_cis.c
Normal file
1158
sys/dev/pcmcia/pcmcia_cis.c
Normal file
File diff suppressed because it is too large
Load Diff
144
sys/dev/pcmcia/pcmciachip.h
Normal file
144
sys/dev/pcmcia/pcmciachip.h
Normal file
@ -0,0 +1,144 @@
|
||||
/* $NetBSD: pcmciachip.h,v 1.2 1997/10/16 23:27:36 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _PCMCIA_PCMCIACHIP_H_
|
||||
#define _PCMCIA_PCMCIACHIP_H_
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
struct pcmcia_function;
|
||||
struct pcmcia_mem_handle;
|
||||
struct pcmcia_io_handle;
|
||||
|
||||
/* interfaces for pcmcia to call the chipset */
|
||||
|
||||
typedef struct pcmcia_chip_functions *pcmcia_chipset_tag_t;
|
||||
typedef void *pcmcia_chipset_handle_t;
|
||||
typedef int pcmcia_mem_handle_t;
|
||||
|
||||
#define PCMCIA_MEM_ATTR 1
|
||||
#define PCMCIA_MEM_COMMON 2
|
||||
|
||||
#define PCMCIA_WIDTH_AUTO 0
|
||||
#define PCMCIA_WIDTH_IO8 1
|
||||
#define PCMCIA_WIDTH_IO16 2
|
||||
|
||||
struct pcmcia_chip_functions {
|
||||
/* memory space allocation */
|
||||
int (*mem_alloc) __P((pcmcia_chipset_handle_t, bus_size_t,
|
||||
struct pcmcia_mem_handle *));
|
||||
void (*mem_free) __P((pcmcia_chipset_handle_t,
|
||||
struct pcmcia_mem_handle *));
|
||||
|
||||
/* memory space window mapping */
|
||||
int (*mem_map) __P((pcmcia_chipset_handle_t, int, bus_addr_t,
|
||||
bus_size_t, struct pcmcia_mem_handle *,
|
||||
bus_addr_t *, int *));
|
||||
void (*mem_unmap) __P((pcmcia_chipset_handle_t, int));
|
||||
|
||||
/* I/O space allocation */
|
||||
int (*io_alloc) __P((pcmcia_chipset_handle_t, bus_addr_t,
|
||||
bus_size_t, bus_size_t, struct pcmcia_io_handle *));
|
||||
void (*io_free) __P((pcmcia_chipset_handle_t,
|
||||
struct pcmcia_io_handle *));
|
||||
|
||||
/* I/O space window mapping */
|
||||
int (*io_map) __P((pcmcia_chipset_handle_t, int, bus_addr_t,
|
||||
bus_size_t, struct pcmcia_io_handle *, int *));
|
||||
void (*io_unmap) __P((pcmcia_chipset_handle_t, int));
|
||||
|
||||
/* interrupt glue */
|
||||
void *(*intr_establish) __P((pcmcia_chipset_handle_t,
|
||||
struct pcmcia_function *, int, int (*)(void *), void *));
|
||||
void (*intr_disestablish) __P((pcmcia_chipset_handle_t, void *));
|
||||
|
||||
/* card enable/disable */
|
||||
void (*socket_enable) __P((pcmcia_chipset_handle_t));
|
||||
void (*socket_disable) __P((pcmcia_chipset_handle_t));
|
||||
};
|
||||
|
||||
/* Memory space functions. */
|
||||
#define pcmcia_chip_mem_alloc(tag, handle, size, pcmhp) \
|
||||
((*(tag)->mem_alloc)((handle), (size), (pcmhp)))
|
||||
|
||||
#define pcmcia_chip_mem_free(tag, handle, pcmhp) \
|
||||
((*(tag)->mem_free)((handle), (pcmhp)))
|
||||
|
||||
#define pcmcia_chip_mem_map(tag, handle, kind, card_addr, size, pcmhp, \
|
||||
offsetp, windowp) \
|
||||
((*(tag)->mem_map)((handle), (kind), (card_addr), (size), (pcmhp), \
|
||||
(offsetp), (windowp)))
|
||||
|
||||
#define pcmcia_chip_mem_unmap(tag, handle, window) \
|
||||
((*(tag)->mem_unmap)((handle), (window)))
|
||||
|
||||
/* I/O space functions. */
|
||||
#define pcmcia_chip_io_alloc(tag, handle, start, size, align, pcihp) \
|
||||
((*(tag)->io_alloc)((handle), (start), (size), (align), (pcihp)))
|
||||
|
||||
#define pcmcia_chip_io_free(tag, handle, pcihp) \
|
||||
((*(tag)->io_free)((handle), (pcihp)))
|
||||
|
||||
#define pcmcia_chip_io_map(tag, handle, width, card_addr, size, pcihp, \
|
||||
windowp) \
|
||||
((*(tag)->io_map)((handle), (width), (card_addr), (size), (pcihp), \
|
||||
(windowp)))
|
||||
|
||||
#define pcmcia_chip_io_unmap(tag, handle, window) \
|
||||
((*(tag)->io_unmap)((handle), (window)))
|
||||
|
||||
/* Interrupt functions. */
|
||||
#define pcmcia_chip_intr_establish(tag, handle, pf, ipl, fct, arg) \
|
||||
((*(tag)->intr_establish)((handle), (pf), (ipl), (fct), (arg)))
|
||||
|
||||
#define pcmcia_chip_intr_disestablish(tag, handle, ih) \
|
||||
((*(tag)->intr_disestablish)((handle), (ih)))
|
||||
|
||||
/* Socket functions. */
|
||||
#define pcmcia_chip_socket_enable(tag, handle) \
|
||||
((*(tag)->socket_enable)((handle)))
|
||||
#define pcmcia_chip_socket_disable(tag, handle) \
|
||||
((*(tag)->socket_disable)((handle)))
|
||||
|
||||
struct pcmciabus_attach_args {
|
||||
pcmcia_chipset_tag_t pct;
|
||||
pcmcia_chipset_handle_t pch;
|
||||
bus_addr_t iobase; /* start i/o space allocation here */
|
||||
bus_size_t iosize; /* size of the i/o space range */
|
||||
};
|
||||
|
||||
/* interfaces for the chipset to call pcmcia */
|
||||
|
||||
int pcmcia_card_attach __P((struct device *));
|
||||
void pcmcia_card_detach __P((struct device *));
|
||||
int pcmcia_card_gettype __P((struct device *));
|
||||
|
||||
#endif /* _PCMCIA_PCMCIACHIP_H_ */
|
221
sys/dev/pcmcia/pcmciareg.h
Normal file
221
sys/dev/pcmcia/pcmciareg.h
Normal file
@ -0,0 +1,221 @@
|
||||
/* $NetBSD: pcmciareg.h,v 1.2 1997/10/16 23:27:38 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* most of this is from the PCMCIA PC Card Standard, Release 2.1 */
|
||||
|
||||
/*
|
||||
* CIS Tuples
|
||||
*/
|
||||
|
||||
/* Layer 1 Basic Compatibility Tuples */
|
||||
#define PCMCIA_CISTPL_NULL 0x00
|
||||
#define PCMCIA_CISTPL_DEVICE 0x01
|
||||
#define PCMCIA_DTYPE_MASK 0xF0
|
||||
#define PCMCIA_DTYPE_NULL 0x00
|
||||
#define PCMCIA_DTYPE_ROM 0x10
|
||||
#define PCMCIA_DTYPE_OTPROM 0x20
|
||||
#define PCMCIA_DTYPE_EPROM 0x30
|
||||
#define PCMCIA_DTYPE_EEPROM 0x40
|
||||
#define PCMCIA_DTYPE_FLASH 0x50
|
||||
#define PCMCIA_DTYPE_SRAM 0x60
|
||||
#define PCMCIA_DTYPE_DRAM 0x70
|
||||
#define PCMCIA_DTYPE_FUNCSPEC 0xD0
|
||||
#define PCMCIA_DTYPE_EXTEND 0xE0
|
||||
#define PCMCIA_DSPEED_MASK 0x07
|
||||
#define PCMCIA_DSPEED_NULL 0x00
|
||||
#define PCMCIA_DSPEED_250NS 0x01
|
||||
#define PCMCIA_DSPEED_200NS 0x02
|
||||
#define PCMCIA_DSPEED_150NS 0x03
|
||||
#define PCMCIA_DSPEED_100NS 0x04
|
||||
#define PCMCIA_DSPEED_EXT 0x05
|
||||
|
||||
/*
|
||||
* the 2.1 docs have 0x02-0x07 as reserved, but the linux drivers list the
|
||||
* follwing tuple code values. I have at least one card (3com 3c562
|
||||
* lan+modem) which has a code 0x06 tuple, so I'm going to assume that these
|
||||
* are for real
|
||||
*/
|
||||
|
||||
#define PCMCIA_CISTPL_LONGLINK_CB 0x02
|
||||
#define PCMCIA_CISTPL_CONFIG_CB 0x04
|
||||
#define PCMCIA_CISTPL_CFTABLE_ENTRY_CB 0x05
|
||||
#define PCMCIA_CISTPL_LONGLINK_MFC 0x06
|
||||
#define PCMCIA_MFC_MEM_ATTR 0x00
|
||||
#define PCMCIA_MFC_MEM_COMMON 0x01
|
||||
#define PCMCIA_CISTPL_BAR 0x07
|
||||
|
||||
#define PCMCIA_CISTPL_CHECKSUM 0x10
|
||||
#define PCMCIA_CISTPL_LONGLINK_A 0x11
|
||||
#define PCMCIA_CISTPL_LONGLINK_C 0x12
|
||||
#define PCMCIA_CISTPL_LINKTARGET 0x13
|
||||
#define PCMCIA_CISTPL_NO_LINK 0x14
|
||||
#define PCMCIA_CISTPL_VERS_1 0x15
|
||||
#define PCMCIA_CISTPL_ALTSTR 0x16
|
||||
#define PCMCIA_CISTPL_DEVICE_A 0x17
|
||||
#define PCMCIA_CISTPL_JEDEC_C 0x18
|
||||
#define PCMCIA_CISTPL_JEDEC_A 0x19
|
||||
#define PCMCIA_CISTPL_CONFIG 0x1A
|
||||
#define PCMCIA_TPCC_RASZ_MASK 0x03
|
||||
#define PCMCIA_TPCC_RASZ_SHIFT 0
|
||||
#define PCMCIA_TPCC_RMSZ_MASK 0x3C
|
||||
#define PCMCIA_TPCC_RMSZ_SHIFT 2
|
||||
#define PCMCIA_TPCC_RFSZ_MASK 0xC0
|
||||
#define PCMCIA_TPCC_RFSZ_SHIFT 6
|
||||
#define PCMCIA_CISTPL_CFTABLE_ENTRY 0x1B
|
||||
#define PCMCIA_TPCE_INDX_INTFACE 0x80
|
||||
#define PCMCIA_TPCE_INDX_DEFAULT 0x40
|
||||
#define PCMCIA_TPCE_INDX_NUM_MASK 0x3F
|
||||
#define PCMCIA_TPCE_IF_MWAIT 0x80
|
||||
#define PCMCIA_TPCE_IF_RDYBSY 0x40
|
||||
#define PCMCIA_TPCE_IF_WP 0x20
|
||||
#define PCMCIA_TPCE_IF_BVD 0x10
|
||||
#define PCMCIA_TPCE_IF_IFTYPE 0x0F
|
||||
#define PCMCIA_IFTYPE_MEMORY 0
|
||||
#define PCMCIA_IFTYPE_IO 1
|
||||
#define PCMCIA_TPCE_FS_MISC 0x80
|
||||
#define PCMCIA_TPCE_FS_MEMSPACE_MASK 0x60
|
||||
#define PCMCIA_TPCE_FS_MEMSPACE_NONE 0x00
|
||||
#define PCMCIA_TPCE_FS_MEMSPACE_LENGTH 0x20
|
||||
#define PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR 0x40
|
||||
#define PCMCIA_TPCE_FS_MEMSPACE_TABLE 0x60
|
||||
#define PCMCIA_TPCE_FS_IRQ 0x10
|
||||
#define PCMCIA_TPCE_FS_IOSPACE 0x08
|
||||
#define PCMCIA_TPCE_FS_TIMING 0x04
|
||||
#define PCMCIA_TPCE_FS_POWER_MASK 0x03
|
||||
#define PCMCIA_TPCE_FS_POWER_NONE 0x00
|
||||
#define PCMCIA_TPCE_FS_POWER_VCC 0x01
|
||||
#define PCMCIA_TPCE_FS_POWER_VCCVPP1 0x02
|
||||
#define PCMCIA_TPCE_FS_POWER_VCCVPP1VPP2 0x03
|
||||
#define PCMCIA_TPCE_TD_RESERVED_MASK 0xE0
|
||||
#define PCMCIA_TPCE_TD_RDYBSY_MASK 0x1C
|
||||
#define PCMCIA_TPCE_TD_WAIT_MASK 0x03
|
||||
#define PCMCIA_TPCE_IO_HASRANGE 0x80
|
||||
#define PCMCIA_TPCE_IO_BUSWIDTH_16BIT 0x40
|
||||
#define PCMCIA_TPCE_IO_BUSWIDTH_8BIT 0x20
|
||||
#define PCMCIA_TPCE_IO_IOADDRLINES_MASK 0x1F
|
||||
#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK 0xC0
|
||||
#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_NONE 0x00
|
||||
#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE 0x40
|
||||
#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO 0x80
|
||||
#define PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR 0xC0
|
||||
#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK 0x30
|
||||
#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_NONE 0x00
|
||||
#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE 0x10
|
||||
#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO 0x20
|
||||
#define PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR 0x30
|
||||
#define PCMCIA_TPCE_IO_RANGE_COUNT 0x0F
|
||||
#define PCMCIA_TPCE_IR_SHARE 0x80
|
||||
#define PCMCIA_TPCE_IR_PULSE 0x40
|
||||
#define PCMCIA_TPCE_IR_LEVEL 0x20
|
||||
#define PCMCIA_TPCE_IR_HASMASK 0x10
|
||||
#define PCMCIA_TPCE_IR_IRQ 0x0F
|
||||
#define PCMCIA_TPCE_MS_HOSTADDR 0x80
|
||||
#define PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK 0x60
|
||||
#define PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT 5
|
||||
#define PCMCIA_TPCE_MS_LENGTH_SIZE_MASK 0x18
|
||||
#define PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT 3
|
||||
#define PCMCIA_TPCE_MS_COUNT 0x07
|
||||
#define PCMCIA_TPCE_MI_EXT 0x80
|
||||
#define PCMCIA_TPCE_MI_RESERVED 0x40
|
||||
#define PCMCIA_TPCE_MI_PWRDOWN 0x20
|
||||
#define PCMCIA_TPCE_MI_READONLY 0x10
|
||||
#define PCMCIA_TPCE_MI_AUDIO 0x08
|
||||
#define PCMCIA_TPCE_MI_MAXTWINS 0x07
|
||||
#define PCMCIA_CISTPL_DEVICE_OC 0x1C
|
||||
#define PCMCIA_CISTPL_DEVICE_OA 0x1D
|
||||
#define PCMCIA_CISTPL_DEVICE_GEO 0x1E
|
||||
#define PCMCIA_CISTPL_DEVICE_GEO_A 0x1F
|
||||
|
||||
/* Layer 2 Data Recording Format Tuples */
|
||||
|
||||
#define PCMCIA_CISTPL_MANFID 0x20
|
||||
#define PCMCIA_CISTPL_FUNCID 0x21
|
||||
#define PCMCIA_CISTPL_FUNCE 0x22
|
||||
#define PCMCIA_CISTPL_SWIL 0x23
|
||||
/* #define PCMCIA_CISTPL_RESERVED 0x24-0x3F */
|
||||
#define PCMCIA_CISTPL_VERS_2 0x40
|
||||
#define PCMCIA_CISTPL_FORMAT 0x41
|
||||
#define PCMCIA_CISTPL_GEOMETRY 0x42
|
||||
#define PCMCIA_CISTPL_BYTEORDER 0x43
|
||||
#define PCMCIA_CISTPL_DATE 0x44
|
||||
#define PCMCIA_CISTPL_BATTERY 0x45
|
||||
|
||||
/* Layer 3 Data Organization Tuples */
|
||||
|
||||
#define PCMCIA_CISTPL_ORG 0x46
|
||||
/* #define PCMCIA_CISTPL_RESERVED 0x47-0x7F */
|
||||
|
||||
/* Layer 4 System-Specific Standard Tuples */
|
||||
|
||||
/* #define PCMCIA_CISTPL_RESERVED 0x80-0xFE */
|
||||
#define PCMCIA_CISTPL_END 0xFF
|
||||
|
||||
/*
|
||||
* Card Configuration Registers
|
||||
*/
|
||||
|
||||
#define PCMCIA_CCR_OPTION 0x00
|
||||
#define PCMCIA_CCR_OPTION_SRESET 0x80
|
||||
#define PCMCIA_CCR_OPTION_LEVIREQ 0x40
|
||||
#define PCMCIA_CCR_OPTION_CFINDEX 0x3F
|
||||
#define PCMCIA_CCR_OPTION_IREQ_ENABLE 0x04
|
||||
#define PCMCIA_CCR_OPTION_ADDR_DECODE 0x02
|
||||
#define PCMCIA_CCR_OPTION_FUNC_ENABLE 0x01
|
||||
#define PCMCIA_CCR_STATUS 0x02
|
||||
#define PCMCIA_CCR_STATUS_PINCHANGED 0x80
|
||||
#define PCMCIA_CCR_STATUS_SIGCHG 0x40
|
||||
#define PCMCIA_CCR_STATUS_IOIS8 0x20
|
||||
#define PCMCIA_CCR_STATUS_RESERVED1 0x10
|
||||
#define PCMCIA_CCR_STATUS_AUDIO 0x08
|
||||
#define PCMCIA_CCR_STATUS_PWRDWN 0x04
|
||||
#define PCMCIA_CCR_STATUS_INTR 0x02
|
||||
#define PCMCIA_CCR_STATUS_INTRACK 0x01
|
||||
#define PCMCIA_CCR_PIN 0x04
|
||||
#define PCMCIA_CCR_PIN_CBVD1 0x80
|
||||
#define PCMCIA_CCR_PIN_CBVD2 0x40
|
||||
#define PCMCIA_CCR_PIN_CRDYBSY 0x20
|
||||
#define PCMCIA_CCR_PIN_CWPROT 0x10
|
||||
#define PCMCIA_CCR_PIN_RBVD1 0x08
|
||||
#define PCMCIA_CCR_PIN_RBVD2 0x04
|
||||
#define PCMCIA_CCR_PIN_RRDYBSY 0x02
|
||||
#define PCMCIA_CCR_PIN_RWPROT 0x01
|
||||
#define PCMCIA_CCR_SOCKETCOPY 0x06
|
||||
#define PCMCIA_CCR_SOCKETCOPY_RESERVED 0x80
|
||||
#define PCMCIA_CCR_SOCKETCOPY_COPY_MASK 0x70
|
||||
#define PCMCIA_CCR_SOCKETCOPY_COPY_SHIFT 4
|
||||
#define PCMCIA_CCR_SOCKETCOPY_SOCKET_MASK 0x0F
|
||||
#define PCMCIA_CCR_IOBASE0 0x0A
|
||||
#define PCMCIA_CCR_IOBASE1 0x0C
|
||||
#define PCMCIA_CCR_IOBASE2 0x0E
|
||||
#define PCMCIA_CCR_IOBASE3 0x10
|
||||
#define PCMCIA_CCR_IOSIZE 0x12
|
||||
|
||||
#define PCMCIA_CCR_SIZE 0x14
|
252
sys/dev/pcmcia/pcmciavar.h
Normal file
252
sys/dev/pcmcia/pcmciavar.h
Normal file
@ -0,0 +1,252 @@
|
||||
/* $NetBSD: pcmciavar.h,v 1.2 1997/10/16 23:27:40 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Marc Horowitz.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/pcmcia/pcmciachip.h>
|
||||
|
||||
/*
|
||||
* Contains information about mapped/allocated i/o spaces.
|
||||
*/
|
||||
struct pcmcia_io_handle {
|
||||
bus_space_tag_t iot; /* bus space tag (from chipset) */
|
||||
bus_space_handle_t ioh; /* mapped space handle */
|
||||
bus_addr_t addr; /* resulting address in bus space */
|
||||
bus_size_t size; /* size of i/o space */
|
||||
int flags; /* misc. information */
|
||||
};
|
||||
|
||||
#define PCMCIA_IO_ALLOCATED 0x01 /* i/o space was allocated */
|
||||
|
||||
/*
|
||||
* Contains information about allocated memory space.
|
||||
*/
|
||||
struct pcmcia_mem_handle {
|
||||
bus_space_tag_t memt; /* bus space tag (from chipset) */
|
||||
bus_space_handle_t memh; /* mapped space handle */
|
||||
bus_addr_t addr; /* resulting address in bus space */
|
||||
bus_size_t size; /* size of mem space */
|
||||
pcmcia_mem_handle_t mhandle; /* opaque memory handle */
|
||||
bus_size_t realsize; /* how much we really allocated */
|
||||
};
|
||||
|
||||
/* pcmcia itself */
|
||||
|
||||
#define PCMCIA_CFE_MWAIT_REQUIRED 0x0001
|
||||
#define PCMCIA_CFE_RDYBSY_ACTIVE 0x0002
|
||||
#define PCMCIA_CFE_WP_ACTIVE 0x0004
|
||||
#define PCMCIA_CFE_BVD_ACTIVE 0x0008
|
||||
#define PCMCIA_CFE_IO8 0x0010
|
||||
#define PCMCIA_CFE_IO16 0x0020
|
||||
#define PCMCIA_CFE_IRQSHARE 0x0040
|
||||
#define PCMCIA_CFE_IRQPULSE 0x0080
|
||||
#define PCMCIA_CFE_IRQLEVEL 0x0100
|
||||
#define PCMCIA_CFE_POWERDOWN 0x0200
|
||||
#define PCMCIA_CFE_READONLY 0x0400
|
||||
#define PCMCIA_CFE_AUDIO 0x0800
|
||||
|
||||
struct pcmcia_config_entry {
|
||||
int number;
|
||||
u_int32_t flags;
|
||||
int iftype;
|
||||
int num_iospace;
|
||||
|
||||
/*
|
||||
* The card will only decode this mask in any case, so we can
|
||||
* do dynamic allocation with this in mind, in case the suggestions
|
||||
* below are no good.
|
||||
*/
|
||||
u_long iomask;
|
||||
struct {
|
||||
u_long length;
|
||||
u_long start;
|
||||
} iospace[4]; /* XXX this could be as high as 16 */
|
||||
u_int16_t irqmask;
|
||||
int num_memspace;
|
||||
struct {
|
||||
u_long length;
|
||||
u_long cardaddr;
|
||||
u_long hostaddr;
|
||||
} memspace[2]; /* XXX this could be as high as 8 */
|
||||
int maxtwins;
|
||||
SIMPLEQ_ENTRY(pcmcia_config_entry) cfe_list;
|
||||
};
|
||||
|
||||
struct pcmcia_function {
|
||||
/* read off the card */
|
||||
int number;
|
||||
int function;
|
||||
int last_config_index;
|
||||
u_long ccr_base;
|
||||
u_long ccr_mask;
|
||||
SIMPLEQ_HEAD(, pcmcia_config_entry) cfe_head;
|
||||
SIMPLEQ_ENTRY(pcmcia_function) pf_list;
|
||||
/* run-time state */
|
||||
struct pcmcia_softc *sc;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
struct pcmcia_mem_handle pf_pcmh;
|
||||
#define pf_ccrt pf_pcmh.memt
|
||||
#define pf_ccrh pf_pcmh.memh
|
||||
#define pf_ccr_mhandle pf_pcmh.mhandle
|
||||
#define pf_ccr_realsize pf_pcmh.realsize
|
||||
bus_addr_t pf_ccr_offset;
|
||||
int pf_ccr_window;
|
||||
int (*ih_fct) __P((void *));
|
||||
void *ih_arg;
|
||||
int ih_ipl;
|
||||
int pf_flags;
|
||||
};
|
||||
|
||||
/* pf_flags */
|
||||
#define PFF_ENABLED 0x0001 /* function is enabled */
|
||||
|
||||
struct pcmcia_card {
|
||||
int cis1_major;
|
||||
int cis1_minor;
|
||||
/* XXX waste of space? */
|
||||
char cis1_info_buf[256];
|
||||
char *cis1_info[4];
|
||||
int manufacturer;
|
||||
u_int16_t product;
|
||||
u_int16_t error;
|
||||
SIMPLEQ_HEAD(, pcmcia_function) pf_head;
|
||||
};
|
||||
|
||||
struct pcmcia_softc {
|
||||
struct device dev;
|
||||
|
||||
/* this stuff is for the socket */
|
||||
pcmcia_chipset_tag_t pct;
|
||||
pcmcia_chipset_handle_t pch;
|
||||
|
||||
/* this stuff is for the card */
|
||||
struct pcmcia_card card;
|
||||
void *ih;
|
||||
int sc_enabled_count; /* how many functions are
|
||||
enabled */
|
||||
|
||||
/*
|
||||
* These are passed down from the PCMCIA chip, and exist only
|
||||
* so that cards with Very Special address allocation needs
|
||||
* know what range they should be dealing with.
|
||||
*/
|
||||
bus_addr_t iobase; /* start i/o space allocation here */
|
||||
bus_size_t iosize; /* size of the i/o space range */
|
||||
};
|
||||
|
||||
struct pcmcia_attach_args {
|
||||
u_int16_t manufacturer;
|
||||
u_int16_t product;
|
||||
struct pcmcia_card *card;
|
||||
struct pcmcia_function *pf;
|
||||
};
|
||||
|
||||
struct pcmcia_tuple {
|
||||
unsigned int code;
|
||||
unsigned int length;
|
||||
u_long mult;
|
||||
bus_addr_t ptr;
|
||||
bus_space_tag_t memt;
|
||||
bus_space_handle_t memh;
|
||||
};
|
||||
|
||||
void pcmcia_read_cis __P((struct pcmcia_softc *));
|
||||
void pcmcia_print_cis __P((struct pcmcia_softc *));
|
||||
int pcmcia_scan_cis __P((struct device * dev,
|
||||
int (*) (struct pcmcia_tuple *, void *), void *));
|
||||
|
||||
#define pcmcia_cis_read_1(tuple, idx0) \
|
||||
(bus_space_read_1((tuple)->memt, (tuple)->memh, (tuple)->mult*(idx0)))
|
||||
|
||||
#define pcmcia_tuple_read_1(tuple, idx1) \
|
||||
(pcmcia_cis_read_1((tuple), ((tuple)->ptr+(2+(idx1)))))
|
||||
|
||||
#define pcmcia_tuple_read_2(tuple, idx2) \
|
||||
(pcmcia_tuple_read_1((tuple), (idx2)) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx2)+1)<<8))
|
||||
|
||||
#define pcmcia_tuple_read_3(tuple, idx3) \
|
||||
(pcmcia_tuple_read_1((tuple), (idx3)) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx3)+1)<<8) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx3)+2)<<16))
|
||||
|
||||
#define pcmcia_tuple_read_4(tuple, idx4) \
|
||||
(pcmcia_tuple_read_1((tuple), (idx4)) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx4)+1)<<8) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx4)+2)<<16) | \
|
||||
(pcmcia_tuple_read_1((tuple), (idx4)+3)<<24))
|
||||
|
||||
#define pcmcia_tuple_read_n(tuple, n, idxn) \
|
||||
(((n)==1)?pcmcia_tuple_read_1((tuple), (idxn)) : \
|
||||
(((n)==2)?pcmcia_tuple_read_2((tuple), (idxn)) : \
|
||||
(((n)==3)?pcmcia_tuple_read_3((tuple), (idxn)) : \
|
||||
/* n == 4 */ pcmcia_tuple_read_4((tuple), (idxn)))))
|
||||
|
||||
#define PCMCIA_SPACE_MEMORY 1
|
||||
#define PCMCIA_SPACE_IO 2
|
||||
|
||||
int pcmcia_ccr_read __P((struct pcmcia_function *, int));
|
||||
void pcmcia_ccr_write __P((struct pcmcia_function *, int, int));
|
||||
|
||||
#define pcmcia_mfc(sc) ((sc)->card.pf_head.sqh_first && \
|
||||
(sc)->card.pf_head.sqh_first->pf_list.sqe_next)
|
||||
|
||||
void pcmcia_function_init __P((struct pcmcia_function *,
|
||||
struct pcmcia_config_entry *));
|
||||
int pcmcia_function_enable __P((struct pcmcia_function *));
|
||||
void pcmcia_function_disable __P((struct pcmcia_function *));
|
||||
|
||||
#define pcmcia_io_alloc(pf, start, size, align, pciop) \
|
||||
(pcmcia_chip_io_alloc((pf)->sc->pct, pf->sc->pch, (start), \
|
||||
(size), (align), (pciop)))
|
||||
|
||||
int pcmcia_io_map __P((struct pcmcia_function *, int, bus_addr_t,
|
||||
bus_size_t, struct pcmcia_io_handle *, int *));
|
||||
|
||||
#define pcmcia_mem_alloc(pf, size, pcmhp) \
|
||||
(pcmcia_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
|
||||
|
||||
#define pcmcia_mem_free(pf, pcmhp) \
|
||||
(pcmcia_chip_mem_free((pf)->sc->pct, (pf)->sc->pch, (pcmhp)))
|
||||
|
||||
#define pcmcia_mem_map(pf, kind, card_addr, size, pcmhp, offsetp, windowp) \
|
||||
(pcmcia_chip_mem_map((pf)->sc->pct, (pf)->sc->pch, (kind), \
|
||||
(card_addr), (size), (pcmhp), (offsetp), (windowp)))
|
||||
|
||||
#define pcmcia_mem_unmap(pf, window) \
|
||||
(pcmcia_chip_mem_unmap((pf)->sc->pct, (pf)->sc->pch, (window)))
|
||||
|
||||
void *pcmcia_intr_establish __P((struct pcmcia_function *, int,
|
||||
int (*) (void *), void *));
|
||||
void pcmcia_intr_disestablish __P((struct pcmcia_function *, void *));
|
Loading…
Reference in New Issue
Block a user