summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2011-02-18 02:14:53 +0000
committeryongari <yongari@FreeBSD.org>2011-02-18 02:14:53 +0000
commitdc543f1c565aff6c848614be2c8831e4d6711e28 (patch)
treeff4c31ff67cd1056e6e77d4ae150a1f2ceebe3dd /sys/dev
parentc06fd95fe5e99df3b53a22cef747f99a883dd98a (diff)
downloadFreeBSD-src-dc543f1c565aff6c848614be2c8831e4d6711e28.zip
FreeBSD-src-dc543f1c565aff6c848614be2c8831e4d6711e28.tar.gz
When driver have to use base softc due to lack of SROM on second
port, copy SROM information from base softc as well and run SROM parser again. This change is necessary for some dual port controllers to make dc(4) correctly detect PHY media based on first port configuration table. While I'm here add a check for validity of the base softc before duplicating SROM contents from base softc. If driver failed to attach to the first port it can access invalid area. PR: kern/79262 Reviewed by: marius
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dc/if_dc.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 40752a8..14e68e1 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -1815,6 +1815,7 @@ dc_attach(device_t dev)
u_int32_t command;
struct dc_softc *sc;
struct ifnet *ifp;
+ struct dc_mediainfo *m;
u_int32_t reg, revision;
int error, i, mac_offset, phy, rid, tmp;
u_int8_t *mac;
@@ -2108,8 +2109,24 @@ dc_attach(device_t dev)
if ((sc->dc_eaddr[0] == 0 && (sc->dc_eaddr[1] & ~0xffff) == 0) ||
(sc->dc_eaddr[0] == 0xffffffff &&
(sc->dc_eaddr[1] & 0xffff) == 0xffff)) {
- if (dc_check_multiport(sc) == 0)
+ error = dc_check_multiport(sc);
+ if (error == 0) {
bcopy(sc->dc_eaddr, eaddr, sizeof(eaddr));
+ /* Extract media information. */
+ if (DC_IS_INTEL(sc) && sc->dc_srom != NULL) {
+ while (sc->dc_mi != NULL) {
+ m = sc->dc_mi->dc_next;
+ free(sc->dc_mi, M_DEVBUF);
+ sc->dc_mi = m;
+ }
+ error = dc_parse_21143_srom(sc);
+ if (error != 0)
+ goto fail;
+ }
+ } else if (error == ENOMEM)
+ goto fail;
+ else
+ error = 0;
}
/* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
@@ -3875,12 +3892,30 @@ dc_check_multiport(struct dc_softc *sc)
continue;
if (unit > device_get_unit(sc->dc_dev))
continue;
+ if (device_is_attached(child) == 0)
+ continue;
dsc = device_get_softc(child);
- device_printf(sc->dc_dev, "Using station address of %s as base",
+ device_printf(sc->dc_dev,
+ "Using station address of %s as base\n",
device_get_nameunit(child));
bcopy(dsc->dc_eaddr, sc->dc_eaddr, ETHER_ADDR_LEN);
eaddr = (uint8_t *)sc->dc_eaddr;
eaddr[5]++;
+ /* Prepare SROM to parse again. */
+ if (DC_IS_INTEL(sc) && dsc->dc_srom != NULL &&
+ sc->dc_romwidth != 0) {
+ free(sc->dc_srom, M_DEVBUF);
+ sc->dc_romwidth = dsc->dc_romwidth;
+ sc->dc_srom = malloc(DC_ROM_SIZE(sc->dc_romwidth),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->dc_srom == NULL) {
+ device_printf(sc->dc_dev,
+ "Could not allocate SROM buffer\n");
+ return (ENOMEM);
+ }
+ bcopy(dsc->dc_srom, sc->dc_srom,
+ DC_ROM_SIZE(sc->dc_romwidth));
+ }
return (0);
}
return (ENOENT);
OpenPOWER on IntegriCloud