Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pcmcia implement cnw_detach.



details:   https://anonhg.NetBSD.org/src/rev/23d0d4efb7c8
branches:  trunk
changeset: 481592:23d0d4efb7c8
user:      itojun <itojun%NetBSD.org@localhost>
date:      Wed Feb 02 12:25:13 2000 +0000

description:
implement cnw_detach.
XXX it looks that whenever there's error-return in xx_attach,
we need to have some check in xx_detach().  otherwise, routines such as
ether_ifdetach() will be called without call to ether_ifattach().

diffstat:

 sys/dev/pcmcia/if_cnw.c |  91 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 88 insertions(+), 3 deletions(-)

diffs (178 lines):

diff -r 889bb7ad0531 -r 23d0d4efb7c8 sys/dev/pcmcia/if_cnw.c
--- a/sys/dev/pcmcia/if_cnw.c   Wed Feb 02 12:11:47 2000 +0000
+++ b/sys/dev/pcmcia/if_cnw.c   Wed Feb 02 12:25:13 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_cnw.c,v 1.4 2000/01/25 16:48:47 itojun Exp $        */
+/*     $NetBSD: if_cnw.c,v 1.5 2000/02/02 12:25:13 itojun Exp $        */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -177,6 +177,9 @@
 
 int    cnw_match __P((struct device *, struct cfdata *, void *));
 void   cnw_attach __P((struct device *, struct device *, void *));
+int    cnw_detach __P((struct device *, int));
+
+int    cnw_activate __P((struct device *, enum devact));
 
 struct cnw_softc {
        struct device sc_dev;               /* Device glue (must be first) */
@@ -199,10 +202,16 @@
        void *sc_ih;                        /* Interrupt cookie */
        struct timeval sc_txlast;           /* When the last xmit was made */
        int sc_active;                      /* Currently xmitting a packet */
+
+       int sc_resource;                    /* Resources alloc'ed on attach */
+#define CNW_RES_IO     1
+#define CNW_RES_MEM    2
+#define CNW_RES_NET    4
 };
 
 struct cfattach cnw_ca = {
-       sizeof(struct cnw_softc), cnw_match, cnw_attach
+       sizeof(struct cnw_softc), cnw_match, cnw_attach, cnw_detach,
+               cnw_activate
 };
 
 
@@ -388,6 +397,9 @@
 {
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 
+       if ((ifp->if_flags & IFF_RUNNING) != 0)
+               return (0);
+
        sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, cnw_intr, sc);
        if (sc->sc_ih == NULL) {
                printf("%s: couldn't establish interrupt handler\n",
@@ -414,6 +426,9 @@
 {
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 
+       if ((ifp->if_flags & IFF_RUNNING) == 0)
+               return;
+
        pcmcia_function_disable(sc->sc_pf);
        pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
        ifp->if_flags &= ~IFF_RUNNING;
@@ -456,6 +471,8 @@
        u_int8_t macaddr[ETHER_ADDR_LEN];
        int i;
 
+       sc->sc_resource = 0;
+
        /* Enable the card */
        sc->sc_pf = pa->pf;
        pcmcia_function_init(sc->sc_pf, sc->sc_pf->cfe_head.sqh_first);
@@ -472,23 +489,33 @@
        }
        if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, 0,
            CNW_IO_SIZE, &sc->sc_pcioh, &sc->sc_iowin) != 0) {
+               pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
                printf(": can't map i/o space\n");
                return;
        }
        sc->sc_iot = sc->sc_pcioh.iot;
        sc->sc_ioh = sc->sc_pcioh.ioh;
+       sc->sc_resource |= CNW_RES_IO;
        if (pcmcia_mem_alloc(sc->sc_pf, CNW_MEM_SIZE, &sc->sc_pcmemh) != 0) {
                printf(": can't allocate memory\n");
+               pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
+               pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
+               sc->sc_resource = 0;
                return;
        }
        if (pcmcia_mem_map(sc->sc_pf, PCMCIA_MEM_COMMON, CNW_MEM_ADDR,
            CNW_MEM_SIZE, &sc->sc_pcmemh, &sc->sc_memoff,
            &sc->sc_memwin) != 0) {
                printf(": can't map memory\n");
+               pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
+               pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
+               pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
+               sc->sc_resource = 0;
                return;
        }
        sc->sc_memt = sc->sc_pcmemh.memt;
        sc->sc_memh = sc->sc_pcmemh.memh;
+       sc->sc_resource |= CNW_RES_MEM;
        switch (pa->product) {
        case PCMCIA_PRODUCT_TDK_XIR_CNW_801:
                printf(": %s\n", PCMCIA_STR_TDK_XIR_CNW_801);
@@ -526,6 +553,7 @@
        bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
            sizeof(struct ether_header));
 #endif
+       sc->sc_resource |= CNW_RES_NET;
 
        ifp->if_baudrate = 1 * 1024 * 1024;
 
@@ -842,7 +870,8 @@
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        int ret, status, rser, tser;
 
-       if (!(sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING))
+       if ((sc->sc_ethercom.ec_if.if_flags & IFF_RUNNING) == 0 ||
+           (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
                return (0);
        ifp->if_timer = 0;      /* stop watchdog timer */
 
@@ -1109,3 +1138,59 @@
        sc->sc_skey = key;
        return 0;
 }
+
+int
+cnw_activate(self, act)
+       struct device *self;
+       enum devact act;
+{
+       struct cnw_softc *sc = (struct cnw_softc *)self;
+       int rv = 0, s;
+
+       s = splnet();
+       switch (act) {
+       case DVACT_ACTIVATE:
+               rv = EOPNOTSUPP;
+               break;
+
+       case DVACT_DEACTIVATE:
+               if_deactivate(&sc->sc_ethercom.ec_if);
+               break;
+       }
+       splx(s);
+       return (rv);
+}
+
+int
+cnw_detach(self, flags)
+       struct device *self;
+       int flags;
+{
+       struct cnw_softc *sc = (struct cnw_softc *)self;
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+       /* cnw_disable() checks IFF_RUNNING */
+       cnw_disable(sc);
+
+       if ((sc->sc_resource & CNW_RES_NET) != 0) {
+#if NBPFILTER > 0
+               bpfdetach(ifp);
+#endif
+               ether_ifdetach(ifp);
+               if_detach(ifp);
+       }
+
+       /* unmap and free our i/o windows */
+       if ((sc->sc_resource & CNW_RES_IO) != 0) {
+               pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
+               pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
+       }
+
+       /* unmap and free our memory windows */
+       if ((sc->sc_resource & CNW_RES_MEM) != 0) {
+               pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
+               pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
+       }
+
+       return (0);
+}



Home | Main Index | Thread Index | Old Index