Make all network interrupt service routines MPSAFE part 1/3.
[dragonfly.git] / sys / dev / netif / ed / if_ed_isa.c
index d55e2ce..b3c9399 100644 (file)
@@ -24,8 +24,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/ed/if_ed_isa.c,v 1.5.2.2 2002/07/29 07:52:57 takawata Exp $
- * $DragonFly: src/sys/dev/netif/ed/if_ed_isa.c,v 1.5 2003/11/20 22:07:27 dillon Exp $
+ * $FreeBSD: src/sys/dev/ed/if_ed_isa.c,v 1.15 2003/10/31 18:31:58 brooks Exp $
+ * $DragonFly: src/sys/dev/netif/ed/if_ed_isa.c,v 1.13 2005/11/28 17:13:42 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <net/if_mib.h>
 
 #include <bus/isa/isavar.h>
-#include <bus/isa/pnpvar.h>
 
 #include "if_edvar.h"
 
 static int ed_isa_probe                (device_t);
 static int ed_isa_attach       (device_t);
+static int ed_isa_detach       (device_t);
 
 static struct isa_pnp_id ed_ids[] = {
        { 0x1684a34d,   NULL },         /* SMC8416 */
@@ -64,15 +64,11 @@ static struct isa_pnp_id ed_ids[] = {
 };
 
 static int
-ed_isa_probe(dev)
-       device_t dev;
+ed_isa_probe(device_t dev)
 {
-       struct ed_softc *sc = device_get_softc(dev);
        int flags = device_get_flags(dev);
        int error = 0;
 
-       bzero(sc, sizeof(struct ed_softc));
-
        /* Check isapnp ids */
        error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids);
 
@@ -98,6 +94,11 @@ ed_isa_probe(dev)
                goto end;
        ed_release_resources(dev);
 
+       error = ed_probe_SIC(dev, 0, flags);
+       if (error == 0)
+               goto end;
+       ed_release_resources(dev);
+
        error = ed_probe_Novell(dev, 0, flags);
        if (error == 0)
                goto end;
@@ -117,11 +118,9 @@ end:
 }
 
 static int
-ed_isa_attach(dev)
-       device_t dev;
+ed_isa_attach(device_t dev)
 {
        struct ed_softc *sc = device_get_softc(dev);
-       int flags = device_get_flags(dev);
        int error;
        
        if (sc->port_used > 0)
@@ -131,20 +130,45 @@ ed_isa_attach(dev)
 
        ed_alloc_irq(dev, sc->irq_rid, 0);
 
-       error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
-                              edintr, sc, &sc->irq_handle);
-       if (error) {
+       error = ed_attach(dev);
+       if (error == 0) {
+               error = bus_setup_intr(dev, sc->irq_res, INTR_NETSAFE,
+                                      edintr, sc, &sc->irq_handle,
+                                      sc->arpcom.ac_if.if_serializer);
+               if (error)
+                       ed_isa_detach(dev);
+       } else {
                ed_release_resources(dev);
-               return (error);
        }
+       return (error);
+}
 
-       return ed_attach(sc, device_get_unit(dev), flags);
+static int
+ed_isa_detach(device_t dev)
+{
+        struct ed_softc *sc = device_get_softc(dev);
+        struct ifnet *ifp = &sc->arpcom.ac_if;
+
+        lwkt_serialize_enter(ifp->if_serializer);
+        if (sc->gone) {
+                device_printf(dev, "already unloaded\n");
+                return (0);
+        }
+        ed_stop(sc);
+        ifp->if_flags &= ~IFF_RUNNING;
+        ether_ifdetach(ifp);
+        sc->gone = 1;
+        bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+        ed_release_resources(dev);
+        lwkt_serialize_exit(ifp->if_serializer);
+        return (0);
 }
 
 static device_method_t ed_isa_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,         ed_isa_probe),
        DEVMETHOD(device_attach,        ed_isa_attach),
+       DEVMETHOD(device_attach,        ed_isa_detach),
 
        { 0, 0 }
 };
@@ -155,6 +179,5 @@ static driver_t ed_isa_driver = {
        sizeof(struct ed_softc)
 };
 
-static devclass_t ed_isa_devclass;
-
-DRIVER_MODULE(if_ed, isa, ed_isa_driver, ed_isa_devclass, 0, 0);
+DRIVER_MODULE(if_ed, isa, ed_isa_driver, ed_devclass, 0, 0);
+MODULE_DEPEND(if_ed, isa, 1, 1, 1);