Various updates for the ThunderLAN driver:
- When trying to map ports, if mapping TL_PCI_LOIO or TL_PCI_LOMEM fails, try mapping the other one. Apparently, some ThunderLAN parts swap these two registers while others don't. - Add support for bitrate (non-MII) PHYs. If no MII-based PHY is found, program the chip for bitrate mode. This is required for the TNETE110 part, which doesn't have MII support. (It's also obsolete, but there are still some people out there who have them.) With this change and the change above, the Compaq Netflex-3/P 10baseT/BNC board works correctly. (Thanks to Matthew Dodd for getting me one of these cards.) - Convert to bus_space_foo() for register accesses. - Add changes to support FreeBSD/Alpha. I still have to actually test this in my Alpha box so I'm not going to update /sys/alpha/conf/GENERIC yet.
This commit is contained in:
parent
94678b53d5
commit
85c47a212e
178
sys/pci/if_tl.c
178
sys/pci/if_tl.c
@ -29,7 +29,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: if_tl.c,v 1.25 1999/01/26 15:18:26 wpaul Exp $
|
||||
* $Id: if_tl.c,v 1.37 1999/03/30 16:59:06 wpaul Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -201,6 +201,9 @@
|
||||
#include <vm/vm.h> /* for vtophys */
|
||||
#include <vm/pmap.h> /* for vtophys */
|
||||
#include <machine/clock.h> /* for DELAY */
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus_pio.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
@ -218,48 +221,7 @@
|
||||
|
||||
#if !defined(lint)
|
||||
static const char rcsid[] =
|
||||
"$Id: if_tl.c,v 1.25 1999/01/26 15:18:26 wpaul Exp $";
|
||||
#endif
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
#define EV_TXEOC 2
|
||||
#define EV_TXEOF 3
|
||||
#define EV_RXEOC 4
|
||||
#define EV_RXEOF 5
|
||||
#define EV_START_TX 6
|
||||
#define EV_START_Q 7
|
||||
#define EV_SETMODE 8
|
||||
#define EV_AUTONEG_XMIT 9
|
||||
#define EV_AUTONEG_FIN 10
|
||||
#define EV_START_TX_REAL 11
|
||||
#define EV_WATCHDOG 12
|
||||
#define EV_INIT 13
|
||||
|
||||
static void evset(sc, e)
|
||||
struct tl_softc *sc;
|
||||
int e;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 19; i > 0; i--)
|
||||
sc->tl_event[i] = sc->tl_event[i - 1];
|
||||
sc->tl_event[0] = e;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void evshow(sc)
|
||||
struct tl_softc *sc;
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("tl%d: events: ", sc->tl_unit);
|
||||
for (i = 0; i < 20; i++)
|
||||
printf(" %d", sc->tl_event[i]);
|
||||
printf("\n");
|
||||
|
||||
return;
|
||||
}
|
||||
"$Id: if_tl.c,v 1.37 1999/03/30 16:59:06 wpaul Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -933,9 +895,6 @@ static void tl_autoneg(sc, flag, verbose)
|
||||
DELAY(5000000);
|
||||
break;
|
||||
case TL_FLAG_SCHEDDELAY:
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_AUTONEG_XMIT);
|
||||
#endif
|
||||
/*
|
||||
* Wait for the transmitter to go idle before starting
|
||||
* an autoneg session, otherwise tl_start() may clobber
|
||||
@ -956,9 +915,6 @@ static void tl_autoneg(sc, flag, verbose)
|
||||
sc->tl_want_auto = 0;
|
||||
return;
|
||||
case TL_FLAG_DELAYTIMEO:
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_AUTONEG_FIN);
|
||||
#endif
|
||||
ifp->if_timer = 0;
|
||||
sc->tl_autoneg = 0;
|
||||
break;
|
||||
@ -1066,6 +1022,22 @@ static void tl_setmode(sc, media)
|
||||
{
|
||||
u_int16_t bmcr;
|
||||
|
||||
if (sc->tl_bitrate) {
|
||||
if (IFM_SUBTYPE(media) == IFM_10_5)
|
||||
tl_dio_setbit(sc, TL_ACOMMIT, TL_AC_MTXD1);
|
||||
if (IFM_SUBTYPE(media) == IFM_10_T) {
|
||||
tl_dio_clrbit(sc, TL_ACOMMIT, TL_AC_MTXD1);
|
||||
if ((media & IFM_GMASK) == IFM_FDX) {
|
||||
tl_dio_clrbit(sc, TL_ACOMMIT, TL_AC_MTXD3);
|
||||
tl_dio_setbit(sc, TL_NETCMD, TL_CMD_DUPLEX);
|
||||
} else {
|
||||
tl_dio_setbit(sc, TL_ACOMMIT, TL_AC_MTXD3);
|
||||
tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_DUPLEX);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bmcr = tl_phy_readreg(sc, PHY_BMCR);
|
||||
|
||||
bmcr &= ~(PHY_BMCR_SPEEDSEL|PHY_BMCR_DUPLEX|PHY_BMCR_AUTONEGENBL|
|
||||
@ -1319,12 +1291,16 @@ static void tl_softreset(sc, internal)
|
||||
* one fragment mode.
|
||||
*/
|
||||
tl_dio_setbit16(sc, TL_NETCONFIG, TL_CFG_ONECHAN|TL_CFG_ONEFRAG);
|
||||
if (internal) {
|
||||
if (internal && !sc->tl_bitrate) {
|
||||
tl_dio_setbit16(sc, TL_NETCONFIG, TL_CFG_PHYEN);
|
||||
} else {
|
||||
tl_dio_clrbit16(sc, TL_NETCONFIG, TL_CFG_PHYEN);
|
||||
}
|
||||
|
||||
/* Handle cards with bitrate devices. */
|
||||
if (sc->tl_bitrate)
|
||||
tl_dio_setbit16(sc, TL_NETCONFIG, TL_CFG_BITRATE);
|
||||
|
||||
/* Set PCI burst size */
|
||||
tl_dio_write8(sc, TL_BSIZEREG, 0x33);
|
||||
|
||||
@ -1585,7 +1561,20 @@ tl_attach(config_id, unit)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sc->iobase = pci_conf_read(config_id, TL_PCI_LOIO) & 0xFFFFFFFC;
|
||||
if (!pci_map_port(config_id, TL_PCI_LOIO,
|
||||
(u_short *)&(sc->tl_bhandle))) {
|
||||
if (!pci_map_port(config_id, TL_PCI_LOMEM,
|
||||
(u_short *)&(sc->tl_bhandle))) {
|
||||
printf ("tl%d: couldn't map ports\n", unit);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#ifdef __alpha__
|
||||
sc->tl_btag = ALPHA_BUS_SPACE_IO;
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
sc->tl_btag = I386_BUS_SPACE_IO;
|
||||
#endif
|
||||
#else
|
||||
if (!(command & PCIM_CMD_MEMEN)) {
|
||||
printf("tl%d: failed to enable memory mapping!\n", unit);
|
||||
@ -1593,11 +1582,19 @@ tl_attach(config_id, unit)
|
||||
}
|
||||
|
||||
if (!pci_map_mem(config_id, TL_PCI_LOMEM, &vbase, &pbase)) {
|
||||
printf ("tl%d: couldn't map memory\n", unit);
|
||||
goto fail;
|
||||
if (!pci_map_mem(config_id, TL_PCI_LOIO, &vbase, &pbase)) {
|
||||
printf ("tl%d: couldn't map memory\n", unit);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
sc->csr = (volatile caddr_t)vbase;
|
||||
#ifdef __alpha__
|
||||
sc->tl_btag = ALPHA_BUS_SPACE_MEM;
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
sc->tl_btag = I386_BUS_SPACE_MEM;
|
||||
#endif
|
||||
sc->tl_bhandle = vbase;
|
||||
#endif
|
||||
|
||||
#ifdef notdef
|
||||
@ -1753,9 +1750,24 @@ tl_attach(config_id, unit)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no MII-based PHYs were detected, then this is a
|
||||
* TNETE110 device with a bit rate PHY. There's no autoneg
|
||||
* support, so just default to 10baseT mode.
|
||||
*/
|
||||
if (!phys) {
|
||||
printf("tl%d: no physical interfaces attached!\n", unit);
|
||||
goto fail;
|
||||
struct ifmedia *ifm;
|
||||
sc->tl_bitrate = 1;
|
||||
ifmedia_init(&sc->ifmedia, 0, tl_ifmedia_upd, tl_ifmedia_sts);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
|
||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
|
||||
/* Reset again, this time setting bitrate mode. */
|
||||
tl_softreset(sc, 1);
|
||||
ifm = &sc->ifmedia;
|
||||
ifm->ifm_media = ifm->ifm_cur->ifm_media;
|
||||
tl_ifmedia_upd(ifp);
|
||||
}
|
||||
|
||||
tl_intvec_adchk((void *)sc, 0);
|
||||
@ -1866,6 +1878,10 @@ static int tl_newbuf(sc, c)
|
||||
return(ENOBUFS);
|
||||
}
|
||||
|
||||
#ifdef __alpha__
|
||||
m_new->m_data += 2;
|
||||
#endif
|
||||
|
||||
c->tl_mbuf = m_new;
|
||||
c->tl_next = NULL;
|
||||
c->tl_ptr->tlist_frsize = MCLBYTES;
|
||||
@ -1913,10 +1929,6 @@ static int tl_intvec_rxeof(xsc, type)
|
||||
sc = xsc;
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_RXEOF);
|
||||
#endif
|
||||
|
||||
while(sc->tl_cdata.tl_rx_head->tl_ptr->tlist_cstat & TL_CSTAT_FRAMECMP){
|
||||
r++;
|
||||
cur_rx = sc->tl_cdata.tl_rx_head;
|
||||
@ -2000,10 +2012,6 @@ static int tl_intvec_rxeoc(xsc, type)
|
||||
|
||||
sc = xsc;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_RXEOC);
|
||||
#endif
|
||||
|
||||
/* Flush out the receive queue and ack RXEOF interrupts. */
|
||||
r = tl_intvec_rxeof(xsc, type);
|
||||
CMD_PUT(sc, TL_CMD_ACK | r | (type & ~(0x00100000)));
|
||||
@ -2023,10 +2031,6 @@ static int tl_intvec_txeof(xsc, type)
|
||||
|
||||
sc = xsc;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_TXEOF);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Go through our tx list and free mbufs for those
|
||||
* frames that have been sent.
|
||||
@ -2083,10 +2087,6 @@ static int tl_intvec_txeoc(xsc, type)
|
||||
/* Clear the timeout timer. */
|
||||
ifp->if_timer = 0;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_TXEOC);
|
||||
#endif
|
||||
|
||||
if (sc->tl_cdata.tl_tx_head == NULL) {
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
sc->tl_cdata.tl_tx_tail = NULL;
|
||||
@ -2131,9 +2131,6 @@ static int tl_intvec_adchk(xsc, type)
|
||||
if (type)
|
||||
printf("tl%d: adapter check: %x\n", sc->tl_unit,
|
||||
(unsigned int)CSR_READ_4(sc, TL_CH_PARM));
|
||||
#ifdef TL_DEBUG
|
||||
evshow(sc);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Before resetting the adapter, try reading the PHY
|
||||
@ -2141,6 +2138,7 @@ static int tl_intvec_adchk(xsc, type)
|
||||
* necessary to keep the chip operating at the same
|
||||
* speed and duplex settings after the reset completes.
|
||||
*/
|
||||
if (!sc->tl_bitrate) {
|
||||
bmcr = tl_phy_readreg(sc, PHY_BMCR);
|
||||
ctl = tl_phy_readreg(sc, TL_PHY_CTL);
|
||||
tl_softreset(sc, 1);
|
||||
@ -2151,6 +2149,7 @@ static int tl_intvec_adchk(xsc, type)
|
||||
} else {
|
||||
tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_DUPLEX);
|
||||
}
|
||||
}
|
||||
tl_stop(sc);
|
||||
tl_init(sc);
|
||||
CMD_SET(sc, TL_CMD_INTSON);
|
||||
@ -2456,14 +2455,8 @@ static void tl_start(ifp)
|
||||
if (sc->tl_cdata.tl_tx_head == NULL) {
|
||||
sc->tl_cdata.tl_tx_head = start_tx;
|
||||
sc->tl_cdata.tl_tx_tail = cur_tx;
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_START_TX);
|
||||
#endif
|
||||
|
||||
if (sc->tl_txeoc) {
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_START_TX_REAL);
|
||||
#endif
|
||||
sc->tl_txeoc = 0;
|
||||
CSR_WRITE_4(sc, TL_CH_PARM, vtophys(start_tx->tl_ptr));
|
||||
cmd = CSR_READ_4(sc, TL_HOSTCMD);
|
||||
@ -2472,9 +2465,6 @@ static void tl_start(ifp)
|
||||
CMD_PUT(sc, cmd);
|
||||
}
|
||||
} else {
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_START_Q);
|
||||
#endif
|
||||
sc->tl_cdata.tl_tx_tail->tl_next = start_tx;
|
||||
sc->tl_cdata.tl_tx_tail = cur_tx;
|
||||
}
|
||||
@ -2502,10 +2492,6 @@ static void tl_init(xsc)
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_INIT);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Cancel pending I/O.
|
||||
*/
|
||||
@ -2637,6 +2623,18 @@ static void tl_ifmedia_sts(ifp, ifmr)
|
||||
|
||||
ifmr->ifm_active = IFM_ETHER;
|
||||
|
||||
if (sc->tl_bitrate) {
|
||||
if (tl_dio_read8(sc, TL_ACOMMIT) & TL_AC_MTXD1)
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_5;
|
||||
else
|
||||
ifmr->ifm_active = IFM_ETHER|IFM_10_T;
|
||||
if (tl_dio_read8(sc, TL_ACOMMIT) & TL_AC_MTXD3)
|
||||
ifmr->ifm_active |= IFM_HDX;
|
||||
else
|
||||
ifmr->ifm_active |= IFM_FDX;
|
||||
return;
|
||||
}
|
||||
|
||||
phy_ctl = tl_phy_readreg(sc, PHY_BMCR);
|
||||
phy_sts = tl_phy_readreg(sc, TL_PHY_CTL);
|
||||
|
||||
@ -2716,10 +2714,6 @@ static void tl_watchdog(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
#ifdef TL_DEBUG
|
||||
evset(sc, EV_WATCHDOG);
|
||||
#endif
|
||||
|
||||
if (sc->tl_autoneg) {
|
||||
tl_autoneg(sc, TL_FLAG_DELAYTIMEO, 1);
|
||||
return;
|
||||
|
@ -29,7 +29,7 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: if_tlreg.h,v 1.6 1998/09/23 05:08:54 wpaul Exp $
|
||||
* $Id: if_tlreg.h,v 1.14 1999/03/30 16:57:26 wpaul Exp $
|
||||
*/
|
||||
|
||||
|
||||
@ -111,11 +111,8 @@ struct tl_chain_data {
|
||||
struct tl_softc {
|
||||
struct arpcom arpcom; /* interface info */
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
#ifdef TL_USEIOSPACE
|
||||
u_int32_t iobase;
|
||||
#else
|
||||
volatile caddr_t csr; /* pointer to register map */
|
||||
#endif
|
||||
bus_space_handle_t tl_bhandle;
|
||||
bus_space_tag_t tl_btag;
|
||||
struct tl_type *tl_dinfo; /* ThunderLAN adapter info */
|
||||
struct tl_type *tl_pinfo; /* PHY info struct */
|
||||
u_int8_t tl_ctlr; /* chip number */
|
||||
@ -131,10 +128,8 @@ struct tl_softc {
|
||||
caddr_t tl_ldata_ptr;
|
||||
struct tl_list_data *tl_ldata; /* TX/RX lists and mbufs */
|
||||
struct tl_chain_data tl_cdata;
|
||||
int tl_txeoc;
|
||||
#ifdef TL_DEBUG
|
||||
u_int8_t tl_event[20];
|
||||
#endif
|
||||
u_int8_t tl_txeoc;
|
||||
u_int8_t tl_bitrate;
|
||||
struct callout_handle tl_stat_ch;
|
||||
};
|
||||
|
||||
@ -531,39 +526,31 @@ struct tl_stats {
|
||||
u_int8_t acommit;
|
||||
};
|
||||
|
||||
/*
|
||||
* ACOMMIT register bits. These are used only when a bitrate
|
||||
* PHY is selected ('bitrate' bit in netconfig register is set).
|
||||
*/
|
||||
#define TL_AC_MTXER 0x01 /* reserved */
|
||||
#define TL_AC_MTXD1 0x02 /* 0 == 10baseT 1 == AUI */
|
||||
#define TL_AC_MTXD2 0x04 /* loopback disable */
|
||||
#define TL_AC_MTXD3 0x08 /* full duplex disable */
|
||||
|
||||
/*
|
||||
* register space access macros
|
||||
*/
|
||||
#ifdef TL_USEIOSPACE
|
||||
#define CSR_WRITE_4(sc, reg, val) \
|
||||
outl(sc->iobase + (u_int32_t)(reg), val)
|
||||
bus_space_write_4(sc->tl_btag, sc->tl_bhandle, reg, val)
|
||||
#define CSR_WRITE_2(sc, reg, val) \
|
||||
outw(sc->iobase + (u_int32_t)(reg), val)
|
||||
bus_space_write_2(sc->tl_btag, sc->tl_bhandle, reg, val)
|
||||
#define CSR_WRITE_1(sc, reg, val) \
|
||||
outb(sc->iobase + (u_int32_t)(reg), val)
|
||||
|
||||
#define CSR_READ_4(sc, reg) \
|
||||
inl(sc->iobase + (u_int32_t)(reg))
|
||||
#define CSR_READ_2(sc, reg) \
|
||||
inw(sc->iobase + (u_int32_t)(reg))
|
||||
#define CSR_READ_1(sc, reg) \
|
||||
inb(sc->iobase + (u_int32_t)(reg))
|
||||
#else
|
||||
#define CSR_WRITE_4(sc, reg, val) \
|
||||
((*(u_int32_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int32_t)(val))
|
||||
#define CSR_WRITE_2(sc, reg, val) \
|
||||
((*(u_int16_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int16_t)(val))
|
||||
#define CSR_WRITE_1(sc, reg, val) \
|
||||
((*(u_int8_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int8_t)(val))
|
||||
|
||||
#define CSR_READ_4(sc, reg) \
|
||||
(*(u_int32_t *)((sc)->csr + (u_int32_t)(reg)))
|
||||
#define CSR_READ_2(sc, reg) \
|
||||
(*(u_int16_t *)((sc)->csr + (u_int32_t)(reg)))
|
||||
#define CSR_READ_1(sc, reg) \
|
||||
(*(u_int8_t *)((sc)->csr + (u_int32_t)(reg)))
|
||||
#endif
|
||||
bus_space_write_1(sc->tl_btag, sc->tl_bhandle, reg, val)
|
||||
|
||||
#define CSR_READ_4(sc, reg) \
|
||||
bus_space_read_4(sc->tl_btag, sc->tl_bhandle, reg)
|
||||
#define CSR_READ_2(sc, reg) \
|
||||
bus_space_read_2(sc->tl_btag, sc->tl_bhandle, reg)
|
||||
#define CSR_READ_1(sc, reg) \
|
||||
bus_space_read_1(sc->tl_btag, sc->tl_bhandle, reg)
|
||||
|
||||
#define CMD_PUT(sc, x) CSR_WRITE_4(sc, TL_HOSTCMD, x)
|
||||
#define CMD_SET(sc, x) \
|
||||
|
Loading…
Reference in New Issue
Block a user