Fix some problems reported by Mike Pritchard:

- Add a flag DC_TX_INTR_ALWAYS which causes the transmit code to
  request a TX done interrupt for every packet. The PNIC seems to need
  this to insure that the sent TX buffers get reaped in a timely fashion.

- Try to unreset the SIA as soon as possible after resetting the whole
  chip.

- Change dcphy to support either 10/100 or 10Mbps only NICs. The
  built-in 21143 ethernet in Compaq Presario machines is 10Mbps only
  and it doesn't work right if we try to advertise 100Mbps modes during
  autoneg. When restricted to only 10mbps modes, it works fine.

  Note that for now, I detect this condition by checking the PCI
  subsystem ID on this NIC (which has a Compaq vendor/device ID).
  Yes, I know that's what the SROM is supposed to be for. I'm deliberately
  ignoring the SROM wherever possible. Sue me.

The latter two fixes allow if_dc to work correctly with the built-in
ethernet on certain Compaq Presario boxes. There are liable to be quite
a few people using these as their home systems who might want to try
FreeBSD; may as well be nice to them.

Now if anybody out there has an Alpha miata with 10Mbps ethernet and
can show me the output from pciconf -l on their system, I'd be grateful.
This commit is contained in:
wpaul 1999-12-13 21:45:13 +00:00
parent 81282dc103
commit 20bb20f965
6 changed files with 74 additions and 20 deletions

View File

@ -86,6 +86,13 @@ static const char rcsid[] =
#define MIIF_AUTOTIMEOUT 0x0004
/*
* This is the subsystem ID for the built-in 21143 ethernet
* in several Compaq Presario systems. Apparently these are
* 10Mbps only, so we need to treat them specially.
*/
#define COMPAQ_PRESARIO_ID 0xb0bb0e11
static int dcphy_probe __P((device_t));
static int dcphy_attach __P((device_t));
static int dcphy_detach __P((device_t));
@ -161,9 +168,6 @@ static int dcphy_attach(dev)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
/*dcphy_reset(sc);*/
dc_sc = mii->mii_ifp->if_softc;
CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0);
@ -171,11 +175,14 @@ static int dcphy_attach(dev)
switch(pci_read_config(device_get_parent(sc->mii_dev),
DC_PCI_CSID, 4)) {
case 0x99999999:
case COMPAQ_PRESARIO_ID:
/* Example of how to only allow 10Mbps modes. */
sc->mii_capabilities = BMSR_10TFDX|BMSR_10THDX;
sc->mii_capabilities = BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
break;
default:
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
sc->mii_inst), BMCR_LOOP|BMCR_S100);
sc->mii_capabilities =
BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
BMSR_10TFDX|BMSR_10THDX;
@ -418,11 +425,14 @@ dcphy_status(sc)
if (CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_LP_CAN_NWAY) {
anlpar = CSR_READ_4(dc_sc, DC_10BTSTAT) >> 16;
if (anlpar & ANLPAR_T4)
if (anlpar & ANLPAR_T4 &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
else if (anlpar & ANLPAR_TX_FD &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_TX)
else if (anlpar & ANLPAR_TX &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_TX;
else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX;
@ -478,7 +488,10 @@ dcphy_auto(mii, waitfor)
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
if (mii->mii_capabilities & BMSR_100TXHDX)
CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
else
CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFF);
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_SETBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
DC_SETBIT(sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE);

View File

@ -1247,6 +1247,15 @@ static void dc_reset(sc)
CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000);
CSR_WRITE_4(sc, DC_NETCFG, 0x00000000);
/*
* Bring the SIA out of reset. In some cases, it looks
* like failing to unreset the SIA soon enough gets it
* into a state where it will never come out of reset
* until we reset the whole chip again.
*/
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
return;
}
@ -1480,7 +1489,7 @@ static int dc_attach(dev)
break;
case DC_DEVICEID_82C168:
sc->dc_type = DC_TYPE_PNIC;
sc->dc_flags |= DC_TX_STORENFWD|DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT);
if (revision < DC_REVISION_82C169)
@ -2220,6 +2229,8 @@ static void dc_intr(arg)
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else if (sc->dc_flags & DC_TX_STORENFWD) {
printf("resetting\n");
} else {
sc->dc_txthresh += 0x4000;
printf("increasing TX threshold\n");
@ -2302,6 +2313,8 @@ static int dc_encap(sc, m_head, txidx)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_LASTFRAG;
if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG)
sc->dc_ldata->dc_tx_list[*txidx].dc_ctl |= DC_TXCTL_FINT;
if (sc->dc_flags & DC_TX_INTR_ALWAYS)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
sc->dc_ldata->dc_tx_list[*txidx].dc_status = DC_TXSTAT_OWN;

View File

@ -667,6 +667,7 @@ struct dc_softc {
#define DC_TX_FIXED_RING 0x00000080
#define DC_TX_STORENFWD 0x00000100
#define DC_REDUCED_MII_POLL 0x00000200
#define DC_TX_INTR_ALWAYS 0x00000400
/*
* register space access macros

View File

@ -86,6 +86,13 @@ static const char rcsid[] =
#define MIIF_AUTOTIMEOUT 0x0004
/*
* This is the subsystem ID for the built-in 21143 ethernet
* in several Compaq Presario systems. Apparently these are
* 10Mbps only, so we need to treat them specially.
*/
#define COMPAQ_PRESARIO_ID 0xb0bb0e11
static int dcphy_probe __P((device_t));
static int dcphy_attach __P((device_t));
static int dcphy_detach __P((device_t));
@ -161,9 +168,6 @@ static int dcphy_attach(dev)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
/*dcphy_reset(sc);*/
dc_sc = mii->mii_ifp->if_softc;
CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0);
@ -171,11 +175,14 @@ static int dcphy_attach(dev)
switch(pci_read_config(device_get_parent(sc->mii_dev),
DC_PCI_CSID, 4)) {
case 0x99999999:
case COMPAQ_PRESARIO_ID:
/* Example of how to only allow 10Mbps modes. */
sc->mii_capabilities = BMSR_10TFDX|BMSR_10THDX;
sc->mii_capabilities = BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX;
break;
default:
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
sc->mii_inst), BMCR_LOOP|BMCR_S100);
sc->mii_capabilities =
BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX|
BMSR_10TFDX|BMSR_10THDX;
@ -418,11 +425,14 @@ dcphy_status(sc)
if (CSR_READ_4(dc_sc, DC_10BTSTAT) & DC_TSTAT_LP_CAN_NWAY) {
anlpar = CSR_READ_4(dc_sc, DC_10BTSTAT) >> 16;
if (anlpar & ANLPAR_T4)
if (anlpar & ANLPAR_T4 &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
else if (anlpar & ANLPAR_TX_FD &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
else if (anlpar & ANLPAR_TX)
else if (anlpar & ANLPAR_TX &&
sc->mii_capabilities & BMSR_100TXHDX)
mii->mii_media_active |= IFM_100_TX;
else if (anlpar & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T|IFM_FDX;
@ -478,7 +488,10 @@ dcphy_auto(mii, waitfor)
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
if (mii->mii_capabilities & BMSR_100TXHDX)
CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
else
CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFF);
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_SETBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
DC_SETBIT(sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE);

View File

@ -1247,6 +1247,15 @@ static void dc_reset(sc)
CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000);
CSR_WRITE_4(sc, DC_NETCFG, 0x00000000);
/*
* Bring the SIA out of reset. In some cases, it looks
* like failing to unreset the SIA soon enough gets it
* into a state where it will never come out of reset
* until we reset the whole chip again.
*/
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
return;
}
@ -1480,7 +1489,7 @@ static int dc_attach(dev)
break;
case DC_DEVICEID_82C168:
sc->dc_type = DC_TYPE_PNIC;
sc->dc_flags |= DC_TX_STORENFWD|DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_STORENFWD|DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT);
if (revision < DC_REVISION_82C169)
@ -2220,6 +2229,8 @@ static void dc_intr(arg)
if (sc->dc_txthresh == DC_TXTHRESH_160BYTES) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else if (sc->dc_flags & DC_TX_STORENFWD) {
printf("resetting\n");
} else {
sc->dc_txthresh += 0x4000;
printf("increasing TX threshold\n");
@ -2302,6 +2313,8 @@ static int dc_encap(sc, m_head, txidx)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_LASTFRAG;
if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG)
sc->dc_ldata->dc_tx_list[*txidx].dc_ctl |= DC_TXCTL_FINT;
if (sc->dc_flags & DC_TX_INTR_ALWAYS)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
sc->dc_ldata->dc_tx_list[cur].dc_ctl |= DC_TXCTL_FINT;
sc->dc_ldata->dc_tx_list[*txidx].dc_status = DC_TXSTAT_OWN;

View File

@ -667,6 +667,7 @@ struct dc_softc {
#define DC_TX_FIXED_RING 0x00000080
#define DC_TX_STORENFWD 0x00000100
#define DC_REDUCED_MII_POLL 0x00000200
#define DC_TX_INTR_ALWAYS 0x00000400
/*
* register space access macros