Virgin import of Xircom PCCARD driver v1.20 (1999/06/13):

* Conformance with Dingo specification. This includes:
	Collision/error statistics gathering.
	Multicast address filtering, eg. the hash filter.
	Initialisation and interrupt handling sequences.
Note that I've started on some of this already in v1.20.

* The probe routine needs some more work, to identify oddities such as the
  REM10.

* There are still problems with the autonegotiation code; specifically, it
  won't autonegotiate with some 10/100 hubs.  This might simply be the hardware
  not getting along, in which case there's nothing we can do, but it's still
  worth investigating

* CEM28/CEM33 support.  Should be able to integrate this directly from the
  Linux code.

* Performance enhancements:
	Full-duplex on 10Mbit networks.
	Virtual shared-memory mode.
	Early send and receive modes.

Developed by:	Scott Mitchell <scott@uk.freebsd.org>
Obtained from:	http://www.freebsd-uk.eu.org/~scott/xe_drv/
This commit is contained in:
David E. O'Brien 1999-06-22 19:12:08 +00:00
parent bd5a7eb3e7
commit cb8e217fc6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-sys/xe/dist/; revision=48114
svn path=/vendor-sys/xe/1.20/; revision=48116; tag=vendor/xe/1.20
2 changed files with 739 additions and 246 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: if_xe.c,v 1.19 1999/04/15 22:15:53 scott Exp $
* $Id: if_xe.c,v 1.20 1999/06/13 19:17:40 scott Exp $
*/
/*
@ -63,7 +63,9 @@
* FreeBSD device driver for Xircom CreditCard PCMCIA Ethernet adapters. The
* following cards are currently known to work with the driver:
* Xircom CreditCard 10/100 (CE3)
* Xircom CreditCard Ethernet + Modem 28 (CEM28)
* Xircom CreditCard Ethernet 10/100 + Modem 56 (CEM56)
* Xircom RealPort Ethernet 10
* Xircom RealPort Ethernet 10/100
* Xircom RealPort Ethernet 10/100 + Modem 56 (REM56, REM56G)
* Intel EtherExpress Pro/100 PC Card Mobile Adapter 16 (Pro/100 M16A)
@ -96,7 +98,7 @@
*/
#define XE_DEBUG 1
#define XE_DEBUG 1 /* Increase for more voluminous output! */
#include "xe.h"
#include "card.h"
@ -151,8 +153,8 @@
struct xe_softc {
struct arpcom arpcom;
struct ifmedia ifmedia;
struct callout_handle chand;
struct ifmib_iso_8802_3 mibdata;
struct callout_handle chand;
struct isa_device *dev;
struct pccard_devinfo *crd;
struct ifnet *ifp;
@ -162,14 +164,16 @@ struct xe_softc {
int unit; /* Unit number, from dev->id_unit */
int srev; /* Silicon revision */
int tx_queued; /* Packets currently waiting to transmit */
int tx_ptr; /* Last value of PTR reg on card */
int tx_tpr; /* Last value of TPR reg on card */
int tx_collisions; /* Collisions since last successful send */
int tx_timeouts; /* Count of transmit timeouts */
int autoneg_status; /* Autonegotiation progress state */
int media; /* Private media word */
u_char modem; /* 1 = Multifunction card with modem */
u_char ce3; /* 1 = CE3 class (100Mbit) adapter */
u_char cem56; /* 1 = CEM56 class (CE3 + 56Kbps modem) adapter */
u_char version; /* Bonding Version register from card */
u_char modem; /* 1 = Card has a modem */
u_char ce2; /* 1 = Card has CE2 silicon */
u_char mohawk; /* 1 = Card has Mohawk (CE3) silicon */
u_char dingo; /* 1 = Card has Dingo (CEM56) silicon */
u_char phy_ok; /* 1 = MII-compliant PHY found and initialised */
u_char gone; /* 1 = Card bailed out */
#if NAPM > 0
@ -179,7 +183,6 @@ struct xe_softc {
};
static struct xe_softc *sca[MAXSLOT];
static int iob[MAXSLOT]; /* XXX - very gross */
/*
@ -201,7 +204,7 @@ struct xe_mii_frame {
#define XE_INW(r) inw(scp->dev->id_iobase+(r))
#define XE_OUTB(r, b) outb(scp->dev->id_iobase+(r), (b))
#define XE_OUTW(r, w) outw(scp->dev->id_iobase+(r), (w))
#define XE_SELECT_PAGE(p) XE_OUTB(XE_PSR, (p))
#define XE_SELECT_PAGE(p) XE_OUTB(XE_PR, (p))
/*
* Horrid stuff for accessing CIS tuples
@ -245,6 +248,8 @@ static void xe_setmulti (struct xe_softc *scp);
static void xe_setaddrs (struct xe_softc *scp);
static int xe_pio_write_packet (struct xe_softc *scp, struct mbuf *mbp);
static void xe_card_unload (struct pccard_devinfo *devi);
static u_int32_t xe_compute_crc (u_int8_t *data, int len);
static int xe_compute_hashbit (u_int32_t crc);
/*
* MII functions
@ -318,10 +323,9 @@ struct isa_driver xedriver = {
static int
xe_probe (struct isa_device *dev) {
#ifdef XE_DEBUG
printf("xe%d: probe, iobase = %#x\n", dev->id_unit, dev->id_iobase);
printf("xe%d: probe\n", dev->id_unit);
#endif
bzero(sca, MAXSLOT * sizeof(sca[0]));
iob[dev->id_unit] = dev->id_iobase;
return 0;
}
@ -395,24 +399,32 @@ xe_cem56fix(struct xe_softc *scp)
/* allocate a new I/O slot for the ethernet */
/* XXX: ctrl->mapio() always appears to return 0 (success), so
* this may cause problems if another device is listening
* on 0x300 already
* on 0x300 already. In this case, you should choose a
* known free I/O port address in the kernel config line
* for the driver. It will be picked up here and used
* instead of the autodetected value.
*/
slt->io[1].window = 1;
slt->io[1].flags = IODF_WS|IODF_16BIT|IODF_ZEROWS|IODF_ACTIVE;
slt->io[1].size = 0x10;
if (iob[scp->unit] == -1) {
for (ioport = 0x300; ioport < 0x400; ioport += 0x10) {
slt->io[1].start = ioport;
if ((fail = ctrl->mapio( slt, 1 )) == 0)
break;
}
}
else {
ioport = iob[scp->unit];
#ifdef XE_IOBASE
printf( "xe%d: user requested ioport 0x%x\n", scp->unit, XE_IOBASE );
ioport = XE_IOBASE;
slt->io[1].start = ioport;
fail = ctrl->mapio(slt, 1);
#else
for (ioport = 0x300; ioport < 0x400; ioport += 0x10) {
slt->io[1].start = ioport;
fail = ctrl->mapio(slt, 1);
if ((fail = ctrl->mapio( slt, 1 )) == 0)
break;
}
#endif
/* did we find one? */
if (fail) {
printf( "xe%d: xe_cem56fix: no free address space\n", scp->unit );
@ -421,22 +433,23 @@ xe_cem56fix(struct xe_softc *scp)
/* munge the id_iobase entry for use by the rest of the driver */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf( "xe%d: using 0x%x for RealPort ethernet\n", scp->unit, ioport );
#endif
scp->dev->id_iobase = ioport;
scp->dev->id_alive = 0x10;
/* magic to set up the ethernet */
xe_memwrite( devi, 0x800, 0x47 );
xe_memwrite( devi, 0x80a, ioport & 0xff );
xe_memwrite( devi, 0x80c, (ioport >> 8) & 0xff );
xe_memwrite( devi, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL|DINGO_ECOR_INT_ENABLE|
DINGO_ECOR_IOB_ENABLE|DINGO_ECOR_ETH_ENABLE );
xe_memwrite( devi, DINGO_EBAR0, ioport & 0xff );
xe_memwrite( devi, DINGO_EBAR1, (ioport >> 8) & 0xff );
xe_memwrite( devi, 0x820, 0x01 );
xe_memwrite( devi, 0x822, 0x0c );
xe_memwrite( devi, 0x824, 0x00 );
xe_memwrite( devi, 0x826, 0x00 );
xe_memwrite( devi, 0x828, 0x00 );
xe_memwrite( devi, DINGO_DCOR0, DINGO_DCOR0_SF_INT );
xe_memwrite( devi, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL|DINGO_DCOR1_EEDIO );
xe_memwrite( devi, DINGO_DCOR2, 0x00 );
xe_memwrite( devi, DINGO_DCOR3, 0x00 );
xe_memwrite( devi, DINGO_DCOR4, 0x00 );
/* success! */
return 0;
@ -470,13 +483,13 @@ xe_card_init(struct pccard_devinfo *devi)
/* Check that unit number is OK */
if (unit > MAXSLOT) {
printf("xe: bad unit (%d)\n", unit);
printf("xe%d: bad unit\n", unit);
return (ENODEV);
}
/* Don't attach an active device */
if (scp && !scp->gone) {
printf("xe: unit already attached (%d)\n", unit);
printf("xe%d: already attached\n", unit);
return (EBUSY);
}
@ -503,17 +516,16 @@ xe_card_init(struct pccard_devinfo *devi)
/*
* Read tuples one at a time into buf. Sucks, but it only happens once.
* XXX - If the stuff we need isn't in attribute memory, or (worse yet)
* XXX - attribute memory isn't mapped, we're FUBAR. Maybe need to do an
* XXX - ioctl on the card device and follow links?
* XXX - Not really the driver's problem, PCCARD should handle all this!
* XXX - This assumes that attribute has been mapped by pccardd, which
* XXX - seems to be the default situation. If not, we're well and truly
* XXX - FUBAR. This is a general PCCARD problem, not our fault :)
*/
if ((rc = xe_memread( devi, offs, buf, CISTPL_BUFSIZE )) == 0) {
switch (CISTPL_TYPE(buf)) {
case 0x15: /* Grab version string (needed to ID some weird CE2's) */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Got version string (0x15)\n", unit);
#endif
for (i = 0; i < CISTPL_LEN(buf); ver_str[i] = CISTPL_DATA(buf, i++));
@ -523,7 +535,7 @@ xe_card_init(struct pccard_devinfo *devi)
break;
case 0x20: /* Figure out what type of card we have */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Got card ID (0x20)\n", unit);
#endif
vendor = CISTPL_DATA(buf, 0) + (CISTPL_DATA(buf, 1) << 8);
@ -544,14 +556,14 @@ xe_card_init(struct pccard_devinfo *devi)
}
if (!((prod & 0x40) && (media & 0x01))) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Not a PCMCIA Ethernet card!\n", unit);
#endif
rc = ENODEV; /* Not a PCMCIA Ethernet device */
}
else {
if (media & 0x10) { /* Ethernet/modem cards */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Card is Ethernet/modem combo\n", unit);
#endif
scp->modem = 1;
@ -559,34 +571,38 @@ xe_card_init(struct pccard_devinfo *devi)
case 1:
scp->card_type = "CEM"; break;
case 2:
scp->ce2 = 1;
scp->card_type = "CEM2"; break;
case 3:
scp->ce2 = 1;
scp->card_type = "CEM3"; break;
case 4:
scp->ce2 = 1;
scp->card_type = "CEM33"; break;
case 5:
scp->ce3 = 1;
scp->mohawk = 1;
scp->card_type = "CEM56M"; break;
case 6:
case 7: /* Some kind of RealPort card */
scp->ce3 = 1;
scp->cem56 = 1;
scp->mohawk = 1;
scp->dingo = 1;
scp->card_type = "CEM56"; break;
default:
rc = ENODEV;
}
}
else { /* Ethernet-only cards */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Card is Ethernet only\n", unit);
#endif
switch (prod & 0x0f) {
case 1:
scp->card_type = "CE"; break;
case 2:
scp->ce2 = 1;
scp->card_type = "CE2"; break;
case 3:
scp->ce3 = 1;
scp->mohawk = 1;
scp->card_type = "CE3"; break;
default:
rc = ENODEV;
@ -597,12 +613,12 @@ xe_card_init(struct pccard_devinfo *devi)
break;
case 0x22: /* Get MAC address */
#ifdef XE_DEBUG
printf("xe%d: Got MAC address (0x22)\n", unit);
#endif
if ((CISTPL_LEN(buf) == 8) &&
(CISTPL_DATA(buf, 0) == 0x04) &&
(CISTPL_DATA(buf, 1) == ETHER_ADDR_LEN)) {
#if XE_DEBUG > 1
printf("xe%d: Got MAC address (0x22)\n", unit);
#endif
for (i = 0; i < ETHER_ADDR_LEN; scp->arpcom.ac_enaddr[i] = CISTPL_DATA(buf, i+2), i++);
}
success++;
@ -626,7 +642,7 @@ xe_card_init(struct pccard_devinfo *devi)
/* Check for certain strange CE2's that look like CE's */
if (strcmp(scp->card_type, "CE") == 0) {
u_char *str = ver_str;
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Checking for weird CE2 string\n", unit);
#endif
str += strlen(str) + 1; /* Skip forward to 3rd version string */
@ -656,13 +672,17 @@ xe_card_init(struct pccard_devinfo *devi)
scp->autoneg_status = 0;
/* Hack RealPorts into submission */
if (scp->cem56 && xe_cem56fix(scp) < 0) {
if (scp->dingo && xe_cem56fix(scp) < 0) {
printf( "xe%d: Unable to fix your RealPort\n", unit );
sca[unit] = 0;
free(scp, M_DEVBUF);
return ENODEV;
}
/* Hopefully safe to read this here */
XE_SELECT_PAGE(4);
scp->version = XE_INB(XE_BOV);
/* Attempt to attach the device */
if (!xe_attach(scp->dev)) {
sca[unit] = 0;
@ -729,7 +749,7 @@ xe_attach (struct isa_device *dev) {
* operation, but this driver doesn't, yet. Therefore we leave those modes
* out of the list. We support some form of autoselection in all cases.
*/
if (scp->ce3) {
if (scp->mohawk) {
ifmedia_add(scp->ifm, IFM_ETHER|IFM_100_TX, 0, NULL);
ifmedia_add(scp->ifm, IFM_ETHER|IFM_10_T, 0, NULL);
}
@ -743,12 +763,30 @@ xe_attach (struct isa_device *dev) {
ifmedia_set(scp->ifm, IFM_ETHER|IFM_AUTO);
/* Print some useful information */
printf("\nxe%d: %s %s%s%s\n",
printf("\n");
printf("xe%d: %s %s, bonding version %#x%s%s\n",
scp->unit,
scp->vendor,
scp->card_type,
scp->ce3 ? ", 100Mbps capable" : "",
scp->cem56 ? ", with modem" : "");
scp->version,
scp->mohawk ? ", 100Mbps capable" : "",
scp->modem ? ", with modem" : "");
if (scp->mohawk) {
XE_SELECT_PAGE(0x10);
printf("xe%d: DingoID = %#x, RevisionID = %#x, VendorID = %#x\n",
scp->unit,
XE_INW(XE_DINGOID),
XE_INW(XE_RevID),
XE_INW(XE_VendorID));
}
if (scp->ce2) {
XE_SELECT_PAGE(0x45);
printf("xe%d: CE2 version = %#x\n",
scp->unit,
XE_INB(XE_REV));
}
/* Print MAC address */
printf("xe%d: Ethernet address %02x", scp->unit, scp->arpcom.ac_enaddr[0]);
for (i = 1; i < ETHER_ADDR_LEN; i++) {
printf(":%02x", scp->arpcom.ac_enaddr[i]);
@ -761,7 +799,7 @@ xe_attach (struct isa_device *dev) {
#if NBPFILTER > 0
/* If BPF is in the kernel, call the attach for it */
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: BPF listener attached\n", scp->unit);
#endif
bpfattach(scp->ifp, DLT_EN10MB, sizeof(struct ether_header));
@ -792,7 +830,7 @@ xe_init(void *xscp) {
/* Reset transmitter flags */
scp->tx_queued = 0;
scp->tx_ptr = 0;
scp->tx_tpr = 0;
scp->tx_collisions = 0;
scp->ifp->if_timer = 0;
@ -816,19 +854,19 @@ xe_init(void *xscp) {
/* Fix the data offset register -- reset leaves it off-by-one */
XE_SELECT_PAGE(0);
XE_OUTW(XE_DOR, 0x2000);
XE_OUTW(XE_DO, 0x2000);
/*
* Set MAC interrupt masks and clear status regs. The bit names are direct
* from the Linux code; I have no idea what most of them do.
*/
XE_SELECT_PAGE(0x40); /* Bit 7..0 */
XE_OUTB(XE_RXM0, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */
XE_OUTB(XE_TXM0, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */
XE_OUTB(XE_TXM1, 0xb0); /* rsv, rsv, PTD, EXT, rsv, rsv, rsv, rsv */
XE_OUTB(XE_RXS0, 0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */
XE_OUTB(XE_TXS0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */
XE_OUTB(XE_TXS1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */
XE_OUTB(XE_RX0Msk, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */
XE_OUTB(XE_TX0Msk, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */
XE_OUTB(XE_TX0Msk+1, 0xb0); /* rsv, rsv, PTD, EXT, rsv, rsv, rsv, rsv */
XE_OUTB(XE_RST0, 0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */
XE_OUTB(XE_TXST0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */
XE_OUTB(XE_TXST1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */
/*
* Check for an in-progress autonegotiation. If one is active, just set
@ -841,7 +879,7 @@ xe_init(void *xscp) {
else {
/* Enable receiver, put MAC online */
XE_SELECT_PAGE(0x40);
XE_OUTB(XE_OCR, XE_OCR_RX_ENABLE|XE_OCR_ONLINE);
XE_OUTB(XE_CMD0, XE_CMD0_RX_ENABLE|XE_CMD0_ONLINE);
/* Set up IMR, enable interrupts */
xe_enable_intr(scp);
@ -1021,11 +1059,11 @@ xe_card_intr(struct pccard_devinfo *devi) {
if (scp->gone)
return 0;
if (scp->ce3) {
if (scp->mohawk) {
XE_OUTB(XE_CR, 0); /* Disable interrupts */
}
psr = XE_INB(XE_PSR); /* Stash the current register page */
psr = XE_INB(XE_PR); /* Stash the current register page */
/*
* Read ISR to see what caused this interrupt. Note that this clears the
@ -1036,31 +1074,31 @@ xe_card_intr(struct pccard_devinfo *devi) {
result = 1; /* This device did generate an int */
esr = XE_INB(XE_ESR); /* Read the other status registers */
XE_SELECT_PAGE(0x40);
rxs = XE_INB(XE_RXS0);
XE_OUTB(XE_RXS0, ~rxs & 0xff);
txs = XE_INB(XE_TXS0);
txs |= XE_INB(XE_TXS1) << 8;
XE_OUTB(XE_TXS0, 0);
XE_OUTB(XE_TXS1, 0);
rxs = XE_INB(XE_RST0);
XE_OUTB(XE_RST0, ~rxs & 0xff);
txs = XE_INB(XE_TXST0);
txs |= XE_INB(XE_TXST1) << 8;
XE_OUTB(XE_TXST0, 0);
XE_OUTB(XE_TXST1, 0);
XE_SELECT_PAGE(0);
#if XE_DEBUG > 3
printf("xe%d: ISR=%#2.2x ESR=%#2.2x RXS=%#2.2x TXS=%#4.4x\n", unit, isr, esr, rxs, txs);
#if XE_DEBUG > 2
printf("xe%d: ISR=%#2.2x ESR=%#2.2x RST=%#2.2x TXST=%#4.4x\n", unit, isr, esr, rxs, txs);
#endif
/*
* Handle transmit interrupts
*/
if (isr & XE_ISR_TX_PACKET) {
u_int8_t new_ptr, sent;
u_int8_t new_tpr, sent;
if ((new_ptr = XE_INB(XE_PTR)) < scp->tx_ptr) /* Update packet count */
sent = (0xff - scp->tx_ptr) + new_ptr; /* PTR rolled over */
if ((new_tpr = XE_INB(XE_TPR)) < scp->tx_tpr) /* Update packet count */
sent = (0xff - scp->tx_tpr) + new_tpr; /* TPR rolled over */
else
sent = new_ptr - scp->tx_ptr;
sent = new_tpr - scp->tx_tpr;
if (sent > 0) { /* Packets sent since last interrupt */
scp->tx_ptr = new_ptr;
scp->tx_tpr = new_tpr;
scp->tx_queued -= sent;
ifp->if_opackets += sent;
ifp->if_collisions += scp->tx_collisions;
@ -1117,7 +1155,7 @@ xe_card_intr(struct pccard_devinfo *devi) {
/*
* Handle receive interrupts
*/
while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PKT_RX) {
while ((esr = XE_INB(XE_ESR)) & XE_ESR_FULL_PACKET_RX) {
if ((rsr = XE_INB(XE_RSR)) & XE_RSR_RX_OK) {
struct ether_header *ehp;
@ -1138,7 +1176,7 @@ xe_card_intr(struct pccard_devinfo *devi) {
if ((rx_bytes += len) > 22000) {
ifp->if_iqdrops++;
scp->mibData.dot3StatsMissedFrames++;
XE_OUTW(XE_DOR, 0x8000);
XE_OUTW(XE_DO, 0x8000);
continue;
}
#endif
@ -1185,7 +1223,7 @@ xe_card_intr(struct pccard_devinfo *devi) {
u_short rhs;
XE_SELECT_PAGE(5);
rhs = XE_INW(XE_RHS);
rhs = XE_INW(XE_RHSA);
XE_SELECT_PAGE(0);
rhs += 3; /* Skip control info */
@ -1235,7 +1273,7 @@ xe_card_intr(struct pccard_devinfo *devi) {
*/
if ((ifp->if_flags & IFF_PROMISC) &&
bcmp(ehp->ether_dhost, scp->arpcom.ac_enaddr, sizeof(ehp->ether_dhost)) != 0 &&
(rsr & XE_RSR_PHYS_PKT)) {
(rsr & XE_RSR_PHYS_PACKET)) {
m_freem(mbp);
mbp = NULL;
}
@ -1248,18 +1286,18 @@ xe_card_intr(struct pccard_devinfo *devi) {
ether_input(ifp, ehp, mbp); /* Send the packet on its way */
ifp->if_ipackets++; /* Success! */
}
XE_OUTW(XE_DOR, 0x8000); /* skip_rx_packet command */
XE_OUTW(XE_DO, 0x8000); /* skip_rx_packet command */
}
}
else if (rsr & XE_RSR_LONG_PKT) { /* Packet length >1518 bytes */
else if (rsr & XE_RSR_LONG_PACKET) { /* Packet length >1518 bytes */
scp->mibdata.dot3StatsFrameTooLongs++;
ifp->if_ierrors++;
}
else if (rsr & XE_RSR_CRC_ERR) { /* Bad checksum on packet */
else if (rsr & XE_RSR_CRC_ERROR) { /* Bad checksum on packet */
scp->mibdata.dot3StatsFCSErrors++;
ifp->if_ierrors++;
}
else if (rsr & XE_RSR_ALIGN_ERR) { /* Packet alignment error */
else if (rsr & XE_RSR_ALIGN_ERROR) { /* Packet alignment error */
scp->mibdata.dot3StatsAlignmentErrors++;
ifp->if_ierrors++;
}
@ -1274,8 +1312,8 @@ xe_card_intr(struct pccard_devinfo *devi) {
XE_SELECT_PAGE(psr); /* Restore saved page */
XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Re-enable interrupts */
/* XXX - Could force an int here, instead of dropping packets? */
/* XXX - XE_OUTB(XE_CR, XE_CR_ENABLE_INTR|XE_CE_FORCE_INTR); */
/* Could force an int here, instead of dropping packets? */
/* XE_OUTB(XE_CR, XE_CR_ENABLE_INTR|XE_CE_FORCE_INTR); */
return result;
}
@ -1400,7 +1438,7 @@ static void xe_setmedia(void *xscp) {
switch (scp->autoneg_status) {
case XE_AUTONEG_NONE:
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Waiting for idle transmitter\n", scp->unit);
#endif
scp->arpcom.ac_if.if_flags |= IFF_OACTIVE;
@ -1411,7 +1449,7 @@ static void xe_setmedia(void *xscp) {
case XE_AUTONEG_WAITING:
xe_soft_reset(scp);
if (scp->phy_ok) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Starting autonegotiation\n", scp->unit);
#endif
bmcr = xe_phy_readreg(scp, PHY_BMCR);
@ -1436,7 +1474,7 @@ static void xe_setmedia(void *xscp) {
bmsr = xe_phy_readreg(scp, PHY_BMSR);
lpar = xe_phy_readreg(scp, PHY_LPAR);
if (bmsr & (PHY_BMSR_AUTONEGCOMP|PHY_BMSR_LINKSTAT)) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Autonegotiation complete!\n", scp->unit);
#endif
/*
@ -1475,7 +1513,7 @@ static void xe_setmedia(void *xscp) {
}
}
else {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Autonegotiation failed; trying 100baseTX\n", scp->unit);
#endif
XE_MII_DUMP(scp);
@ -1496,7 +1534,7 @@ static void xe_setmedia(void *xscp) {
(void)xe_phy_readreg(scp, PHY_BMSR);
bmsr = xe_phy_readreg(scp, PHY_BMSR);
if (bmsr & PHY_BMSR_LINKSTAT) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Got 100baseTX link!\n", scp->unit);
#endif
XE_MII_DUMP(scp);
@ -1506,7 +1544,7 @@ static void xe_setmedia(void *xscp) {
scp->autoneg_status = XE_AUTONEG_NONE;
}
else {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Autonegotiation failed; disabling PHY\n", scp->unit);
#endif
XE_MII_DUMP(scp);
@ -1526,10 +1564,10 @@ static void xe_setmedia(void *xscp) {
* already by the big switch above.
*/
if (scp->autoneg_status == XE_AUTONEG_FAIL) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Selecting 10baseX\n", scp->unit);
#endif
if (scp->ce3) {
if (scp->mohawk) {
XE_SELECT_PAGE(0x42);
XE_OUTB(XE_SWC1, 0x80);
scp->media = IFM_ETHER|IFM_10_T;
@ -1556,7 +1594,7 @@ static void xe_setmedia(void *xscp) {
case IFM_100_TX: /* Force 100baseTX */
xe_soft_reset(scp);
if (scp->phy_ok) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Selecting 100baseTX\n", scp->unit);
#endif
XE_SELECT_PAGE(0x42);
@ -1571,7 +1609,7 @@ static void xe_setmedia(void *xscp) {
case IFM_10_T: /* Force 10baseT */
xe_soft_reset(scp);
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Selecting 10baseT\n", scp->unit);
#endif
if (scp->phy_ok) {
@ -1586,7 +1624,7 @@ static void xe_setmedia(void *xscp) {
case IFM_10_2:
xe_soft_reset(scp);
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Selecting 10base2\n", scp->unit);
#endif
XE_SELECT_PAGE(0x42);
@ -1600,7 +1638,7 @@ static void xe_setmedia(void *xscp) {
* Finally, the LEDs are set to match whatever media was chosen and the
* transmitter is unblocked.
*/
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: Setting LEDs\n", scp->unit);
#endif
XE_SELECT_PAGE(2);
@ -1608,7 +1646,7 @@ static void xe_setmedia(void *xscp) {
case IFM_100_TX:
case IFM_10_T:
XE_OUTB(XE_LED, 0x3b);
if (scp->cem56)
if (scp->dingo)
XE_OUTB(0x0b, 0x04); /* 100Mbit LED */
break;
@ -1645,7 +1683,7 @@ xe_hard_reset(struct xe_softc *scp) {
XE_OUTB(XE_GPR1, 0); /* Power off */
DELAY(40000);
if (scp->ce3)
if (scp->mohawk)
XE_OUTB(XE_GPR1, 1); /* And back on again */
else
XE_OUTB(XE_GPR1, 5); /* Also set AIC bit, whatever that is */
@ -1684,7 +1722,7 @@ xe_soft_reset(struct xe_softc *scp) {
XE_OUTB(XE_CR, 0);
DELAY(40000);
if (scp->ce3) {
if (scp->mohawk) {
/*
* set GP1 and GP2 as outputs (bits 2 & 3)
* set GP1 low to power on the ML6692 (bit 0)
@ -1703,7 +1741,7 @@ xe_soft_reset(struct xe_softc *scp) {
* Get silicon revision number.
*/
XE_SELECT_PAGE(4);
if (scp->ce3)
if (scp->mohawk)
scp->srev = (XE_INB(XE_BOV) & 0x70) >> 4;
else
scp->srev = (XE_INB(XE_BOV) & 0x30) >> 4;
@ -1719,7 +1757,7 @@ xe_soft_reset(struct xe_softc *scp) {
/*
* Check for PHY.
*/
if (scp->ce3) {
if (scp->mohawk) {
scp->phy_ok = xe_mii_init(scp);
}
@ -1785,7 +1823,7 @@ xe_enable_intr(struct xe_softc *scp) {
XE_SELECT_PAGE(0);
XE_OUTB(XE_CR, XE_CR_ENABLE_INTR); /* Enable interrupts */
if (scp->modem && !scp->cem56) { /* This bit is just magic */
if (scp->modem && !scp->dingo) { /* This bit is just magic */
if (!(XE_INB(0x10) & 0x01)) {
XE_OUTB(0x10, 0x11); /* Unmask master int enable bit */
}
@ -1804,7 +1842,7 @@ xe_disable_intr(struct xe_softc *scp) {
XE_SELECT_PAGE(0);
XE_OUTB(XE_CR, 0); /* Disable interrupts */
if (scp->modem && !scp->cem56) { /* More magic (does this work?) */
if (scp->modem && !scp->dingo) { /* More magic (does this work?) */
XE_OUTB(0x10, 0x10); /* Mask the master int enable bit */
}
@ -1846,12 +1884,12 @@ xe_setmulti(struct xe_softc *scp) {
XE_SELECT_PAGE(0x42);
XE_OUTB(XE_SWC1, 0x01);
XE_SELECT_PAGE(0x40);
XE_OUTB(XE_OCR, XE_OCR_OFFLINE);
XE_OUTB(XE_CMD0, XE_CMD0_OFFLINE);
/*xe_reg_dump(scp);*/
xe_setaddrs(scp);
/*xe_reg_dump(scp);*/
XE_SELECT_PAGE(0x40);
XE_OUTB(XE_OCR, XE_OCR_RX_ENABLE|XE_OCR_ONLINE);
XE_OUTB(XE_CMD0, XE_CMD0_RX_ENABLE|XE_CMD0_ONLINE);
}
else {
/*
@ -1871,8 +1909,6 @@ xe_setmulti(struct xe_softc *scp) {
* XXX - This doesn't work right, but I'm not sure why yet. We seem to be
* XXX - doing much the same as the Linux code, which is weird enough that
* XXX - it's probably right (despite my earlier comments to the contrary).
* XXX - I wonder if this thing has a multicast hash filter like most other
* XXX - Ethernet hardware seems to?
*/
static void
xe_setaddrs(struct xe_softc *scp) {
@ -1898,7 +1934,7 @@ xe_setaddrs(struct xe_softc *scp) {
}
for (i = 0; i < 6; i++, byte++) {
#if XE_DEBUG > 1
#if XE_DEBUG > 2
if (i)
printf(":%x", addr[i]);
else
@ -1911,12 +1947,12 @@ xe_setaddrs(struct xe_softc *scp) {
XE_SELECT_PAGE(page);
}
if (scp->ce3)
if (scp->mohawk)
XE_OUTB(byte, addr[5 - i]);
else
XE_OUTB(byte, addr[i]);
}
#if XE_DEBUG > 1
#if XE_DEBUG > 2
printf("\n");
#endif
}
@ -1992,7 +2028,7 @@ xe_pio_write_packet(struct xe_softc *scp, struct mbuf *mbp) {
* short packets with random cruft. Otherwise, write nonsense words to fill
* out the packet. I guess it is then sent automatically (?)
*/
if (scp->ce3)
if (scp->mohawk)
XE_OUTB(XE_CR, XE_CR_TX_PACKET|XE_CR_ENABLE_INTR);
else
while (pad > 0) {
@ -2033,6 +2069,60 @@ xe_card_unload(struct pccard_devinfo *devi) {
}
/*
* Compute the 32-bit Ethernet CRC for the given buffer.
*/
static u_int32_t
xe_compute_crc(u_int8_t *data, int len) {
u_int32_t crc = 0xffffffff;
u_int32_t poly = 0x04c11db6;
u_int8_t current, crc31, bit;
int i, k;
for (i = 0; i < len; i++) {
current = data[i];
for (k = 1; k <= 8; k++) {
if (crc & 0x80000000) {
crc31 = 0x01;
}
else {
crc31 = 0;
}
bit = crc31 ^ (current & 0x01);
crc <<= 1;
current >>= 1;
if (bit) {
crc = (crc ^ poly)|1;
}
}
}
return crc;
}
/*
* Convert a CRC into an index into the multicast hash table. What we do is
* take the most-significant 6 bits of the CRC, reverse them, and use that as
* the bit number in the hash table. Bits 5:3 of the result give the byte
* within the table (0-7); bits 2:0 give the bit number within that byte (also
* 0-7), ie. the number of shifts needed to get it into the lsb position.
*/
static int
xe_compute_hashbit(u_int32_t crc) {
u_int8_t hashbit = 0;
int i;
for (i = 0; i < 6; i++) {
hashbit >>= 1;
if (crc & 0x80000000) {
hashbit &= 0x80;
}
crc <<= 1;
}
return (hashbit >> 2);
}
/**************************************************************
* *
@ -2043,6 +2133,9 @@ xe_card_unload(struct pccard_devinfo *devi) {
/*
* Alternative MII/PHY handling code adapted from the xl driver. It doesn't
* seem to work any better than the xirc2_ps stuff, but it's cleaner code.
* XXX - this stuff shouldn't be here. It should all be abstracted off to
* XXX - some kind of common MII-handling code, shared by all drivers. But
* XXX - that's a whole other mission.
*/
#define XE_MII_SET(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) | (x))
#define XE_MII_CLR(x) XE_OUTB(XE_GPR2, (XE_INB(XE_GPR2) | 0x04) & ~(x))
@ -2076,13 +2169,13 @@ xe_mii_init(struct xe_softc *scp) {
status = xe_phy_readreg(scp, PHY_BMSR);
if ((status & 0xff00) != 0x7800) {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: no PHY found, %0x\n", scp->unit, status);
#endif
return 0;
}
else {
#ifdef XE_DEBUG
#if XE_DEBUG > 1
printf("xe%d: PHY OK!\n", scp->unit);
#endif

View File

@ -23,205 +23,595 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: if_xereg.h,v 1.3 1999/02/22 14:00:53 root Exp $
* $Id: if_xereg.h,v 1.5 1999/05/20 21:53:58 scott Exp $
*/
/*
* Register definitions for Xircom CreditCard Ethernet adapters. See if_xe.c
* for details of supported hardware. Adapted from Werner Koch's 'xirc2ps'
* driver for Linux and the FreeBSD 'xl' driver (for the MII support).
* Register definitions for Xircom PCMCIA Ethernet controllers, based on
* Rev. B of the "Dingo" 10/100 controller used in Xircom CEM56 and RealPort
* Ethernet/modem cards. The Dingo can be configured to be register
* compatible with the "Mohawk" 10/100 controller used in Xircom CE3 cards
* (also some Intel and Compaq OEM versions of the CE3). The older 10Mbps CE2
* cards seem to use earlier revisions of the same device. Some registers and
* bits below are marked 'CE2 only'; these are used by Werner Koch's xirc2ps
* driver that was originally for the CE2 but, according to the spec, aren't
* present on the Dingo. They often seem to relate to operation on coax
* cables, which Mohawk can do in theory (it has the SSI interface) so they
* _might_ also work on Mohawk. I've also noted the few registers that are
* specific to Dingo.
*
* As far as I can tell, the Dingo is basically a Mohawk device with a few
* registers and support for a second PCMCIA function (the modem) added. In
* Dingo mode the SSI (non-MII) PHY interface of the Mohawk is not available.
* The CE2 chip is most likely a Mohawk without the MII and definitely with a
* slightly different register set.
*
* In all cases, the controller uses a paged model of register access. The
* first eight registers are always the same, the function of the second eight
* is selected by the value in the Page Register (reg 0x01).
*
* References:
* 1. Dingo External Reference Specification, Revision B. Xircom Inc.,
* Thousand Oaks, California. August 1998. Available under licence from
* Xircom, http://www.xircom.com/
* 2. ML6692 100BASE-TX Physical Layer with MII specification. MicroLinear
* Corp, San Jose, California. May 1997. Available for download from
* http://www.microlinear.com/
* 3. DP83840 10/100 Mb/s Ethernet Physical Layer specification. National
* Semiconductor Corp., Arlington, Texas. March 1997. Available for
* download from http://www.ns.com/
* 4. Werner Koch's xirc2ps driver for Linux, for all the CE2 and CE3 frobs
* that aren't documented in the Xircom spec. Available for download from
* http://www.d.shuttle.de/isil/xircom/xirc2ps.html
*/
#include "xe.h"
#if NXE > 0
/*
* Common registers
*/
#define XE_CR 0 /* Command register (write) */
#define XE_ESR 0 /* Ethernet status register (read) */
#define XE_PSR 1 /* Page select register */
#define XE_EDP 4 /* Ethernet data port */
#define XE_ISR 6 /* Interrupt status register */
/*******************
* PCMCIA registers
*******************/
/*
* Command register values
* These are probably Dingo-specific, but you won't need them unless you have
* a CEM card that needs a bit of hackery to get the Ethernet function to
* operate. All addresses are in card attribute space.
*/
#define XE_CR_TX_PACKET 0x01
#define XE_CR_SOFT_RESET 0x02
#define XE_CR_ENABLE_INTR 0x04
#define XE_CR_FORCE_INTR 0x08
#define XE_CR_CLEAR_FIFO 0x10
#define XE_CR_CLEAR_OVERRUN 0x20
#define XE_CR_RESTART_TX 0x40
#define DINGO_CIS 0x0000 /* Start of CIS tuples */
#define DINGO_ETH 0x0800 /* Ethernet configuration registers */
#define DINGO_COR 0x0820 /* Dingo configuration option registers */
#define DINGO_2ND 0x0840 /* 2nd function configuration registers */
/*
* Status register values
* Ethernet configuration registers
*/
#define XE_ESR_FULL_PKT_RX 0x01
#define XE_ESR_PKT_REJECT 0x04
#define XE_ESR_TX_PENDING 0x08
#define XE_ESR_BAD_POLARITY 0x10
#define XE_ESR_MEDIA_SELECT 0x20
#define DINGO_ECOR (DINGO_ETH+0) /* Ethernet Configuration Option Register */
#define DINGO_ECSR (DINGO_ETH+2) /* Ethernet Configuration Status Register */
#define DINGO_EBAR0 (DINGO_ETH+10) /* Ethernet Base Address Register bits 7:4 (3:0 always 0) */
#define DINGO_EBAR1 (DINGO_ETH+12) /* Ethernet Base Address Register bits 15:8 */
/* DINGO_ECOR bits */
#define DINGO_ECOR_ETH_ENABLE 0x01 /* 1 = Enable Ethernet part of adapter */
#define DINGO_ECOR_IOB_ENABLE 0x02 /* 1 = Enable EBAR, else use INDEX bits */
#define DINGO_ECOR_INT_ENABLE 0x04 /* 1 = Enable Ethernet interrupts */
#define DINGO_ECOR_IOB_INDEX 0x18 /* 00 = 0x300; 01 = 0x310; 10 = 0x320; 11 = no IO base */
#define DINGO_ECOR_IOB_SHIFT 0x03
#define DINGO_ECOR_IRQ_STSCHG 0x20 /* 1 = Route interrupts to -STSCHG pin, else use -INT pin */
#define DINGO_ECOR_IRQ_LEVEL 0x40 /* 1 = Level-triggered interrupts, else edge-triggered */
#define DINGO_ECOR_SRESET 0x80 /* 1 = Soft reset Ethernet adpater. Must write to 0 */
/* DINGO_ECSR bits */
#define DINGO_ECSR_INT_ACK 0x01 /* 1 = Host must acknowledge interrupts (Clear ECSR_INT bit) */
#define DINGO_ECSR_INT 0x02 /* 1 = Interrupt service requested */
#define DINGO_ECSR_POWER_DOWN 0x04 /* 1 = Power down Ethernet adapter */
/*
* Interrupt register values
* EBAR0/EBAR1 set the I/O base address of the Ethernet adapter when
* ECOR_IOB_ENABLE is set. 12 significant bits.
*/
#define XE_ISR_TX_OVERFLOW 0x01
#define XE_ISR_TX_PACKET 0x02
#define XE_ISR_MAC_INTR 0x04
#define XE_ISR_TX_RES 0x08
#define XE_ISR_RX_PACKET 0x20
#define XE_ISR_RX_REJECT 0x40
#define XE_ISR_FORCE_INTR 0x80
/*
* Dingo configuration registers
*/
#define DINGO_DCOR0 (DINGO_COR+0) /* Dingo Configuration Options Register 0 */
#define DINGO_DCOR1 (DINGO_COR+2) /* Dingo Configuration Options Register 1 */
#define DINGO_DCOR2 (DINGO_COR+4) /* Dingo Configuration Options Register 2 */
#define DINGO_DCOR3 (DINGO_COR+6) /* Dingo Configuration Options Register 3 */
#define DINGO_DCOR4 (DINGO_COR+8) /* Dingo Configuration Options Register 4 */
/* DINGO_DCOR0 bits */
#define DINGO_DCOR0_SF_INT 0x01 /* 1 = Enable 2ndF interrupts (alternate to SFCOR:2) */
#define DINGO_DCOR0_DECODE 0x04 /* 1 = Decode 2ndF interrupts in Dingo, else in 2ndF */
#define DINGO_DCOR0_BUS 0x08 /* 1 = 2ndF bus is ISA, else PCMCIA */
#define DINGO_DCOR0_LED3_POWER 0x10 /* 1 = Drive LED3 line from SFCSR:2 */
#define DINGO_DCOR0_LED3_RESET 0x20 /* 1 = Drive LED3 line from SFCOR:7 */
#define DINGO_DCOR0_MR_POWER 0x40 /* 1 = Drive MRESET line from SFCSR:2 */
#define DINGO_DCOR0_MR_RESET 0x80 /* 1 = Drive MRESET line from SFCOR:7 */
/* DINGO_DCOR1 bits */
#define DINGO_DCOR1_INT_STSCHG 0x01 /* 1 = Route 2ndF interrupts to -STSCHG (alternate to SFCOR:5) */
#define DINGO_DCOR1_MSTSCHG 0x02 /* 1 = Route 2ndF -MSTSCHG line to -STSCHG */
#define DINGO_DCOR1_EEDIO 0x04 /* 1 = Use EEDIO pin as data line 6 to 2ndF */
#define DINGO_DCOR1_INT_LEVEL 0x08 /* 1 = Force level-triggered interrupts from 2ndF */
#define DINGO_DCOR1_SHADOW_CSR 0x10 /* Reserved, always write 0 */
#define DINGO_DCOR1_SHADOW_IOB 0x20 /* Reserved, always write 0 */
#define DINGO_DCOR1_CSR_WAIT 0xC0 /* Reserved, always write 0 */
#define DINGO_DCOR1_CSR_SHIFT 0x06
/* DINGO_DCOR2 bits */
#define DINGO_DCOR2_SHM_BASE 0x0f /* Bits 15-12 of Ethernet shared memory window */
#define DINGO_DCOR2_SHM_SHIFT 0x00
#define DINGO_DCOR2_SHADOW_COR 0x10 /* Reserved, always write 0 */
/*
* DCOR3/DCOR4 configure Dingo to assert -IOIS16 on any access to each pair of
* ports in the range SFIOB+0 .. SFIOB+31. Each pair can be set individually,
* eg. DCOR3:0 enables this function on ports SFIOB+0 and SFIOB+1.
*/
/*
* Second function configuration registers
*/
#define DINGO_SFCOR (DINGO_2ND+0) /* 2nd Function Configuration Option Register */
#define DINGO_SFCSR (DINGO_2ND+2) /* 2nd Function Configuration Status Register */
#define DINGO_SFBAR0 (DINGO_2ND+10) /* 2nd Function Base Address Register bits 7:0 */
#define DINGO_SFBAR1 (DINGO_2ND+12) /* 2nd Function Base Address Register bits 15:8 */
#define DINGO_SFILR (DINGO_2ND+18) /* 2nd Function I/O Limit Register */
/* DINGO_SFCOR bits */
#define DINGO_SFCOR_SF_ENABLE 0x01 /* 1 = Enable second fuction */
#define DINGO_SFCOR_IOB_ENABLE 0x02 /* 1 = Enable SFBAR, else use COM_SELECT bits */
#define DINGO_SFCOR_INT_ENABLE 0x04 /* 1 = Enable second function interrupts */
#define DINGO_SFCOR_COM_SELECT 0x18 /* 00 = 0x3f8; 01 = 0x2f8; 10 = 0x3e8; 11 = 0x2e8 */
#define DINGO_SFCOR_COM_SHIFT 0x03
#define DINGO_SFCOR_IRQ_STSCHG 0x20 /* 1 = Route interrupts to -STSCHG pin, else use -INT pin */
#define DINGO_SFCOR_IRQ_LEVEL 0x40 /* 1 = Level-triggered interrupts, else edge-triggered */
#define DINGO_SFCOR_SRESET 0x80 /* 1 = Soft reset second function. Must write to 0 */
/* DINGO_SFCSR bits */
#define DINGO_SFCSR_INT_ACK 0x01 /* 1 = Host must acknowledge interrupts (Clear SFCSR_INT bit) */
#define DINGO_SFCSR_INT 0x02 /* 1 = Interrupt service requested */
#define DINGO_SFCSR_POWER_DOWN 0x04 /* 1 = Power down second function */
/*
* SFBAR0/SFBAR1 set the I/O base address of the second function when
* SFCOR_IOB_ENABLE is set. 16 significant bits.
*/
/*
* SFILR is a bitmap of address lines 7:0 decoded by the second function
* device. Eg. a device with 16 ports should write 0x0f to this register.
*/
/********************************
* Ethernet controller registers
********************************/
/*
* Common registers (available from any register page)
*
* Note: The EDP is actually 32 bits wide, occupying registers 2-5. In PCMCIA
* operation we can only access 16 bits at once, through registers 4 & 5.
*/
#define XE_CR 0x00 /* Command register (write) */
#define XE_ESR 0x00 /* Ethernet status register (read) */
#define XE_PR 0x01 /* Page select register */
#define XE_EDP 0x04 /* Ethernet data port */
#define XE_ISR 0x06 /* Ethernet interrupt status register (read) */
#define XE_GIR 0x07 /* Global interrupt register (Dingo only) */
/* XE_CR bits */
#define XE_CR_TX_PACKET 0x01 /* Transmit packet */
#define XE_CR_SOFT_RESET 0x02 /* Software reset */
#define XE_CR_ENABLE_INTR 0x04 /* Enable interrupts */
#define XE_CR_FORCE_INTR 0x08 /* Force an interrupt */
#define XE_CR_CLEAR_FIFO 0x10 /* Clear FIFO after transmit overrun */
#define XE_CR_CLEAR_OVERRUN 0x20 /* Clear receive overrun condition */
#define XE_CR_RESTART_TX 0x40 /* Restart TX after 16 collisions or TX underrun */
/* XE_ESR bits */
#define XE_ESR_FULL_PACKET_RX 0x01 /* At least one full packet received */
#define XE_ESR_PART_PACKET_RX 0x02 /* At least 64 bytes of packet received */
#define XE_ESR_REJECT_PACKET 0x04 /* Partial packet rejected */
#define XE_ESR_TX_PENDING 0x08 /* At least one packet waiting to transmit */
#define XE_ESR_BAD_POLARITY 0x10 /* Bad cable polarity? (CE2 only) */
#define XE_ESR_MEDIA_SELECT 0x20 /* SSI(?) media select: 1 = Twisted pair; 0 = AUI */
/* XE_ISR bits */
#define XE_ISR_TX_OVERFLOW 0x01 /* No space in transmit buffer */
#define XE_ISR_TX_PACKET 0x02 /* Packet sent successfully */
#define XE_ISR_MAC_INTR 0x04 /* Some kind of MAC interrupt happened */
#define XE_ISR_RX_EARLY 0x10 /* Incoming packet in early receive mode */
#define XE_ISR_RX_PACKET 0x20 /* Complete packet received successfully */
#define XE_ISR_RX_REJECT 0x40 /* Partial incoming packet rejected by MAC */
#define XE_ISR_FORCE_INTR 0x80 /* Interrupt forced */
/* XE_GIR bits */
#define XE_GIR_ETH_IRQ 0x01 /* Ethernet IRQ pending */
#define XE_GIR_ETH_MASK 0x02 /* 1 = Mask Ethernet interrupts to host */
#define XE_GIR_SF_IRQ 0x04 /* Second function IRQ pending */
#define XE_GIR_SF_MASK 0x08 /* 1 = Mask second function interrupts to host */
/*
* Page 0 registers
*/
#define XE_TSO 8 /* Transmit space open */
#define XE_TRS 10 /* Transmit reservation size */
#define XE_DOR 12 /* Data offset register (write) */
#define XE_RSR 12 /* Receive status register (read) */
#define XE_PTR 13 /* Packets transmitted register (read) */
#define XE_RBC 14 /* Received byte count (read) */
#define XE_TSO 0x08 /* Transmit space open (17 bits) */
#define XE_TRS 0x0a /* Transmit reservation size (CE2 only, removed in rev. 1) */
#define XE_DO 0x0c /* Data offset register (13 bits/3 flags, write) */
#define XE_RSR 0x0c /* Receive status register (read) */
#define XE_TPR 0x0d /* Packets transmitted register (read) */
#define XE_RBC 0x0e /* Received byte count (13 bits/3 flags, read) */
/*
* RSR values
*/
#define XE_RSR_PHYS_PKT 0x01
#define XE_RSR_BCAST_PKT 0x02
#define XE_RSR_LONG_PKT 0x04
#define XE_RSR_ALIGN_ERR 0x10
#define XE_RSR_CRC_ERR 0x20
#define XE_RSR_RX_OK 0x80
/* XE_DO bits */
#define XE_DO_OFFSET 0x1fff /* First byte fetched when CHANGE_OFFSET issued */
#define XE_DO_OFFSET_SHIFT 0x00
#define XE_DO_CHANGE_OFFSET 0x2000 /* Flush RX FIFO, start fetching from OFFSET */
#define XE_DO_SHARED_MEM 0x4000 /* Enable shared memory mode */
#define XE_DO_SKIP_RX_PACKET 0x8000 /* Skip to next packet in buffer memory */
/* XE_RSR bits */
#define XE_RSR_PHYS_PACKET 0x01 /* 1 = Physical packet, 0 = Multicast packet */
#define XE_RSR_BCAST_PACKET 0x02 /* Broadcast packet */
#define XE_RSR_LONG_PACKET 0x04 /* Packet >1518 bytes */
#define XE_RSR_ADDR_MATCH 0x08 /* Packet matched one of our node addresses */
#define XE_RSR_ALIGN_ERROR 0x10 /* Bad alignment? (CE2 only) */
#define XE_RSR_CRC_ERROR 0x20 /* Incorrect CRC */
#define XE_RSR_RX_OK 0x80 /* No errors on received packet */
/* XE_RBC bits */
#define XE_RBC_BYTE_COUNT 0x1fff /* Bytes received for current packet */
#define XE_RBC_COUNT_SHIFT 0x00
#define XE_RBC_FULL_PACKET_RX 0x2000 /* These mirror bits 2:0 of ESR, if ECR:7 is set */
#define XE_RBC_PART_PACKET_RX 0x4000
#define XE_RBC_REJECT_PACKET 0x8000
/*
* Page 1 registers
*/
#define XE_IMR0 12 /* Interrupt mask register, part 1 */
#define XE_IMR1 13 /* Interrupt mask register, part 2 */
#define XE_ECR 14 /* Ethernet configuration register */
#define XE_IMR0 0x0c /* Interrupt mask register 0 */
#define XE_IMR1 0x0d /* Interrupt mask register 1 (CE2 only) */
#define XE_ECR 0x0e /* Ethernet configuration register */
/*
* ECR values
*/
#define XE_ECR_FULL_DUPLEX 0x04
#define XE_ECR_LONG_TPCABLE 0x08
#define XE_ECR_NO_POLCOL 0x10
#define XE_ECR_NO_LINKPULSE 0x20
#define XE_ECR_NO_AUTOTX 0x40
/* XE_IMR0 bits */
#define XE_IMR0_TX_OVERFLOW 0x01 /* Masks for bits in ISR */
#define XE_IMR0_TX_PACKET 0x02
#define XE_IMR0_MAC_INTR 0x04
#define XE_IMR0_RX_EARLY 0x10
#define XE_IMR0_RX_PACKET 0x20
#define XE_IMR0_RX_REJECT 0x40
#define XE_IMR0_FORCE_INTR 0x80
/* XE_ECR bits */
#define XE_ECR_EARLY_TX 0x01 /* Enable early transmit mode */
#define XE_ECR_EARLY_RX 0x02 /* Enable early receive mode */
#define XE_ECR_FULL_DUPLEX 0x04 /* Enable full-duplex (disable collision detection) */
#define XE_ECR_LONG_TPCABLE 0x08 /* CE2 only */
#define XE_ECR_NO_POL_COL 0x10 /* CE2 only */
#define XE_ECR_NO_LINK_PULSE 0x20 /* Don't check/send link pulses (not 10BT compliant) */
#define XE_ECR_NO_AUTO_TX 0x40 /* CE2 only */
#define XE_ECR_SOFT_COMPAT 0x80 /* Map ESR bits 2:0 to RBC bits 15:13 */
/*
* Page 2 registers
*/
#define XE_RBS 8 /* Receive buffer start */
#define XE_LED 10 /* LED configuration register */
#define XE_MSR 12 /* Mohawk specfic register (Mohawk = CE3) */
#define XE_GPR2 13 /* General purpose register 2 */
#define XE_RBS 0x08 /* Receive buffer start (16 bits) */
#define XE_LED 0x0a /* LED control register */
#define XE_LED3 0x0b /* LED3 control register */
#define XE_MSR 0x0c /* Misc. setup register (Mohawk specific register?) */
#define XE_GPR2 0x0d /* General purpose register 2 */
/*
* LED function selection:
* 000 - Disabled
* 001 - Collision activity
* 010 - !Collision activity
* 011 - 10Mbit link detected
* 100 - 100Mbit link detected
* 101 - 10/100Mbit link detected
* 110 - Automatic assertion
* 111 - Transmit activity
*/
/* XE_LED bits */
#define XE_LED_LED0_MASK 0x07 /* LED0 function selection */
#define XE_LED_LED0_SHIFT 0x00
#define XE_LED_LED1_MASK 0x38 /* LED1 function selection */
#define XE_LED_LED1_SHIFT 0x03
#define XE_LED_LED0_RX 0x40 /* Add receive activity to LED0 */
#define XE_LED_LED1_RX 0x80 /* Add receive activity to LED1 */
/* XE_LED3 bits */
#define XE_LED3_MASK 0x07 /* LED3 function selection */
#define XE_LED3_SHIFT 0x00
#define XE_LED3_RX 0x40 /* Add receive activity to LED3 */
/* XE_MSR bits */
#define XE_MSR_128K_SRAM 0x01 /* Select 128K SRAM */
#define XE_MSR_RBS_BIT16 0x02 /* Bit 16 of RBS (only useful with big SRAM) */
#define XE_MSR_MII_SELECT 0x08 /* Select MII instead of SSI interface */
#define XE_MSR_HASH_TABLE 0x20 /* Enable hash table filtering */
/* XE_GPR2 bits */
#define XE_GPR2_GP3_OUT 0x01 /* Value written to GP3 line */
#define XE_GPR2_GP4_OUT 0x02 /* Value written to GP4 line */
#define XE_GPR2_GP3_SELECT 0x04 /* 1 = GP3 is output, 0 = GP3 is input */
#define XE_GPR2_GP4_SELECT 0x08 /* 1 = GP4 is output, 0 = GP3 is input */
#define XE_GPR2_GP3_IN 0x10 /* Value read from GP3 line */
#define XE_GPR2_GP4_IN 0x20 /* Value read from GP4 line */
/*
* Page 3 registers
*/
#define XE_TPT 0x0a /* Transmit packet threshold (13 bits) */
/*
* Page 4 registers
*/
#define XE_GPR0 8 /* General purpose register 0 */
#define XE_GPR1 9 /* General purpose register 1 */
#define XE_BOV 10 /* Bonding version register */
#define XE_LMA 12 /* Local memory address */
#define XE_LMD 14 /* Local memory data */
#define XE_GPR0 0x08 /* General purpose register 0 */
#define XE_GPR1 0x09 /* General purpose register 1 */
#define XE_BOV 0x0a /* Bonding version register (read) */
#define XE_EES 0x0b /* EEPROM control register */
#define XE_LMA 0x0c /* Local memory address (CE2 only) */
#define XE_LMD 0x0e /* Local memory data (CE2 only) */
/* XE_GPR0 bits */
#define XE_GPR0_GP1_OUT 0x01 /* Value written to GP1 line */
#define XE_GPR0_GP2_OUT 0x02 /* Value wirtten to GP2 line */
#define XE_GPR0_GP1_SELECT 0x04 /* 1 = GP1 is output, 0 = GP1 is input */
#define XE_GPR0_GP2_SELECT 0x08 /* 1 = GP2 is output, 0 = GP2 is input */
#define XE_GPR0_GP1_IN 0x10 /* Value read from GP1 line */
#define XE_GPR0_GP2_IN 0x20 /* Value read from GP2 line */
/* XE_GPR1 bits */
#define XE_GPR1_POWER_DOWN 0x01 /* Power down analog section (down to 20mA load) */
/* XE_BOV values */
#define XE_BOV_DINGO 0x55 /* Dingo in Dingo mode */
#define XE_BOV_MOHAWK 0x41 /* Original Mohawk */
#define XE_BOV_MOHAWK_REV1 0x45 /* Rev. 1 Mohawk, or Dingo in Mohawk mode */
#define XE_BOV_CEM28 0x11 /* CEM28 */
/* XE_EES bits */
#define XE_EES_SCL_OUTPUT 0x01 /* Value written to SCL line, when MANUAL_ROM set */
#define XE_EES_SDA_OUTPUT 0x02 /* Value written to SDA line, when MANUAL_ROM set */
#define XE_EES_SDA_INPUT 0x04 /* Value read from SDA line */
#define XE_EES_SDA_TRISTATE 0x08 /* 1 = SDA is output, 0 = SDA is input */
#define XE_EES_MANUAL_ROM 0x20 /* Enable manual contro of serial EEPROM */
/*
* Page 5 registers
* Page 5 registers (all read only)
*/
#define XE_RHS 10 /* Receive host start address */
#define XE_CRHA 0x08 /* Current Rx host address (16 bits) */
#define XE_RHSA 0x0a /* Rx host start address (16 bits) */
#define XE_RNSA 0x0c /* Rx network start address (16 bits) */
#define XE_CRNA 0x0e /* Current Rx network address (16 bits) */
/*
* Page 6 registers (all read only)
*/
#define XE_CTHA 0x08 /* Current Tx host address (16 bits) */
#define XE_THSA 0x0a /* Tx host start address (16 bits) */
#define XE_TNSA 0x0c /* Tx network statr address (16 bits) */
#define XE_CTNA 0x0e /* Current Tx network address (16 bits) */
/*
* Page 8 registers (all read only)
*/
#define XE_THBC 0x08 /* Tx host byte count (16 bits) */
#define XE_THPS 0x0a /* Tx host packet size (16 bits) */
#define XE_TNBC 0x0c /* Tx network byte count (16 bits) */
#define XE_TNPS 0x0e /* Tx network packet size (16 bits) */
/*
* Page 0x10 registers (all read only)
*/
#define XE_DINGOID 0x08 /* Dingo ID register (16 bits) (Dingo only) */
#define XE_RevID 0x0a /* Dingo revision ID (16 bits) (Dingo only) */
#define XE_VendorID 0x0c /* Dingo vendor ID (16 bits) (Dingo only) */
/* Values for the above registers */
#define XE_DINGOID_DINGO3 0x444b /* In both Dingo and Mohawk modes */
#define XE_RevID_DINGO3 0x0001
#define XE_VendorID_DINGO3 0x0041
/*
* Page 0x40 registers
*/
#define XE_OCR 8 /* The Other command register */
#define XE_RXS0 9 /* Receive status 0 */
#define XE_TXS0 11 /* Transmit status 0 */
#define XE_TXS1 12 /* Transmit status 1 */
#define XE_RXM0 13 /* Receive mask register 0 */
#define XE_TXM0 14 /* Transmit mask register 0 */
#define XE_TXM1 15 /* Transmit mask register 1 */
#define XE_CMD0 0x08 /* MAC Command register (write) */
#define XE_RST0 0x09 /* Receive status register */
#define XE_TXST0 0x0b /* Transmit status register 0 */
#define XE_TXST1 0x0c /* Transmit status register 1 */
#define XE_RX0Msk 0x0d /* Receive status mask register */
#define XE_TX0Msk 0x0e /* Transmit status 0 mask register */
#define XE_TX1Msk 0x0f /* Transmit status 1 mask register */
/*
* OCR values
*/
#define XE_OCR_TX 0x01
#define XE_OCR_RX_ENABLE 0x04
#define XE_OCR_RX_DISABLE 0x08
#define XE_OCR_ABORT 0x10
#define XE_OCR_ONLINE 0x20
#define XE_OCR_ACK_INTR 0x40
#define XE_OCR_OFFLINE 0x80
/* CMD0 bits */
#define XE_CMD0_TX 0x01 /* CE2 only */
#define XE_CMD0_RX_ENABLE 0x04 /* Enable receiver */
#define XE_CMD0_RX_DISABLE 0x08 /* Disable receiver */
#define XE_CMD0_ABORT 0x10 /* CE2 only */
#define XE_CMD0_ONLINE 0x20 /* Take MAC online */
#define XE_CMD0_ACK_INTR 0x40 /* CE2 only */
#define XE_CMD0_OFFLINE 0x80 /* Take MAC offline */
/* RST0 bits */
#define XE_RST0_LONG_PACKET 0x02 /* Packet received with >1518 and <8184 bytes */
#define XE_RST0_CRC_ERROR 0x08 /* Packet received with incorrect CRC */
#define XE_RST0_RX_OVERRUN 0x10 /* Receiver overrun, byte(s) dropped */
#define XE_RST0_RX_ENABLE 0x20 /* Receiver enabled */
#define XE_RST0_RX_ABORT 0x40 /* Receive aborted: CRC, FIFO overrun or addr mismatch */
#define XE_RST0_RX_OK 0x80 /* Complete packet received OK */
/* TXST0 bits */
#define XE_TXST0_NO_CARRIER 0x01 /* Lost carrier. Only valid in 10Mbit half-duplex */
#define XE_TXST0_16_COLLISIONS 0x02 /* Packet aborted after 16 collisions */
#define XE_TXST0_TX_UNDERRUN 0x08 /* MAC ran out of data to send */
#define XE_TXST0_LATE_COLLISION 0x10 /* Collision later than 512 bits */
#define XE_TXST0_SQE_FAIL 0x20 /* SQE test failed. */
#define XE_TXST0_TX_ABORT 0x40 /* Transmit aborted: collisions, underrun or overrun */
#define XE_TXST0_TX_OK 0x80 /* Complete packet sent OK */
/* TXST1 bits */
#define XE_TXST1_RETRY_COUNT 0x0f /* Collision counter for current packet */
#define XE_TXST1_LINK_STATUS 0x10 /* Valid link status */
/* RX0Msk bits */
#define XE_RX0M_LONG_PACKET 0x02 /* Masks for bits in RXST0 */
#define XE_RX0M_ALIGN_ERROR 0x04 /* Alignment error (CE2 only) */
#define XE_RX0M_CRC_ERROR 0x08
#define XE_RX0M_RX_OVERRUN 0x10
#define XE_RX0M_RX_ABORT 0x40
#define XE_RX0M_RX_OK 0x80
/* TX0Msk bits */
#define XE_TX0M_NO_CARRIER 0x01 /* Masks for bits in TXST0 */
#define XE_TX0M_16_COLLISIONS 0x02
#define XE_TX0M_TX_UNDERRUN 0x08
#define XE_TX0M_LATE_COLLISION 0x10
#define XE_TX0M_SQE_FAIL 0x20
#define XE_TX0M_TX_ABORT 0x40
#define XE_TX0M_TX_OK 0x80
/* TX1Msk bits */
#define XE_TX1M_PKTDEF 0x20
/*
* Page 0x42 registers
*/
#define XE_SWC0 8 /* Software configuration register 0 */
#define XE_SWC1 9 /* Software configuration register 1 */
#define XE_BOC 10 /* Back-off configuration */
#define XE_SWC0 0x08 /* Software configuration 0 */
#define XE_SWC1 0x09 /* Software configuration 1 */
#define XE_BOC 0x0a /* Back-off configuration */
#define XE_TCD 0x0b /* Transmit collision deferral */
/* SWC0 bits */
#define XE_SWC0_LOOPBACK_ENABLE 0x01 /* Enable loopback operation */
#define XE_SWC0_LOOPBACK_SOURCE 0x02 /* 1 = Transceiver, 0 = MAC */
#define XE_SWC0_ACCEPT_ERROR 0x04 /* Accept otherwise OK packets with CRC errors */
#define XE_SWC0_ACCEPT_SHORT 0x08 /* Accept otherwise OK packets that are too short */
#define XE_SWC0_NO_CRC_INSERT 0x40 /* Don't add CRC to outgoing packets */
/* SWC1 bits */
#define XE_SWC1_IA_ENABLE 0x01 /* Enable individual address filters */
#define XE_SWC1_ALLMULTI 0x02 /* Accept all multicast packets */
#define XE_SWC1_PROMISCUOUS 0x04 /* Accept all non-multicast packets */
#define XE_SWC1_BCAST_DISABLE 0x08 /* Reject broadcast packets */
#define XE_SWC1_MEDIA_SELECT 0x40 /* AUI media select (Mohawk only) */
#define XE_SWC1_AUTO_MEDIA 0x80 /* Auto media select (Mohawk only) */
/*
* Page 0x44 registers
* Page 0x44 registers (CE2 only)
*/
#define XE_TDR0 8 /* Time domain reflectometry register 0 */
#define XE_TDR1 9 /* Time domain reflectometry register 1 */
#define XE_RXC0 10 /* Receive byte count low */
#define XE_RXC1 11 /* Receive byte count high */
#define XE_TDR0 0x08 /* Time domain reflectometry register 0 */
#define XE_TDR1 0x09 /* Time domain reflectometry register 1 */
#define XE_RXC0 0x0a /* Receive byte count low */
#define XE_RXC1 0x0b /* Receive byte count high */
/*
* Page 0x45 registers
* Page 0x45 registers (CE2 only)
*/
#define XE_REV 15 /* Revision (read) */
#define XE_REV 0x0f /* Revision (read) */
/*
* Page 0x50 registers
*/
#define XE_IAR 8 /* Individual address register */
/*
* Pages 0x43, 0x46-0x4f and 0x51-0x5e apparently don't exist.
* The remainder of 0x0-0x8 and 0x40-0x5f exist, but I have no
* idea what's on most of them.
*/
/*
* Definitions for the Micro Linear ML6692 100Base-TX PHY, which handles the
* 100Mbit functionality of CE3 type cards, including media autonegotiation.
* It appears to be mostly compatible with the National Semiconductor
* DP83840A, but with a much smaller register set. Please refer to the data
* sheets for these devices for the definitive word on what all this stuff
* means :)
* Page 0x50-0x57: Individual address 0-9
*
* Note that the ML6692 has no 10Mbit capability -- that is handled by another
* chip that we don't know anything about.
* Used to filter incoming packets by matching against individual node
* addresses. If IA matching is enabled (SWC1, bit0) any incoming packet with
* a destination matching one of these 10 addresses will be received. IA0 is
* always enabled and usually matches the card's unique address.
*
* Most of these definitions were adapted from the xl driver.
* Addresses are stored LSB first, ie. IA00 (reg. 8 on page 0x50) contains the
* LSB of IA0, and so on. The data is stored contiguously, in that addresses
* can be broken across page boundaries. That is:
*
* Reg: 50/8 50/9 50/a 50/b 50/c 50/d 50/e 50/f 51/8 51/9 ... 57/a 57/b
* IA00 IA01 IA02 IA03 IA04 IA05 IA10 IA11 IA12 IA13 ... IA94 IA95
*/
/*
* Masks for the MII-related bits in GPR2. For some reason read and write
* data are on separate bits.
* Page 0x58: Multicast hash table filter
*
* In case the 10 individual addresses aren't enough, we also have a multicast
* hash filter, enabled through MSR:5. The most significant six bits of the
* CRC on each incoming packet are reversed and used as an index into the 64
* bits of the hash table. If the appropriate bit is set the packet it
* received, although higher layers may still need to filter it out. The CRC
* calculation is as follows:
*
* crc = 0xffffffff;
* poly = 0x04c11db6;
* for (i = 0; i < 6; i++) {
* current = mcast_addr[i];
* for (k = 1; k <= 8; k++) {
* if (crc & 0x80000000);
* crc31 = 0x01;
* else
* crc31 = 0;
* bit = crc31 ^ (current & 0x01);
* crc <<= 1;
* current >>= 1;
* if (bit)
* crc = (crc ^ poly)|1
* }
* }
*/
#define XE_MII_CLK 0x01
#define XE_MII_DIR 0x08
#define XE_MII_WRD 0x02
#define XE_MII_RDD 0x20
/****************
* MII registers
****************/
/*
* Basic MII-compliant PHY register definitions. According to the Dingo spec,
* PHYs from (at least) MicroLinear, National Semiconductor, ICS, TDK and
* Quality Semiconductor have been used. These apparently all come up with
* PHY ID 0x00 unless the "interceptor module" on the Dingo 3 is in use. With
* the interceptor enabled, the PHY is faked up to look like an ICS unit with
* ID 0x16. The interceptor can be enabled/disabled in software.
*
* The ML6692 (and maybe others) doesn't have a 10Mbps mode -- this is handled
* by an internal 10Mbps transceiver that we know nothing about... some cards
* seem to work with the MII in 10Mbps mode, so I guess some PHYs must support
* it. The question is, how can you figure out which one you have? Just to
* add to the fun there are also 10Mbps _only_ Mohawk/Dingo cards. Aaargh!
*/
/*
* Masks for the MII-related bits in GPR2
*/
#define XE_MII_CLK XE_GPR2_GP3_OUT
#define XE_MII_DIR XE_GPR2_GP4_SELECT
#define XE_MII_WRD XE_GPR2_GP4_OUT
#define XE_MII_RDD XE_GPR2_GP4_IN
/*
* MII PHY ID register values
*/
#define PHY_ID_ML6692 0x0000 /* MicroLinear ML6692? Or unknown */
#define PHY_ID_ICS1890 0x0015 /* ICS1890 */
#define PHY_ID_QS6612 0x0181 /* Quality QS6612 */
#define PHY_ID_DP83840 0x2000 /* National DP83840 */
/*
* MII command (etc) bit strings.
@ -236,10 +626,13 @@
*/
#define PHY_BMCR 0x00 /* Basic Mode Control Register */
#define PHY_BMSR 0x01 /* Basic Mode Status Register */
#define PHY_ID1 0x02 /* PHY ID 1 */
#define PHY_ID2 0x03 /* PHY ID 2 */
#define PHY_ANAR 0x04 /* Auto-Negotiation Advertisment Register */
#define PHY_LPAR 0x05 /* Auto-Negotiation Link Partner Ability Register */
#define PHY_ANER 0x06 /* Auto-Negotiation Expansion Register */
/* BMCR bits */
#define PHY_BMCR_RESET 0x8000 /* Soft reset PHY. Self-clearing */
#define PHY_BMCR_LOOPBK 0x4000 /* Enable loopback */
#define PHY_BMCR_SPEEDSEL 0x2000 /* 1=100Mbps, 0=10Mbps */
@ -249,6 +642,7 @@
#define PHY_BMCR_DUPLEX 0x0100 /* Full duplex operation */
#define PHY_BMCR_COLLTEST 0x0080 /* Enable collision test */
/* BMSR bits */
#define PHY_BMSR_100BT4 0x8000 /* 100Base-T4 capable */
#define PHY_BMSR_100BTXFULL 0x4000 /* 100Base-TX full duplex capable */
#define PHY_BMSR_100BTXHALF 0x2000 /* 100Base-TX half duplex capable */
@ -259,6 +653,7 @@
#define PHY_BMSR_LINKSTAT 0x0004 /* Link is up */
#define PHY_BMSR_EXTENDED 0x0001 /* Extended register capabilities */
/* ANAR bits */
#define PHY_ANAR_NEXTPAGE 0x8000 /* Additional link code word pages */
#define PHY_ANAR_TLRFLT 0x2000 /* Remote wire fault detected */
#define PHY_ANAR_100BT4 0x0200 /* 100Base-T4 capable */
@ -271,7 +666,11 @@
#define PHY_ANAR_PROTO2 0x0004
#define PHY_ANAR_PROTO1 0x0002
#define PHY_ANAR_PROTO0 0x0001
#define PHY_ANAR_8023 PHY_ANAR_PROTO0
#define PHY_ANAR_DINGO PHY_ANAR_100BT+PHY_ANAR_10BT_FD+PHY_ANAR_10BT+PHY_ANAR_8023
#define PHY_ANAR_MOHAWK PHY_ANAR_100BT+PHY_ANAR_10BT_FD+PHY_ANAR_10BT+PHY_ANAR_8023
/* LPAR bits */
#define PHY_LPAR_NEXTPAGE 0x8000 /* Additional link code word pages */
#define PHY_LPAR_LPACK 0x4000 /* Link partner acknowledged receipt */
#define PHY_LPAR_TLRFLT 0x2000 /* Remote wire fault detected */
@ -286,6 +685,7 @@
#define PHY_LPAR_PROTO1 0x0002
#define PHY_LPAR_PROTO0 0x0001
/* ANER bits */
#define PHY_ANER_MLFAULT 0x0010 /* More than one link is up! */
#define PHY_ANER_LPNPABLE 0x0008 /* Link partner supports next page */
#define PHY_ANER_NPABLE 0x0004 /* Local port supports next page */