diff --git a/sys/dev/cardbus/if_re_cardbus.c b/sys/dev/cardbus/if_re_cardbus.c index 7c12520d6d66..f126b3e797ab 100644 --- a/sys/dev/cardbus/if_re_cardbus.c +++ b/sys/dev/cardbus/if_re_cardbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_re_cardbus.c,v 1.25 2010/03/18 20:51:42 dyoung Exp $ */ +/* $NetBSD: if_re_cardbus.c,v 1.26 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 2004 Jonathan Stone @@ -36,7 +36,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_re_cardbus.c,v 1.25 2010/03/18 20:51:42 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_re_cardbus.c,v 1.26 2010/07/27 21:02:00 jakllsch Exp $"); #include #include @@ -95,7 +95,6 @@ struct re_cardbus_softc { pcireg_t sc_csr; int sc_bar_reg; pcireg_t sc_bar_val; - bus_size_t sc_mapsize; cardbus_intr_line_t sc_intrline; }; @@ -170,14 +169,14 @@ re_cardbus_attach(device_t parent, device_t self, void *aux) csc->sc_csr = PCI_COMMAND_MASTER_ENABLE; #ifdef RTK_USEIOSPACE if (Cardbus_mapreg_map(ct, RTK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, - &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) { + &sc->rtk_btag, &sc->rtk_bhandle, &adr, &sc->rtk_bsize) == 0) { csc->sc_csr |= PCI_COMMAND_IO_ENABLE; csc->sc_bar_reg = RTK_PCI_LOIO; csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO; } #else if (Cardbus_mapreg_map(ct, RTK_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, - &sc->rtk_btag, &sc->rtk_bhandle, &adr, &csc->sc_mapsize) == 0) { + &sc->rtk_btag, &sc->rtk_bhandle, &adr, &sc->rtk_bsize) == 0) { csc->sc_csr |= PCI_COMMAND_MEM_ENABLE; csc->sc_bar_reg = RTK_PCI_LOMEM; csc->sc_bar_val = adr | PCI_MAPREG_TYPE_MEM; @@ -231,7 +230,7 @@ re_cardbus_detach(device_t self, int flags) */ if (csc->sc_bar_reg != 0) Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, - sc->rtk_btag, sc->rtk_bhandle, csc->sc_mapsize); + sc->rtk_btag, sc->rtk_bhandle, sc->rtk_bsize); return 0; } diff --git a/sys/dev/ic/rtl8169.c b/sys/dev/ic/rtl8169.c index 796208b6db10..40b01c4ece8c 100644 --- a/sys/dev/ic/rtl8169.c +++ b/sys/dev/ic/rtl8169.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtl8169.c,v 1.131 2010/04/09 10:40:59 nonaka Exp $ */ +/* $NetBSD: rtl8169.c,v 1.132 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.131 2010/04/09 10:40:59 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.132 2010/07/27 21:02:00 jakllsch Exp $"); /* $FreeBSD: /repoman/r/ncvs/src/sys/dev/re/if_re.c,v 1.20 2004/04/11 20:34:08 ru Exp $ */ /* @@ -955,6 +955,9 @@ re_detach(struct rtk_softc *sc) pmf_device_deregister(sc->sc_dev); + /* we don't want to run again */ + sc->sc_flags &= ~RTK_ATTACHED; + return 0; } diff --git a/sys/dev/ic/rtl81x9.c b/sys/dev/ic/rtl81x9.c index 829ffe655525..9ff785cd0504 100644 --- a/sys/dev/ic/rtl81x9.c +++ b/sys/dev/ic/rtl81x9.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtl81x9.c,v 1.90 2010/04/05 07:19:36 joerg Exp $ */ +/* $NetBSD: rtl81x9.c,v 1.91 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 1997, 1998 @@ -86,7 +86,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.90 2010/04/05 07:19:36 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtl81x9.c,v 1.91 2010/07/27 21:02:00 jakllsch Exp $"); #include "rnd.h" @@ -849,6 +849,9 @@ rtk_detach(struct rtk_softc *sc) RTK_RXBUFLEN + 16); bus_dmamem_free(sc->sc_dmat, &sc->sc_dmaseg, sc->sc_dmanseg); + /* we don't want to run again */ + sc->sc_flags &= ~RTK_ATTACHED; + return 0; } diff --git a/sys/dev/ic/rtl81x9var.h b/sys/dev/ic/rtl81x9var.h index 5e11336e0421..e944695471cc 100644 --- a/sys/dev/ic/rtl81x9var.h +++ b/sys/dev/ic/rtl81x9var.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtl81x9var.h,v 1.49 2009/09/05 03:50:49 tsutsui Exp $ */ +/* $NetBSD: rtl81x9var.h,v 1.50 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 1997, 1998 @@ -177,12 +177,13 @@ struct rtk_tx_desc { }; struct rtk_softc { - device_t sc_dev; /* generic device structures */ + device_t sc_dev; struct ethercom ethercom; /* interface info */ struct mii_data mii; struct callout rtk_tick_ch; /* tick callout */ - bus_space_handle_t rtk_bhandle; /* bus space handle */ bus_space_tag_t rtk_btag; /* bus space tag */ + bus_space_handle_t rtk_bhandle; /* bus space handle */ + bus_size_t rtk_bsize; /* bus space mapping size */ u_int sc_quirk; /* chip quirks */ #define RTKQ_8129 0x00000001 /* 8129 */ #define RTKQ_8139CPLUS 0x00000002 /* 8139C+ */ diff --git a/sys/dev/pci/if_re_pci.c b/sys/dev/pci/if_re_pci.c index 4e40dac5ae3b..f4f7926b3ef5 100644 --- a/sys/dev/pci/if_re_pci.c +++ b/sys/dev/pci/if_re_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_re_pci.c,v 1.38 2009/09/02 15:11:13 tsutsui Exp $ */ +/* $NetBSD: if_re_pci.c,v 1.39 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -46,7 +46,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_re_pci.c,v 1.38 2009/09/02 15:11:13 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_re_pci.c,v 1.39 2010/07/27 21:02:00 jakllsch Exp $"); #include @@ -76,14 +76,14 @@ struct re_pci_softc { void *sc_ih; pci_chipset_tag_t sc_pc; - pcitag_t sc_pcitag; }; static int re_pci_match(device_t, cfdata_t, void *); static void re_pci_attach(device_t, device_t, void *); +static int re_pci_detach(device_t, int); CFATTACH_DECL_NEW(re_pci, sizeof(struct re_pci_softc), - re_pci_match, re_pci_attach, NULL, NULL); + re_pci_match, re_pci_attach, re_pci_detach, NULL); /* * Various supported device vendors/types and their names. @@ -116,9 +116,23 @@ static const struct rtk_type re_devs[] = { { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_EG1032, RTK_8169, "Linksys EG1032 rev. 3 Gigabit Ethernet" }, - { 0, 0, 0, NULL } }; +static const struct rtk_type * +re_pci_lookup(const struct pci_attach_args * pa) +{ + int i; + + for(i = 0; i < __arraycount(re_devs); i++) { + if (PCI_VENDOR(pa->pa_id) != re_devs[i].rtk_vid) + continue; + if (PCI_PRODUCT(pa->pa_id) == re_devs[i].rtk_did) + return &re_devs[i]; + } + + return NULL; +} + #define RE_LINKSYS_EG1032_SUBID 0x00241737 /* @@ -128,7 +142,6 @@ static const struct rtk_type re_devs[] = { static int re_pci_match(device_t parent, cfdata_t cf, void *aux) { - const struct rtk_type *t; struct pci_attach_args *pa = aux; pcireg_t subid; @@ -140,6 +153,7 @@ re_pci_match(device_t parent, cfdata_t cf, void *aux) if (subid != RE_LINKSYS_EG1032_SUBID) return 0; } + /* Don't match 8139 other than C-PLUS */ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139) { @@ -147,15 +161,8 @@ re_pci_match(device_t parent, cfdata_t cf, void *aux) return 0; } - t = re_devs; - - while (t->rtk_name != NULL) { - if ((PCI_VENDOR(pa->pa_id) == t->rtk_vid) && - (PCI_PRODUCT(pa->pa_id) == t->rtk_did)) { - return 2; /* defect rtk(4) */ - } - t++; - } + if (re_pci_lookup(pa) != NULL) + return 2; /* defeat rtk(4) */ return 0; } @@ -171,22 +178,22 @@ re_pci_attach(device_t parent, device_t self, void *aux) const char *intrstr = NULL; const struct rtk_type *t; uint32_t hwrev; - int error = 0; pcireg_t command, memtype; bool ioh_valid, memh_valid; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; - bus_size_t iosize, memsize, bsize; + bus_size_t iosize, memsize; sc->sc_dev = self; + psc->sc_pc = pa->pa_pc; - /* - * Map control/status registers. - */ command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); command |= PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); + /* + * Map control/status registers. + */ ioh_valid = (pci_mapreg_map(pa, RTK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, &iosize) == 0); memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, RTK_PCI_LOMEM); @@ -204,26 +211,20 @@ re_pci_attach(device_t parent, device_t self, void *aux) if (ioh_valid) { sc->rtk_btag = iot; sc->rtk_bhandle = ioh; - bsize = iosize; + sc->rtk_bsize = iosize; + if (memh_valid) + bus_space_unmap(memt, memh, memsize); } else if (memh_valid) { sc->rtk_btag = memt; sc->rtk_bhandle = memh; - bsize = memsize; + sc->rtk_bsize = memsize; } else { aprint_error(": can't map registers\n"); return; } - t = re_devs; - hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV; - - while (t->rtk_name != NULL) { - if ((PCI_VENDOR(pa->pa_id) == t->rtk_vid) && - (PCI_PRODUCT(pa->pa_id) == t->rtk_did)) { - break; - } - t++; - } + t = re_pci_lookup(pa); + KASSERT(t != NULL); aprint_normal(": %s (rev. 0x%02x)\n", t->rtk_name, PCI_REVISION(pa->pa_class)); @@ -262,28 +263,45 @@ re_pci_attach(device_t parent, device_t self, void *aux) re_attach(sc); + hwrev = CSR_READ_4(sc, RTK_TXCFG) & RTK_TXCFG_HWREV; + /* * Perform hardware diagnostic on the original RTL8169. * Some 32-bit cards were incorrectly wired and would * malfunction if plugged into a 64-bit slot. */ if (hwrev == RTK_HWREV_8169) { - error = re_diag(sc); - if (error) { - aprint_error_dev(self, - "attach aborted due to hardware diag failure\n"); - - re_detach(sc); - - if (psc->sc_ih != NULL) { - pci_intr_disestablish(pc, psc->sc_ih); - psc->sc_ih = NULL; - } - - if (ioh_valid) - bus_space_unmap(iot, ioh, iosize); - if (memh_valid) - bus_space_unmap(memt, memh, memsize); + if (re_diag(sc)) { + re_pci_detach(self, 0); + aprint_error_dev(self, "disabled\n"); } } } + +static int +re_pci_detach(device_t self, int flags) +{ + struct re_pci_softc *psc = device_private(self); + struct rtk_softc *sc = &psc->sc_rtk; + int rv; + + if ((sc->sc_flags & RTK_ATTACHED) != 0) + /* re_stop() */ + sc->ethercom.ec_if.if_stop(&sc->ethercom.ec_if, 0); + + rv = re_detach(sc); + if (rv) + return rv; + + if (psc->sc_ih != NULL) { + pci_intr_disestablish(psc->sc_pc, psc->sc_ih); + psc->sc_ih = NULL; + } + + if (sc->rtk_bsize != 0) { + bus_space_unmap(sc->rtk_btag, sc->rtk_bhandle, sc->rtk_bsize); + sc->rtk_bsize = 0; + } + + return 0; +} diff --git a/sys/dev/pci/if_rtk_pci.c b/sys/dev/pci/if_rtk_pci.c index 28c7e3bb0dfb..b4177c33dff2 100644 --- a/sys/dev/pci/if_rtk_pci.c +++ b/sys/dev/pci/if_rtk_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_rtk_pci.c,v 1.40 2009/11/26 15:17:09 njoly Exp $ */ +/* $NetBSD: if_rtk_pci.c,v 1.41 2010/07/27 21:02:00 jakllsch Exp $ */ /* * Copyright (c) 1997, 1998 @@ -47,7 +47,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_rtk_pci.c,v 1.40 2009/11/26 15:17:09 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_rtk_pci.c,v 1.41 2010/07/27 21:02:00 jakllsch Exp $"); #include #include @@ -82,6 +82,7 @@ struct rtk_pci_softc { /* PCI-specific goo.*/ void *sc_ih; + pci_chipset_tag_t sc_pc; }; static const struct rtk_type rtk_pci_devs[] = { @@ -107,26 +108,27 @@ static const struct rtk_type rtk_pci_devs[] = { RTK_8139, "D-Link Systems DFE 530TX+" }, { PCI_VENDOR_NORTEL, PCI_PRODUCT_NORTEL_BAYSTACK_21, RTK_8139, "Baystack 21 (MPX EN5038) 10/100BaseTX" }, - { 0, 0, 0, NULL } }; static int rtk_pci_match(device_t, cfdata_t, void *); static void rtk_pci_attach(device_t, device_t, void *); +static int rtk_pci_detach(device_t, int); CFATTACH_DECL_NEW(rtk_pci, sizeof(struct rtk_pci_softc), - rtk_pci_match, rtk_pci_attach, NULL, NULL); + rtk_pci_match, rtk_pci_attach, rtk_pci_detach, NULL); static const struct rtk_type * rtk_pci_lookup(const struct pci_attach_args *pa) { - const struct rtk_type *t; + int i; - for (t = rtk_pci_devs; t->rtk_name != NULL; t++) { - if (PCI_VENDOR(pa->pa_id) == t->rtk_vid && - PCI_PRODUCT(pa->pa_id) == t->rtk_did) { - return (t); - } + for (i = 0; i < __arraycount(rtk_pci_devs); i++) { + if (PCI_VENDOR(pa->pa_id) != rtk_pci_devs[i].rtk_vid) + continue; + if (PCI_PRODUCT(pa->pa_id) == rtk_pci_devs[i].rtk_did) + return &rtk_pci_devs[i]; } + return NULL; } @@ -155,17 +157,16 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) pci_intr_handle_t ih; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; + bus_size_t iosize, memsize; const char *intrstr = NULL; const struct rtk_type *t; - int ioh_valid, memh_valid; + bool ioh_valid, memh_valid; sc->sc_dev = self; + psc->sc_pc = pa->pa_pc; t = rtk_pci_lookup(pa); - if (t == NULL) { - aprint_normal("\n"); - panic("%s: impossible", __func__); - } + KASSERT(t != NULL); aprint_naive("\n"); aprint_normal(": %s (rev. 0x%02x)\n", @@ -184,19 +185,23 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) * on the part of Realtek. Memory mapped mode does appear to * work on uniprocessor systems though. * - * On NetBSD, some port doesn't support PCI I/O space properly, + * On NetBSD, some ports don't support PCI I/O space properly, * so we try to map both and prefer I/O space to mem space. */ ioh_valid = (pci_mapreg_map(pa, RTK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, - &iot, &ioh, NULL, NULL) == 0); + &iot, &ioh, NULL, &iosize) == 0); memh_valid = (pci_mapreg_map(pa, RTK_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0, - &memt, &memh, NULL, NULL) == 0); + &memt, &memh, NULL, &memsize) == 0); if (ioh_valid) { sc->rtk_btag = iot; sc->rtk_bhandle = ioh; + sc->rtk_bsize = iosize; + if (memh_valid) + bus_space_unmap(memt, memh, memsize); } else if (memh_valid) { sc->rtk_btag = memt; sc->rtk_bhandle = memh; + sc->rtk_bsize = memsize; } else { aprint_error_dev(self, "can't map registers\n"); return; @@ -232,3 +237,30 @@ rtk_pci_attach(device_t parent, device_t self, void *aux) rtk_attach(sc); } + +static int +rtk_pci_detach(device_t self, int flags) +{ + struct rtk_pci_softc *psc = device_private(self); + struct rtk_softc *sc = &psc->sc_rtk; + int rv; + + /* rtk_stop() */ + sc->ethercom.ec_if.if_stop(&sc->ethercom.ec_if, 0); + + rv = rtk_detach(sc); + if (rv) + return rv; + + if (psc->sc_ih != NULL) { + pci_intr_disestablish(psc->sc_pc, psc->sc_ih); + psc->sc_ih = NULL; + } + + if (sc->rtk_bsize != 0) { + bus_space_unmap(sc->rtk_btag, sc->rtk_bhandle, sc->rtk_bsize); + sc->rtk_bsize = 0; + } + + return 0; +}