aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2002-10-07 05:26:35 +0000
committerWarner Losh <imp@FreeBSD.org>2002-10-07 05:26:35 +0000
commit3097aa70be2f876f9534c9a80b4def27ade42ed6 (patch)
tree75cbd504f8a21d6b9e302e35b1ae8d2d74ebad31 /sys/dev
parentea5420299c3fb19204cf8a9f95cf990d5c24e67b (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dc/if_dc.c118
-rw-r--r--sys/dev/dc/if_dcreg.h3
2 files changed, 106 insertions, 15 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 5c330ff70194a..5219671889e3e 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -229,6 +229,7 @@ static void dc_eeprom_getword_pnic
(struct dc_softc *, int, u_int16_t *);
static void dc_eeprom_getword_xircom
(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_width (struct dc_softc *);
static void dc_read_eeprom (struct dc_softc *, caddr_t, int, int, int);
static void dc_mii_writebit (struct dc_softc *, int);
@@ -256,6 +257,7 @@ static void dc_reset (struct dc_softc *);
static int dc_list_rx_init (struct dc_softc *);
static int dc_list_tx_init (struct dc_softc *);
+static void dc_read_srom (struct dc_softc *, int);
static void dc_parse_21143_srom (struct dc_softc *);
static void dc_decode_leaf_sia (struct dc_softc *, struct dc_eblock_sia *);
static void dc_decode_leaf_mii (struct dc_softc *, struct dc_eblock_mii *);
@@ -330,6 +332,70 @@ dc_delay(sc)
CSR_READ_4(sc, DC_BUSCTL);
}
+void dc_eeprom_width(sc)
+ struct dc_softc *sc;
+{
+ int i;
+
+ /* Force EEPROM to idle state. */
+ dc_eeprom_idle(sc);
+
+ /* Enter EEPROM access mode. */
+ CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+ dc_delay(sc);
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+ dc_delay(sc);
+
+ for (i = 3; i--;) {
+ if (6 & (1 << i))
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+ else
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ }
+
+ for (i = 1; i <= 12; i++) {
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ break;
+ }
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ }
+
+ /* Turn off EEPROM access mode. */
+ dc_eeprom_idle(sc);
+
+ if (i < 4 || i > 12)
+ sc->dc_romwidth = 6;
+ else
+ sc->dc_romwidth = i;
+
+ /* Enter EEPROM access mode. */
+ CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+ dc_delay(sc);
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+ dc_delay(sc);
+
+ /* Turn off EEPROM access mode. */
+ dc_eeprom_idle(sc);
+}
+
static void
dc_eeprom_idle(sc)
struct dc_softc *sc;
@@ -371,21 +437,24 @@ dc_eeprom_putbyte(sc, addr)
{
register int d, i;
- /*
- * The AN985 has a 93C66 EEPROM on it instead of
- * a 93C46. It uses a different bit sequence for
- * specifying the "read" opcode.
- */
- if (DC_IS_CENTAUR(sc) || DC_IS_CONEXANT(sc))
- d = addr | (DC_EECMD_READ << 2);
- else
- d = addr | DC_EECMD_READ;
+ d = DC_EECMD_READ >> 6;
+ for (i = 3; i--; ) {
+ if (d & (1 << i))
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+ else
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+ dc_delay(sc);
+ DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+ dc_delay(sc);
+ }
/*
* Feed in each bit and strobe the clock.
*/
- for (i = 0x400; i; i >>= 1) {
- if (d & i) {
+ for (i = sc->dc_romwidth; i--;) {
+ if (addr & (1 << i)) {
SIO_SET(DC_SIO_EE_DATAIN);
} else {
SIO_CLR(DC_SIO_EE_DATAIN);
@@ -1767,6 +1836,17 @@ dc_decode_leaf_mii(sc, l)
return;
}
+void dc_read_srom(sc, bits)
+ struct dc_softc *sc;
+ int bits;
+{
+ int size;
+
+ size = 2 << bits;
+ sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
+ dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
+}
+
static void
dc_parse_21143_srom(sc)
struct dc_softc *sc;
@@ -1901,7 +1981,8 @@ dc_attach(dev)
sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL;
/* Save EEPROM contents so we can parse them later. */
- dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 512, 0);
+ dc_eeprom_width(sc);
+ dc_read_srom(sc, sc->dc_romwidth);
break;
case DC_DEVICEID_DM9100:
case DC_DEVICEID_DM9102:
@@ -1920,6 +2001,8 @@ dc_attach(dev)
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
+ dc_eeprom_width(sc);
+ dc_read_srom(sc, sc->dc_romwidth);
break;
case DC_DEVICEID_AN985:
case DC_DEVICEID_FE2500:
@@ -1928,6 +2011,8 @@ dc_attach(dev)
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
+ dc_eeprom_width(sc);
+ dc_read_srom(sc, sc->dc_romwidth);
break;
case DC_DEVICEID_98713:
case DC_DEVICEID_98713_CP:
@@ -1990,13 +2075,16 @@ dc_attach(dev)
* it to obtain a double word aligned buffer.
* The DC_TX_COALESCE flag is required.
*/
+ sc->dc_pmode = DC_PMODE_MII;
+ /* XXX Call the cardbus function to get nic from the CIS */
break;
case DC_DEVICEID_RS7112:
sc->dc_type = DC_TYPE_CONEXANT;
sc->dc_flags |= DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_REDUCED_MII_POLL;
sc->dc_pmode = DC_PMODE_MII;
- dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 256, 0);
+ dc_eeprom_width(sc);
+ dc_read_srom(sc, sc->dc_romwidth);
break;
default:
printf("dc%d: unknown device: %x\n", sc->dc_unit,
@@ -2060,13 +2148,15 @@ dc_attach(dev)
break;
case DC_TYPE_AL981:
case DC_TYPE_AN985:
+ bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
+ ETHER_ADDR_LEN);
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
break;
case DC_TYPE_CONEXANT:
bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr, 6);
break;
case DC_TYPE_XIRCOM:
- dc_read_eeprom(sc, (caddr_t)&eaddr, 3, 3, 0);
+
break;
default:
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
diff --git a/sys/dev/dc/if_dcreg.h b/sys/dev/dc/if_dcreg.h
index 3be7658ed8593..432d9be770b3a 100644
--- a/sys/dev/dc/if_dcreg.h
+++ b/sys/dev/dc/if_dcreg.h
@@ -710,13 +710,14 @@ struct dc_softc {
u_int8_t dc_pmode;
u_int8_t dc_link;
u_int8_t dc_cachesize;
+ int dc_romwidth;
int dc_pnic_rx_bug_save;
unsigned char *dc_pnic_rx_buf;
int dc_if_flags;
int dc_if_media;
u_int32_t dc_flags;
u_int32_t dc_txthresh;
- u_int8_t dc_srom[1024];
+ u_int8_t *dc_srom;
struct dc_mediainfo *dc_mi;
struct dc_list_data *dc_ldata;
struct dc_chain_data dc_cdata;