Use pcmcia_function_{configure,unconfigure}().

This commit is contained in:
mycroft 2004-08-10 02:54:19 +00:00
parent 2137977a97
commit 7f6dd84dc4
2 changed files with 92 additions and 136 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: com_pcmcia.c,v 1.43 2004/08/09 18:30:51 mycroft Exp $ */
/* $NetBSD: com_pcmcia.c,v 1.44 2004/08/10 02:55:30 mycroft Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: com_pcmcia.c,v 1.43 2004/08/09 18:30:51 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: com_pcmcia.c,v 1.44 2004/08/10 02:55:30 mycroft Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -110,6 +110,7 @@ static int com_devs_size = sizeof(com_devs) / sizeof(com_devs[0]);
static struct com_dev *com_dev_match __P((struct pcmcia_card *));
int com_pcmcia_match __P((struct device *, struct cfdata *, void *));
int com_pcmcia_validate_config __P((struct pcmcia_config_entry *));
void com_pcmcia_attach __P((struct device *, struct device *, void *));
int com_pcmcia_detach __P((struct device *, int));
void com_pcmcia_cleanup __P((void *));
@ -121,10 +122,9 @@ 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 */
int sc_attached;
};
CFATTACH_DECL(com_pcmcia, sizeof(struct com_pcmcia_softc),
@ -194,6 +194,20 @@ com_pcmcia_match(parent, match, aux)
return 0;
}
int
com_pcmcia_validate_config(cfe)
struct pcmcia_config_entry *cfe;
{
if (cfe->iftype != PCMCIA_IFTYPE_IO ||
cfe->num_iospace != 1)
return (EINVAL);
/* Some cards have a memory space, but we don't use it. */
cfe->num_memspace = 0;
/* Some cards don't have IO8 in their CIS. */
cfe->flags |= PCMCIA_CFE_IO8;
return (0);
}
void
com_pcmcia_attach(parent, self, aux)
struct device *parent, *self;
@ -203,86 +217,31 @@ com_pcmcia_attach(parent, self, aux)
struct com_softc *sc = &psc->sc_com;
struct pcmcia_attach_args *pa = aux;
struct pcmcia_config_entry *cfe;
int autoalloc = 0;
int error;
aprint_normal("\n");
psc->sc_pf = pa->pf;
psc->sc_io_window = -1;
retry:
/* find a cfe we can use */
SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
#if 0
/*
* Some modem cards (e.g. Xircom CM33) also have
* mem space. Don't bother with this check.
*/
if (cfe->num_memspace != 0)
continue;
#endif
if (cfe->num_iospace != 1)
continue;
if (autoalloc == 0) {
/*
* cfe->iomask == 3 is our test for the "generic"
* config table entry, which we want to avoid on the
* first pass and use exclusively on the second pass.
*/
if ((cfe->iomask != 3) &&
(cfe->iospace[0].start != 0)) {
if (!pcmcia_io_alloc(pa->pf,
cfe->iospace[0].start,
cfe->iospace[0].length,
cfe->iospace[0].length, &psc->sc_pcioh)) {
goto found;
}
}
} else {
if (cfe->iomask == 3) {
if (!pcmcia_io_alloc(pa->pf, 0,
cfe->iospace[0].length,
cfe->iospace[0].length, &psc->sc_pcioh)) {
goto found;
}
}
}
}
if (autoalloc == 0) {
autoalloc = 1;
goto retry;
} else if (!cfe) {
aprint_error("%s: can't allocate i/o space\n", self->dv_xname);
return;
}
found:
/* Enable the card. */
pcmcia_function_init(pa->pf, cfe);
if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
PCMCIA_WIDTH_AUTO : PCMCIA_WIDTH_IO8), &psc->sc_pcioh,
&psc->sc_io_window)) {
aprint_error("%s: can't map i/o space\n", self->dv_xname);
error = pcmcia_function_configure(pa->pf, com_pcmcia_validate_config);
if (error) {
aprint_error("%s: configure failed, error=%d\n", self->dv_xname,
error);
return;
}
if (com_pcmcia_enable(sc)) {
aprint_error("%s: function enable failed\n", self->dv_xname);
pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
return;
cfe = pa->pf->cfe;
sc->sc_iot = cfe->iospace[0].handle.iot;
sc->sc_ioh = cfe->iospace[0].handle.ioh;
error = com_pcmcia_enable(sc);
if (error) {
aprint_error("%s: enable failed, error=%d\n", self->dv_xname,
error);
goto fail;
}
sc->enabled = 1;
/* map in the io space */
sc->sc_iot = psc->sc_pcioh.iot;
sc->sc_ioh = psc->sc_pcioh.ioh;
sc->sc_iobase = -1;
sc->sc_frequency = COM_FREQ;
@ -295,7 +254,12 @@ found:
sc->enabled = 0;
psc->sc_attached = 1;
com_pcmcia_disable(sc);
return;
fail:
pcmcia_function_unconfigure(pa->pf);
}
int
@ -306,23 +270,14 @@ com_pcmcia_detach(self, flags)
struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) self;
int error;
/* Unmap our i/o window. */
if (psc->sc_io_window == -1) {
printf("%s: I/O window not allocated.\n",
psc->sc_com.sc_dev.dv_xname);
return 0;
}
if (!psc->sc_attached)
return (0);
if ((error = com_detach(self, flags)) != 0)
return error;
/* Unmap our i/o window. */
pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
/* Free our i/o space. */
pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
return 0;
pcmcia_function_unconfigure(psc->sc_pf);
return (0);
}
int
@ -343,6 +298,7 @@ com_pcmcia_enable(sc)
if ((error = pcmcia_function_enable(pf)) != 0) {
pcmcia_intr_disestablish(pf, psc->sc_ih);
psc->sc_ih = 0;
return (error);
}
@ -370,4 +326,5 @@ com_pcmcia_disable(sc)
pcmcia_function_disable(psc->sc_pf);
pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
psc->sc_ih = 0;
}

View File

@ -1,4 +1,5 @@
/* $NetBSD: if_ray.c,v 1.48 2004/08/09 21:30:18 mycroft Exp $ */
/* $NetBSD: if_ray.c,v 1.49 2004/08/10 02:54:19 mycroft Exp $ */
/*
* Copyright (c) 2000 Christian E. Hopps
* All rights reserved.
@ -56,7 +57,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_ray.c,v 1.48 2004/08/09 21:30:18 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_ray.c,v 1.49 2004/08/10 02:54:19 mycroft Exp $");
#include "opt_inet.h"
#include "bpfilter.h"
@ -156,11 +157,11 @@ struct ray_softc {
struct ifmedia sc_media;
struct pcmcia_function *sc_pf;
struct pcmcia_mem_handle sc_mem;
int sc_window;
void *sc_ih;
void *sc_sdhook;
void *sc_pwrhook;
int sc_attached;
int sc_flags; /*. misc flags */
#define RAY_FLAGS_RESUMEINIT 0x0001
int sc_resetloop;
@ -214,12 +215,13 @@ struct ray_softc {
struct ray_param_req *sc_repreq;
struct ray_param_req *sc_updreq;
bus_space_tag_t sc_memt;
bus_space_handle_t sc_memh;
#ifdef RAY_DO_SIGLEV
struct ray_siglev sc_siglevs[RAY_NSIGLEVRECS];
#endif
};
#define sc_memt sc_mem.memt
#define sc_memh sc_mem.memh
#define sc_ccrt sc_pf->pf_ccrt
#define sc_ccrh sc_pf->pf_ccrh
#define sc_ccroff sc_pf->pf_ccr_offset
@ -280,6 +282,7 @@ typedef void (*ray_cmd_func_t)(struct ray_softc *);
static int ray_alloc_ccs __P((struct ray_softc *, bus_size_t *, u_int, u_int));
static bus_size_t ray_fill_in_tx_ccs __P((struct ray_softc *, size_t,
u_int, u_int));
static int ray_validate_config __P((struct pcmcia_config_entry *));
static void ray_attach __P((struct device *, struct device *, void *));
static ray_cmd_func_t ray_ccs_done __P((struct ray_softc *, bus_size_t));
static void ray_check_ccs __P((void *));
@ -491,6 +494,17 @@ ray_match(parent, match, aux)
&& pa->product == PCMCIA_PRODUCT_RAYTHEON_WLAN);
}
static int
ray_validate_config(cfe)
struct pcmcia_config_entry *cfe;
{
if (cfe->iftype != PCMCIA_IFTYPE_IO ||
cfe->num_memspace != 1 ||
cfe->num_iospace != 0 ||
cfe->memspace[0].length != RAY_SRAM_MEM_SIZE)
return (EINVAL);
return (0);
}
static void
ray_attach(parent, self, aux)
@ -502,45 +516,32 @@ ray_attach(parent, self, aux)
struct ifnet *ifp = &sc->sc_if;
struct pcmcia_config_entry *cfe;
struct ray_ecf_startup *ep;
bus_size_t memoff;
sc->sc_window = -1;
int error;
aprint_normal("\n");
sc->sc_pf = pa->pf;
SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
if (cfe->num_memspace != 1)
continue;
if (cfe->num_iospace != 0)
continue;
if (pcmcia_mem_alloc(pa->pf, cfe->memspace[0].length,
&sc->sc_mem) == 0)
break;
}
if (!cfe) {
aprint_error("%s: can't alloc shared memory\n", self->dv_xname);
goto fail1;
/*XXXmem8|common*/
error = pcmcia_function_configure(pa->pf, ray_validate_config);
if (error) {
aprint_error("%s: configure failed, error=%d\n", self->dv_xname,
error);
return;
}
/* enable the card */
pcmcia_function_init(sc->sc_pf, cfe);
if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
RAY_SRAM_MEM_BASE, RAY_SRAM_MEM_SIZE, &sc->sc_mem, &memoff,
&sc->sc_window)) {
aprint_error("%s: can't map shared memory\n", self->dv_xname);
goto fail2;
}
cfe = pa->pf->cfe;
sc->sc_memt = cfe->memspace[0].handle.memt;
sc->sc_memh = cfe->memspace[0].handle.memh;
callout_init(&sc->sc_reset_resetloop_ch);
callout_init(&sc->sc_disable_ch);
callout_init(&sc->sc_start_join_timo_ch);
if (ray_enable(sc)) {
aprint_error("%s: failed to enable the card\n", self->dv_xname);
goto fail3;
error = ray_enable(sc);
if (error) {
aprint_error("%s: enable failed, error=%d\n", self->dv_xname,
error);
goto fail;
}
/* get startup results */
@ -552,14 +553,14 @@ ray_attach(parent, self, aux)
if (ep->e_status != RAY_ECFS_CARD_OK) {
aprint_error("%s: card failed self test: status %d\n",
self->dv_xname, sc->sc_ecf_startup.e_status);
goto fail4;
goto fail2;
}
/* check firmware version */
if (sc->sc_version != SC_BUILD_4 && sc->sc_version != SC_BUILD_5) {
aprint_error("%s: unsupported firmware version %d\n",
self->dv_xname, ep->e_fw_build_string);
goto fail4;
goto fail2;
}
/* clear any interrupt if present */
@ -620,17 +621,14 @@ ray_attach(parent, self, aux)
sc->sc_pwrhook = powerhook_establish(ray_power, sc);
/* The attach is successful. */
sc->sc_attached = 1;
ray_disable(sc);
return;
fail4:
ray_disable(sc);
fail3:
pcmcia_mem_unmap(sc->sc_pf, sc->sc_window);
fail2:
pcmcia_mem_free(sc->sc_pf, &sc->sc_mem);
fail1:
sc->sc_window = -1;
ray_disable(sc);
fail:
pcmcia_function_unconfigure(pa->pf);
}
static int
@ -671,8 +669,7 @@ ray_detach(self, flags)
ifp = &sc->sc_if;
RAY_DPRINTF(("%s: detach\n", sc->sc_xname));
if (sc->sc_window == -1)
/* Nothing to detach. */
if (!sc->sc_attached)
return (0);
if (sc->sc_pwrhook)
@ -686,8 +683,7 @@ ray_detach(self, flags)
ether_ifdetach(ifp);
if_detach(ifp);
pcmcia_mem_unmap(sc->sc_pf, sc->sc_window);
pcmcia_mem_free(sc->sc_pf, &sc->sc_mem);
pcmcia_function_unconfigure(sc->sc_pf);
return (0);
}
@ -709,8 +705,10 @@ ray_enable(sc)
return (EIO);
error = ray_init(sc);
if (error)
if (error) {
pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
sc->sc_ih = 0;
}
return (error);
}
@ -732,9 +730,10 @@ ray_disable(sc)
sc->sc_rxhcksum = 0;
sc->sc_rxnoise = 0;
if (sc->sc_ih)
if (sc->sc_ih) {
pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
sc->sc_ih = 0;
sc->sc_ih = 0;
}
}
/*