summaryrefslogtreecommitdiffstats
path: root/sys/dev/xe
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-05-14 01:58:59 +0000
committerobrien <obrien@FreeBSD.org>1999-05-14 01:58:59 +0000
commite2d43e406c247d549b4d41740854d7a58e8c88b0 (patch)
tree586e52c8034ac9605438b996fcb0f343b11759c0 /sys/dev/xe
parent1f02744948dbb75039617d296985a2a6e7a6b1e3 (diff)
downloadFreeBSD-src-e2d43e406c247d549b4d41740854d7a58e8c88b0.zip
FreeBSD-src-e2d43e406c247d549b4d41740854d7a58e8c88b0.tar.gz
Virgin import of Xircom PCCARD driver v1.17
v1.17 (1999/03/28) has xperimental fixes to 10Mbit autonegotiation and CE2 input lockup. KNOWN BUGS ========== * Media auto-negotiation is definitely not right. It will work in most circumstances and seems to connect OK to most 100Mbit networks, however some pathological combinations of hubs/networks/peers seem to confuse it. * CE2 support is somewhat flakey (ranging from 'works perfectly' to 'hangs the machine' so far). I've fixed the probe routine and a potential lockup in the output routine, but a lot of people still report that they can't receive or transmit. * You won't be able to use the modem and Ethenet parts of a multifunction card simultaneously. This is limitation the current FreeBSD PCMCIA support. Likewise, there is no support for CardBus devices. Developed by: Scott Mitchell <scott@uk.freebsd.org> Obtained from: http://www.freebsd-uk.eu.org/~scott/xe_drv/
Diffstat (limited to 'sys/dev/xe')
-rw-r--r--sys/dev/xe/if_xe.c121
1 files changed, 87 insertions, 34 deletions
diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c
index 776eb32..78d52ac 100644
--- a/sys/dev/xe/if_xe.c
+++ b/sys/dev/xe/if_xe.c
@@ -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.16 1999/03/08 16:28:50 root Exp $
+ * $Id: if_xe.c,v 1.17 1999/03/28 20:27:24 scott Exp $
*/
/*
@@ -60,28 +60,29 @@
*/
/*
- * FreeBSD device driver for Xircom CreditCard PCMCIA Ethernet adapters.
- * The following cards and media are supported (Ethernet part only on the
- * multifunction CEM cards):
+ * FreeBSD device driver for Xircom CreditCard PCMCIA Ethernet adapters. The
+ * following cards and media are, or will eventually be, supported (Ethernet
+ * part only on the multifunction CEM cards):
* CE2 10BASE-2, 10BASE-T (I think)
* CEM28 ditto
* CEM33 ditto
* CE3 10BASE-T, 100BASE-TX
* CEM56 ditto
* RealPort ditto
- * Some Compaq and Intel cards using the Xircom hardware are also known to
+ * Compaq and Intel cards using the Xircom CE3 hardware are also known to
* work. See the website for full details of supported hardware.
*
- * <Acknowledgements to go here>
+ * Thanks to all who assisted with the development and testing of the driver,
+ * especially: Werner Koch, Duke Kamstra, Duncan Barclay, Ade Lovett, Jason
+ * George, Dru Nelson, Mike Kephart, Bill Rainey and Douglas Rand. Apologies
+ * if I've left out anyone who deserves a mention here.
*
- * The web page for the driver is located at:
- * http://www.dcs.qmw.ac.uk/~scott/xe_drv/
- * Check here first for new releases, bug fixes, etc.
+ * Driver web page: http://www.freebsd-uk.eu.org/~scott/xe_drv/
*
- * Please send all feedback, bug reports, patches, etc. to
- * <scott@dcs.qmw.ac.uk>. Mail with the tag "[XE]" in the subject line will
- * be automatically filed in an appropriate folder where I'm more likely to
- * see it and respond promptly.
+ * Mailing list: http://www.lovett.com/lists/freebsd-xircom/
+ * or send "subscribe freebsd-xircom" to <majordomo@lovett.com>
+ *
+ * Author email: <scott@freebsd-uk.eu.org>
*/
#define XE_DEBUG 1
@@ -303,6 +304,9 @@ struct isa_driver xedriver = {
*/
static int
xe_probe (struct isa_device *dev) {
+#ifdef XE_DEBUG
+ printf("xe: probe\n");
+#endif
bzero(sca, MAXSLOT * sizeof(sca[0]));
return 0;
}
@@ -383,6 +387,7 @@ xe_card_init(struct pccard_devinfo *devi)
* 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!
*/
if ((rc = cdevsw[CARD_MAJOR]->d_read(makedev(CARD_MAJOR, devi->slt->slotnum), &uios, 0)) == 0) {
@@ -942,7 +947,7 @@ xe_card_intr(struct pccard_devinfo *devi) {
* any outstanding collisions count will be held against the next
* frame to be successfully sent. Hopefully it averages out in the
* end!
- * XXX - This will screw up if tx_collisions/sent > 14.
+ * XXX - This will screw up if tx_collisions/sent > 14. FIX IT!
*/
switch (scp->tx_collisions) {
case 0:
@@ -1065,10 +1070,13 @@ xe_card_intr(struct pccard_devinfo *devi) {
int i;
/*
- * XXX - this i-- seems very wrong, but it's what the Linux guys
+ * XXX - This i-- seems very wrong, but it's what the Linux guys
* XXX - do. Need someone with an old CE2 to test this for me.
+ * XXX - 99/3/28: Changed the first i-- to an i++, maybe that'll
+ * XXX - fix it? It seems as though the previous version would
+ * XXX - have caused an infinite loop (what, another one?).
*/
- for (i = 0; i < len; i--, rhs++) {
+ for (i = 0; i < len; i++, rhs++) {
((char *)ehp)[i] = XE_INB(XE_EDP);
if (rhs = 0x8000) {
rhs = 0;
@@ -1139,7 +1147,7 @@ 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 - Maybe force an int here, instead of dropping packets? */
+ /* XXX - Could force an int here, instead of dropping packets? */
/* XXX - XE_OUTB(XE_CR, XE_CR_ENABLE_INTR|XE_CE_FORCE_INTR); */
return result;
@@ -1216,7 +1224,7 @@ xe_media_status(struct ifnet *ifp, struct ifmediareq *mrp) {
*/
static void xe_setmedia(void *xscp) {
struct xe_softc *scp = xscp;
- u_int16_t bmcr, bmsr, anar, lpar, aner;
+ u_int16_t bmcr, bmsr, anar, lpar;
#ifdef XE_DEBUG
printf("xe%d: setmedia\n", scp->unit);
@@ -1319,10 +1327,24 @@ static void xe_setmedia(void *xscp) {
scp->autoneg_status = XE_AUTONEG_NONE;
}
else {
+ /*
+ * XXX - Bit of a hack going on in here.
+ * XXX - This is derived from Ken Hughes patch to the Linux driver
+ * XXX - to make it work with 10Mbit _autonegotiated_ links on CE3B
+ * XXX - cards. What's a CE3B and how's it differ from a plain CE3?
+ * XXX - these are the things we need to find out.
+ */
xe_phy_writereg(scp, PHY_BMCR, 0x0000);
XE_SELECT_PAGE(2);
- XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08); /* Disable PHY? */
- scp->autoneg_status = XE_AUTONEG_FAIL;
+ /* BEGIN HACK */
+ XE_OUTB(XE_MSR, XE_INB(XE_MSR) | 0x08);
+ XE_SELECT_PAGE(0x42);
+ XE_OUTB(XE_SWC1, 0x80);
+ scp->media = IFM_ETHER|IFM_10_T;
+ scp->autoneg_status = XE_AUTONEG_NONE;
+ /* END HACK */
+ /*XE_OUTB(XE_MSR, XE_INB(XE_MSR) & ~0x08);*/ /* Disable PHY? */
+ /*scp->autoneg_status = XE_AUTONEG_FAIL;*/
}
}
else {
@@ -1558,7 +1580,10 @@ xe_soft_reset(struct xe_softc *scp) {
scp->srev = (XE_INB(XE_BOV) & 0x70) >> 4;
else
scp->srev = (XE_INB(XE_BOV) & 0x30) >> 4;
-
+#ifdef XE_DEBUG
+ printf("xe%d: silicon revision = %d\n", scp->unit, scp->srev);
+#endif
+
/*
* Shut off interrupts.
*/
@@ -1692,10 +1717,12 @@ xe_setmulti(struct xe_softc *scp) {
* Program the filters for up to 9 addresses
*/
XE_SELECT_PAGE(0x42);
- XE_OUTB(XE_SWC1, 0);
+ XE_OUTB(XE_SWC1, 0x01);
XE_SELECT_PAGE(0x40);
XE_OUTB(XE_OCR, XE_OCR_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);
}
@@ -1714,9 +1741,11 @@ xe_setmulti(struct xe_softc *scp) {
* Set up all on-chip addresses (for multicast). AFAICS, there are 10
* of these things; the first is our MAC address, the other 9 are mcast
* addresses, padded with the MAC address if there aren't enough.
- * XXX - I think the Linux code gets this wrong and only writes one byte for
- * XXX - each address. I *think* this code does it right, but it needs more
- * XXX - intensive testing to be sure.
+ * 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) {
@@ -1742,6 +1771,12 @@ xe_setaddrs(struct xe_softc *scp) {
}
for (i = 0; i < 6; i++, byte++) {
+#ifdef XE_DEBUG
+ if (i)
+ printf(":%x", addr[i]);
+ else
+ printf("xe%d: individual addresses %d: %x", scp->unit, slot, addr[0]);
+#endif
if (byte > 15) {
page++;
@@ -1754,7 +1789,11 @@ xe_setaddrs(struct xe_softc *scp) {
else
XE_OUTB(byte, addr[i]);
}
+#ifdef XE_DEBUG
+ printf("\n");
+#endif
}
+
XE_SELECT_PAGE(0);
}
@@ -2131,10 +2170,16 @@ xe_phy_writereg(struct xe_softc *scp, u_int16_t reg, u_int16_t data) {
#ifdef XE_DEBUG
+/*
+ * A bit of debugging code.
+ */
static void
xe_mii_dump(struct xe_softc *scp) {
- int i, unit = scp->dev->id_unit;
+ int i, s;
+ s = splimp();
+
+ printf("xe%d: MII registers: ", scp->unit);
for (i = 0; i < 2; i++) {
printf(" %d:%04x", i, xe_phy_readreg(scp, i));
}
@@ -2142,21 +2187,24 @@ xe_mii_dump(struct xe_softc *scp) {
printf(" %d:%04x", i, xe_phy_readreg(scp, i));
}
printf("\n");
+
+ (void)splx(s);
}
static void
xe_reg_dump(struct xe_softc *scp) {
- int unit = scp->dev->id_unit;
- int page, i;
+ int page, i, s;
- printf("xe%d: Common registers: ", unit);
+ s = splimp();
+
+ printf("xe%d: Common registers: ", scp->unit);
for (i = 0; i < 8; i++) {
printf(" %2.2x", XE_INB(i));
}
printf("\n");
- for (page = 0; page < 8; page++) {
- printf("xe%d: Register page %2.2x: ", unit, page);
+ for (page = 0; page <= 8; page++) {
+ printf("xe%d: Register page %2.2x: ", scp->unit, page);
XE_SELECT_PAGE(page);
for (i = 8; i < 16; i++) {
printf(" %2.2x", XE_INB(i));
@@ -2164,16 +2212,21 @@ xe_reg_dump(struct xe_softc *scp) {
printf("\n");
}
- for (page = 0x40; page < 0x5f; page++) {
- if (page==0x43 || (page>=0x46 && page<=0x4f) || (page>=0x51 && page<=0x5e))
+ for (page = 0x10; page < 0x5f; page++) {
+ if ((page >= 0x11 && page <= 0x3f) ||
+ (page == 0x41) ||
+ (page >= 0x43 && page <= 0x4f) ||
+ (page >= 0x59))
continue;
- printf("xe%d: Register page %2.2x: ", unit, page);
+ printf("xe%d: Register page %2.2x: ", scp->unit, page);
XE_SELECT_PAGE(page);
for (i = 8; i < 16; i++) {
printf(" %2.2x", XE_INB(i));
}
printf("\n");
}
+
+ (void)splx(s);
}
#endif
OpenPOWER on IntegriCloud