From db05febdfa07ec9b7458b994146df99e05536ded Mon Sep 17 00:00:00 2001 From: sommerfeld Date: Sat, 30 Oct 1999 16:07:58 +0000 Subject: [PATCH] Add enable/disable support and EEPROM size selection, prerequisites for getting the cardbus fxp attachment to work. Tested on the built-in 82559 in a VAIO Z505S. From Johan Danielsson / PR8631; changed slightly to KNF. --- sys/dev/ic/i82557.c | 80 +++++++++++++++++++++++++++++++++++++++- sys/dev/ic/i82557var.h | 13 ++++++- sys/dev/pci/if_fxp_pci.c | 6 ++- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/sys/dev/ic/i82557.c b/sys/dev/ic/i82557.c index 46fd9b960e3a..861d621b9ad9 100644 --- a/sys/dev/ic/i82557.c +++ b/sys/dev/ic/i82557.c @@ -1,4 +1,4 @@ -/* $NetBSD: i82557.c,v 1.9 1999/10/28 19:21:51 sommerfeld Exp $ */ +/* $NetBSD: i82557.c,v 1.10 1999/10/30 16:07:58 sommerfeld Exp $ */ /*- * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. @@ -191,6 +191,9 @@ void fxp_power __P((int, void *)); int fxp_copy_small = 0; +int fxp_enable __P((struct fxp_softc*)); +void fxp_disable __P((struct fxp_softc*)); + struct fxp_phytype { int fp_phy; /* type of PHY, -1 for MII at the end. */ void (*fp_init) __P((struct fxp_softc *)); @@ -480,6 +483,34 @@ fxp_get_info(sc, enaddr) CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); DELAY(10); + /* + * Figure out EEPROM size. + * + * Cards can have either 64-word or 256-word EEPROMs, with + * addresses fed in using a bit-at-a-time protocol, MSB first. + * + * XXX this is probably not the best way to do this; the linux + * driver does a checksum of the eeprom, but there is + * (AFAIK) no on-line documentation on what this checksum + * should look like (you could just steal the code from + * linux, but that's cheating); for now we just use the fact + * that the upper two bits of word 10 should be 01 + */ + for(sc->sc_eeprom_size = 6; + sc->sc_eeprom_size <= 8; + sc->sc_eeprom_size += 2) { + fxp_read_eeprom(sc, &data, 10, 1); + if((data & 0xc000) == 0x4000) + break; + } + if(sc->sc_eeprom_size > 8) + panic("%s: failed to get EEPROM size", sc->sc_dev.dv_xname); +#ifdef DEBUG + printf("%s: assuming %d word EEPROM\n", + sc->sc_dev.dv_xname, + 1 << sc->sc_eeprom_size); +#endif + /* * Get info about the primary PHY */ @@ -533,7 +564,7 @@ fxp_read_eeprom(sc, data, offset, words) /* * Shift in address. */ - for (x = 6; x > 0; x--) { + for (x = sc->sc_eeprom_size; x > 0; x--) { if ((i + offset) & (1 << (x - 1))) { reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; } else { @@ -1380,6 +1411,12 @@ fxp_mii_mediastatus(ifp, ifmr) { struct fxp_softc *sc = ifp->if_softc; + if(sc->sc_enabled == 0) { + ifmr->ifm_active = IFM_ETHER | IFM_NONE; + ifmr->ifm_status = 0; + return; + } + mii_pollstat(&sc->sc_mii); ifmr->ifm_status = sc->sc_mii.mii_media_status; ifmr->ifm_active = sc->sc_mii.mii_media_active; @@ -1521,6 +1558,8 @@ fxp_ioctl(ifp, command, data) switch (command) { case SIOCSIFADDR: + if ((error = fxp_enable(sc)) != 0) + break; ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) { @@ -1568,24 +1607,33 @@ fxp_ioctl(ifp, command, data) * stop it. */ fxp_stop(sc, 1); + fxp_disable(sc); } else if ((ifp->if_flags & IFF_UP) != 0 && (ifp->if_flags & IFF_RUNNING) == 0) { /* * If interface is marked up and it is stopped, then * start it. */ + if((error = fxp_enable(sc)) != 0) + break; error = fxp_init(sc); } else if ((ifp->if_flags & IFF_UP) != 0) { /* * Reset the interface to pick up change in any other * flags that affect the hardware state. */ + if((error = fxp_enable(sc)) != 0) + break; error = fxp_init(sc); } break; case SIOCADDMULTI: case SIOCDELMULTI: + if(sc->sc_enabled == 0) { + error = EIO; + break; + } error = (command == SIOCADDMULTI) ? ether_addmulti(ifr, &sc->sc_ethercom) : ether_delmulti(ifr, &sc->sc_ethercom); @@ -1700,3 +1748,31 @@ fxp_mc_setup(sc) BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); } while ((mcsp->cb_status & FXP_CB_STATUS_C) == 0); } + +int +fxp_enable(sc) + struct fxp_softc *sc; +{ + + if (sc->sc_enabled == 0 && sc->sc_enable != NULL) { + if ((*sc->sc_enable)(sc) != 0) { + printf("%s: device enable failed\n", + sc->sc_dev.dv_xname); + return (EIO); + } + } + + sc->sc_enabled = 1; + + return 0; +} + +void +fxp_disable(sc) + struct fxp_softc *sc; +{ + if (sc->sc_enabled != 0 && sc->sc_disable != NULL) { + (*sc->sc_disable)(sc); + sc->sc_enabled = 0; + } +} diff --git a/sys/dev/ic/i82557var.h b/sys/dev/ic/i82557var.h index 2b8cae301e79..3bcd83c7df15 100644 --- a/sys/dev/ic/i82557var.h +++ b/sys/dev/ic/i82557var.h @@ -1,4 +1,4 @@ -/* $NetBSD: i82557var.h,v 1.7 1999/10/28 19:21:51 sommerfeld Exp $ */ +/* $NetBSD: i82557var.h,v 1.8 1999/10/30 16:07:58 sommerfeld Exp $ */ /*- * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. @@ -199,9 +199,16 @@ struct fxp_softc { int phy_primary_addr; /* address of primary PHY */ int phy_primary_device; /* device type of primary PHY */ int phy_10Mbps_only; /* PHY is 10Mbps-only device */ + + int sc_enabled; /* boolean; power enabled on interface */ + int (*sc_enable) __P((struct fxp_softc *)); + void (*sc_disable) __P((struct fxp_softc *)); + + int sc_eeprom_size; /* log2 size of EEPROM */ #if NRND > 0 rndsource_element_t rnd_source; /* random source */ #endif + }; #define FXP_RXMAP_GET(sc) ((sc)->sc_rxmaps[(sc)->sc_rxfree++]) @@ -307,3 +314,7 @@ do { \ void fxp_attach __P((struct fxp_softc *)); int fxp_intr __P((void *)); + +int fxp_enable __P((struct fxp_softc*)); +void fxp_disable __P((struct fxp_softc*)); + diff --git a/sys/dev/pci/if_fxp_pci.c b/sys/dev/pci/if_fxp_pci.c index 3ebeecb8dbe2..70d251dc54ff 100644 --- a/sys/dev/pci/if_fxp_pci.c +++ b/sys/dev/pci/if_fxp_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_fxp_pci.c,v 1.1 1999/06/20 16:35:40 thorpej Exp $ */ +/* $NetBSD: if_fxp_pci.c,v 1.2 1999/10/30 16:07:59 sommerfeld Exp $ */ /*- * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. @@ -135,6 +135,10 @@ fxp_pci_attach(parent, self, aux) bus_size_t size; int flags; + sc->sc_enabled = 1; + sc->sc_enable = NULL; + sc->sc_disable = NULL; + /* * Map control/status registers. */