Make the Realtek PCI network interfaces detachable.

Use __arraycount to avoid null table entries.
Miscellaneous other touch-ups in bus front-ends.
This commit is contained in:
jakllsch 2010-07-27 21:02:00 +00:00
parent 0117c2837f
commit 28b0c5a3fd
6 changed files with 135 additions and 79 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -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;
}

View File

@ -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 <sys/cdefs.h>
__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;
}

View File

@ -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 <sys/cdefs.h>
__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;
}

View File

@ -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+ */

View File

@ -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 <sys/cdefs.h>
__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 <sys/types.h>
@ -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;
}

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -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;
}