|
@@ -49,7 +49,6 @@
|
|
|
|
|
|
#include "etherif.h"
|
|
#include "etherif.h"
|
|
|
|
|
|
-#define coherence()
|
|
|
|
#define XCVRDEBUG if(0)print
|
|
#define XCVRDEBUG if(0)print
|
|
|
|
|
|
enum {
|
|
enum {
|
|
@@ -165,13 +164,12 @@ enum { /* Window 0 - setup */
|
|
coaxAvailable9 = 0x1000,
|
|
coaxAvailable9 = 0x1000,
|
|
auiAvailable9 = 0x2000,
|
|
auiAvailable9 = 0x2000,
|
|
/* EepromCommand bits */
|
|
/* EepromCommand bits */
|
|
- _EepromReadRegister = 0x0080,
|
|
|
|
- _EepromRead8bRegister = 0x0230,
|
|
|
|
|
|
+ EepromReadRegister = 0x0080,
|
|
|
|
+ EepromReadOffRegister = 0x00B0,
|
|
|
|
+ EepromRead8bRegister = 0x0230,
|
|
EepromBusy = 0x8000,
|
|
EepromBusy = 0x8000,
|
|
};
|
|
};
|
|
|
|
|
|
-static int EepromReadRegister = _EepromReadRegister;
|
|
|
|
-
|
|
|
|
#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
|
|
#define EEPROMCMD(port, cmd, a) outs((port)+EepromCommand, (cmd)|(a))
|
|
#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
|
|
#define EEPROMBUSY(port) (ins((port)+EepromCommand) & EepromBusy)
|
|
#define EEPROMDATA(port) ins((port)+EepromData)
|
|
#define EEPROMDATA(port) ins((port)+EepromData)
|
|
@@ -385,8 +383,8 @@ enum { /* 3C90x extended register set */
|
|
|
|
|
|
updnLastFrag = 0x80000000, /* (dpd->len) */
|
|
updnLastFrag = 0x80000000, /* (dpd->len) */
|
|
|
|
|
|
- Nup = 32,
|
|
|
|
- Ndn = 64,
|
|
|
|
|
|
+ Nup = 16,
|
|
|
|
+ Ndn = 8,
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -402,10 +400,18 @@ typedef struct Pd {
|
|
ulong len;
|
|
ulong len;
|
|
|
|
|
|
Pd* next;
|
|
Pd* next;
|
|
- void *vaddr;
|
|
|
|
|
|
+ void* vaddr;
|
|
} Pd;
|
|
} Pd;
|
|
|
|
|
|
-typedef struct {
|
|
|
|
|
|
+typedef struct Ctlr Ctlr;
|
|
|
|
+struct Ctlr {
|
|
|
|
+ int port;
|
|
|
|
+ Pcidev* pcidev;
|
|
|
|
+ int irq;
|
|
|
|
+ Ctlr* next;
|
|
|
|
+ int active;
|
|
|
|
+ int did;
|
|
|
|
+
|
|
Lock wlock; /* window access */
|
|
Lock wlock; /* window access */
|
|
|
|
|
|
int attached;
|
|
int attached;
|
|
@@ -443,12 +449,19 @@ typedef struct {
|
|
ulong dnqueued;
|
|
ulong dnqueued;
|
|
|
|
|
|
int xcvr; /* transceiver type */
|
|
int xcvr; /* transceiver type */
|
|
|
|
+ int eepromcmd; /* EEPROM read command */
|
|
int rxstatus9; /* old-style RxStatus register */
|
|
int rxstatus9; /* old-style RxStatus register */
|
|
int rxearly; /* RxEarlyThreshold */
|
|
int rxearly; /* RxEarlyThreshold */
|
|
int ts; /* threshold shift */
|
|
int ts; /* threshold shift */
|
|
int upenabled;
|
|
int upenabled;
|
|
int dnenabled;
|
|
int dnenabled;
|
|
-} Ctlr;
|
|
|
|
|
|
+
|
|
|
|
+ ulong cbfnpa; /* CardBus functions */
|
|
|
|
+ ulong* cbfn;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static Ctlr* ctlrhead;
|
|
|
|
+static Ctlr* ctlrtail;
|
|
|
|
|
|
static void
|
|
static void
|
|
init905(Ctlr* ctlr)
|
|
init905(Ctlr* ctlr)
|
|
@@ -542,9 +555,9 @@ startdma(Ether* ether, ulong address)
|
|
|
|
|
|
/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
|
|
/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
|
|
static void
|
|
static void
|
|
-intrack3c575(ulong *cbfns)
|
|
|
|
|
|
+intrackcb(ulong *cbfn)
|
|
{
|
|
{
|
|
- cbfns[1] = 0x8000;
|
|
|
|
|
|
+ cbfn[1] = 0x8000;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -562,7 +575,7 @@ attach(Ether* ether)
|
|
|
|
|
|
port = ether->port;
|
|
port = ether->port;
|
|
|
|
|
|
- COMMAND(port, SetRxFilter, receiveIndividual|receiveBroadcast);
|
|
|
|
|
|
+ COMMAND(port, SetRxFilter, receiveIndividual/*|receiveBroadcast*/);
|
|
x = interruptMask;
|
|
x = interruptMask;
|
|
if(ctlr->busmaster == 1)
|
|
if(ctlr->busmaster == 1)
|
|
x &= ~(rxEarly|rxComplete);
|
|
x &= ~(rxEarly|rxComplete);
|
|
@@ -577,9 +590,11 @@ attach(Ether* ether)
|
|
COMMAND(port, RxEnable, 0);
|
|
COMMAND(port, RxEnable, 0);
|
|
COMMAND(port, TxEnable, 0);
|
|
COMMAND(port, TxEnable, 0);
|
|
|
|
|
|
- if (ether->mem)
|
|
|
|
- /* This must be a cardbus card. Acknowledge the interrupt */
|
|
|
|
- intrack3c575(KADDR(ether->mem));
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If this is a CardBus card, acknowledge any interrupts.
|
|
|
|
+ */
|
|
|
|
+ if(ctlr->cbfn != nil)
|
|
|
|
+ intrackcb(ctlr->cbfn);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Prime the busmaster channel for receiving directly into a
|
|
* Prime the busmaster channel for receiving directly into a
|
|
@@ -1029,8 +1044,8 @@ interrupt(Ureg*, void* arg)
|
|
panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
|
|
panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
|
|
|
|
|
|
COMMAND(port, AcknowledgeInterrupt, interruptLatch);
|
|
COMMAND(port, AcknowledgeInterrupt, interruptLatch);
|
|
- if (ether->mem)
|
|
|
|
- intrack3c575((ulong *)KADDR(ether->mem));
|
|
|
|
|
|
+ if(ctlr->cbfn != nil)
|
|
|
|
+ intrackcb(ctlr->cbfn);
|
|
|
|
|
|
}while((status = STATUS(port)) & (interruptMask|interruptLatch));
|
|
}while((status = STATUS(port)) & (interruptMask|interruptLatch));
|
|
|
|
|
|
@@ -1046,7 +1061,6 @@ interrupt(Ureg*, void* arg)
|
|
static void
|
|
static void
|
|
txrxreset(int port)
|
|
txrxreset(int port)
|
|
{
|
|
{
|
|
- COMMAND(port, TxReset, 0);
|
|
|
|
while(STATUS(port) & commandInProgress)
|
|
while(STATUS(port) & commandInProgress)
|
|
;
|
|
;
|
|
COMMAND(port, RxReset, 0);
|
|
COMMAND(port, RxReset, 0);
|
|
@@ -1054,29 +1068,24 @@ txrxreset(int port)
|
|
;
|
|
;
|
|
}
|
|
}
|
|
|
|
|
|
-typedef struct Adapter {
|
|
|
|
- int port;
|
|
|
|
- int irq;
|
|
|
|
- int tbdf;
|
|
|
|
- ulong cbfns;
|
|
|
|
-} Adapter;
|
|
|
|
-static Block* adapter;
|
|
|
|
-
|
|
|
|
-static void
|
|
|
|
-tcmadapter(int port, int irq, int tbdf, ulong cbfns)
|
|
|
|
|
|
+static Ctlr*
|
|
|
|
+tcmadapter(int port, int irq, Pcidev* pcidev)
|
|
{
|
|
{
|
|
- Block *bp;
|
|
|
|
- Adapter *ap;
|
|
|
|
|
|
+ Ctlr *ctlr;
|
|
|
|
+
|
|
|
|
+ ctlr = malloc(sizeof(Ctlr));
|
|
|
|
+ ctlr->port = port;
|
|
|
|
+ ctlr->irq = irq;
|
|
|
|
+ ctlr->pcidev = pcidev;
|
|
|
|
+ ctlr->eepromcmd = EepromReadRegister;
|
|
|
|
|
|
- bp = allocb(sizeof(Adapter));
|
|
|
|
- ap = (Adapter*)bp->rp;
|
|
|
|
- ap->port = port;
|
|
|
|
- ap->irq = irq;
|
|
|
|
- ap->tbdf = tbdf;
|
|
|
|
- ap->cbfns = cbfns;
|
|
|
|
|
|
+ if(ctlrhead != nil)
|
|
|
|
+ ctlrtail->next = ctlr;
|
|
|
|
+ else
|
|
|
|
+ ctlrhead = ctlr;
|
|
|
|
+ ctlrtail = ctlr;
|
|
|
|
|
|
- bp->next = adapter;
|
|
|
|
- adapter = bp;
|
|
|
|
|
|
+ return ctlr;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1216,7 +1225,7 @@ tcm509isa(void)
|
|
COMMAND(port, AcknowledgeInterrupt, 0xFF);
|
|
COMMAND(port, AcknowledgeInterrupt, 0xFF);
|
|
|
|
|
|
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
|
|
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
|
|
- tcmadapter(port, irq, BUSUNKNOWN, 0);
|
|
|
|
|
|
+ tcmadapter(port, irq, nil);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1254,29 +1263,21 @@ tcm5XXeisa(void)
|
|
COMMAND(port, AcknowledgeInterrupt, 0xFF);
|
|
COMMAND(port, AcknowledgeInterrupt, 0xFF);
|
|
|
|
|
|
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
|
|
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
|
|
- tcmadapter(port, irq, BUSUNKNOWN, 0);
|
|
|
|
|
|
+ tcmadapter(port, irq, nil);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
-tcm59Xpci(Ether *ether)
|
|
|
|
|
|
+tcm59Xpci(void)
|
|
{
|
|
{
|
|
Pcidev *p;
|
|
Pcidev *p;
|
|
|
|
+ Ctlr *ctlr;
|
|
int irq, port;
|
|
int irq, port;
|
|
- ulong bar;
|
|
|
|
|
|
|
|
p = nil;
|
|
p = nil;
|
|
while(p = pcimatch(p, 0x10B7, 0)){
|
|
while(p = pcimatch(p, 0x10B7, 0)){
|
|
- if (p->did == 0x5157) {
|
|
|
|
- EepromReadRegister = _EepromRead8bRegister;
|
|
|
|
-
|
|
|
|
- /* Map the CardBus functions */
|
|
|
|
- bar = pcicfgr32(p, PciBAR2);
|
|
|
|
- print("ether#%d: CardBus functions at %.8luX\n", ether->ctlrno, bar & ~KZERO);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- bar = 0;
|
|
|
|
-
|
|
|
|
|
|
+ if(p->ccrb != 0x02 || p->ccru != 0)
|
|
|
|
+ continue;
|
|
/*
|
|
/*
|
|
* Not prepared to deal with memory-mapped
|
|
* Not prepared to deal with memory-mapped
|
|
* devices yet.
|
|
* devices yet.
|
|
@@ -1285,11 +1286,25 @@ tcm59Xpci(Ether *ether)
|
|
continue;
|
|
continue;
|
|
port = p->mem[0].bar & ~0x01;
|
|
port = p->mem[0].bar & ~0x01;
|
|
irq = p->intl;
|
|
irq = p->intl;
|
|
- COMMAND(port, GlobalReset, 0);
|
|
|
|
- while(STATUS(port) & commandInProgress)
|
|
|
|
- ;
|
|
|
|
|
|
|
|
- tcmadapter(port, irq, p->tbdf, bar);
|
|
|
|
|
|
+ txrxreset(port);
|
|
|
|
+ COMMAND(port, AcknowledgeInterrupt, 0xFF);
|
|
|
|
+
|
|
|
|
+ ctlr = tcmadapter(port, irq, p);
|
|
|
|
+ switch(p->did){
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ case 0x5157:
|
|
|
|
+ ctlr->eepromcmd = EepromRead8bRegister;
|
|
|
|
+ ctlr->cbfnpa = p->mem[2].bar&~0x0F;
|
|
|
|
+ ctlr->cbfn = KADDR(ctlr->cbfnpa);
|
|
|
|
+ break;
|
|
|
|
+ case 0x6056:
|
|
|
|
+ ctlr->eepromcmd = EepromReadOffRegister;
|
|
|
|
+ ctlr->cbfnpa = p->mem[2].bar&~0x0F;
|
|
|
|
+ ctlr->cbfn = KADDR(ctlr->cbfnpa);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
pcisetbme(p);
|
|
pcisetbme(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1301,32 +1316,33 @@ static char* tcmpcmcia[] = {
|
|
nil,
|
|
nil,
|
|
};
|
|
};
|
|
|
|
|
|
-static int
|
|
|
|
|
|
+static Ctlr*
|
|
tcm5XXpcmcia(Ether* ether)
|
|
tcm5XXpcmcia(Ether* ether)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
+ Ctlr *ctlr;
|
|
|
|
+
|
|
|
|
+ if(ether->type == nil)
|
|
|
|
+ return nil;
|
|
|
|
|
|
for(i = 0; tcmpcmcia[i] != nil; i++){
|
|
for(i = 0; tcmpcmcia[i] != nil; i++){
|
|
- if(!cistrcmp(ether->type, tcmpcmcia[i])){
|
|
|
|
- /*
|
|
|
|
- * No need for an ioalloc here, the 589 reset
|
|
|
|
- * code deals with it.
|
|
|
|
- if(ioalloc(ether->port, 0x10, 0, "tcm5XXpcmcia") < 0)
|
|
|
|
- return 0;
|
|
|
|
- */
|
|
|
|
- return ether->port;
|
|
|
|
- }
|
|
|
|
|
|
+ if(cistrcmp(ether->type, tcmpcmcia[i]))
|
|
|
|
+ continue;
|
|
|
|
+ ctlr = tcmadapter(ether->port, ether->irq, nil);
|
|
|
|
+ ctlr->active = 1;
|
|
|
|
+ return ctlr;
|
|
}
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return nil;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
-setxcvr(int port, int xcvr, int is9)
|
|
|
|
|
|
+setxcvr(Ctlr* ctlr, int xcvr)
|
|
{
|
|
{
|
|
- int x;
|
|
|
|
|
|
+ int port, x;
|
|
|
|
|
|
- if(is9){
|
|
|
|
|
|
+ port = ctlr->port;
|
|
|
|
+ if(ctlr->rxstatus9){
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
x = ins(port+AddressConfig) & ~xcvrMask9;
|
|
x = ins(port+AddressConfig) & ~xcvrMask9;
|
|
x |= (xcvr>>20)<<14;
|
|
x |= (xcvr>>20)<<14;
|
|
@@ -1425,7 +1441,7 @@ miir(int port, int phyad, int regad)
|
|
return data & 0xFFFF;
|
|
return data & 0xFFFF;
|
|
}
|
|
}
|
|
|
|
|
|
-static void
|
|
|
|
|
|
+static int
|
|
scanphy(int port)
|
|
scanphy(int port)
|
|
{
|
|
{
|
|
int i, x;
|
|
int i, x;
|
|
@@ -1437,7 +1453,10 @@ scanphy(int port)
|
|
x |= miir(port, i, 3)>>10;
|
|
x |= miir(port, i, 3)>>10;
|
|
XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
|
|
XCVRDEBUG("phy%d: oui %uX reg1 %uX\n", i, x, miir(port, i, 1));
|
|
USED(x);
|
|
USED(x);
|
|
|
|
+
|
|
|
|
+ return i;
|
|
}
|
|
}
|
|
|
|
+ return 24;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef notdef
|
|
#ifdef notdef
|
|
@@ -1470,10 +1489,9 @@ static struct {
|
|
};
|
|
};
|
|
|
|
|
|
static int
|
|
static int
|
|
-autoselect(int port, int xcvr, int is9)
|
|
|
|
|
|
+autoselect(Ctlr* ctlr)
|
|
{
|
|
{
|
|
- int media, x;
|
|
|
|
- USED(xcvr);
|
|
|
|
|
|
+ int media, port, x;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Pathetic attempt at automatic media selection.
|
|
* Pathetic attempt at automatic media selection.
|
|
@@ -1481,7 +1499,8 @@ autoselect(int port, int xcvr, int is9)
|
|
* cards operational.
|
|
* cards operational.
|
|
* It's a bonus if it works for anything else.
|
|
* It's a bonus if it works for anything else.
|
|
*/
|
|
*/
|
|
- if(is9){
|
|
|
|
|
|
+ port = ctlr->port;
|
|
|
|
+ if(ctlr->rxstatus9){
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
x = ins(port+ConfigControl);
|
|
x = ins(port+ConfigControl);
|
|
media = 0;
|
|
media = 0;
|
|
@@ -1508,7 +1527,7 @@ autoselect(int port, int xcvr, int is9)
|
|
/*
|
|
/*
|
|
* Must have InternalConfig register.
|
|
* Must have InternalConfig register.
|
|
*/
|
|
*/
|
|
- setxcvr(port, xcvr100BaseTX, is9);
|
|
|
|
|
|
+ setxcvr(ctlr, xcvr100BaseTX);
|
|
|
|
|
|
COMMAND(port, SelectRegisterWindow, Wdiagnostic);
|
|
COMMAND(port, SelectRegisterWindow, Wdiagnostic);
|
|
x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
|
|
x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
|
|
@@ -1521,7 +1540,7 @@ autoselect(int port, int xcvr, int is9)
|
|
}
|
|
}
|
|
|
|
|
|
if(media & base10TAvailable){
|
|
if(media & base10TAvailable){
|
|
- setxcvr(port, xcvr10BaseT, is9);
|
|
|
|
|
|
+ setxcvr(ctlr, xcvr10BaseT);
|
|
|
|
|
|
COMMAND(port, SelectRegisterWindow, Wdiagnostic);
|
|
COMMAND(port, SelectRegisterWindow, Wdiagnostic);
|
|
x = ins(port+MediaStatus) & ~dcConverterEnabled;
|
|
x = ins(port+MediaStatus) & ~dcConverterEnabled;
|
|
@@ -1541,35 +1560,60 @@ autoselect(int port, int xcvr, int is9)
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
static int
|
|
-eepromdata(int port, int offset)
|
|
|
|
|
|
+eepromdata(Ctlr* ctlr, int offset)
|
|
{
|
|
{
|
|
|
|
+ int port;
|
|
|
|
+
|
|
|
|
+ port = ctlr->port;
|
|
|
|
+
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
while(EEPROMBUSY(port))
|
|
while(EEPROMBUSY(port))
|
|
;
|
|
;
|
|
- EEPROMCMD(port, EepromReadRegister, offset);
|
|
|
|
|
|
+ EEPROMCMD(port, ctlr->eepromcmd, offset);
|
|
while(EEPROMBUSY(port))
|
|
while(EEPROMBUSY(port))
|
|
;
|
|
;
|
|
return EEPROMDATA(port);
|
|
return EEPROMDATA(port);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+resetctlr(Ctlr *ctlr)
|
|
|
|
+{
|
|
|
|
+ int port, x;
|
|
|
|
+
|
|
|
|
+ port = ctlr->port;
|
|
|
|
+
|
|
|
|
+ txrxreset(port);
|
|
|
|
+ x = ins(port+ResetOp905B);
|
|
|
|
+ XCVRDEBUG("905[BC] reset ops 0x%uX\n", x);
|
|
|
|
+ x &= ~0x4010;
|
|
|
|
+ if(ctlr->did == 0x5157){
|
|
|
|
+ x |= 0x0010; /* Invert LED */
|
|
|
|
+ outs(port+ResetOp905B, x);
|
|
|
|
+ }
|
|
|
|
+ if(ctlr->did == 0x6056){
|
|
|
|
+ x |= 0x4000;
|
|
|
|
+ outs(port+ResetOp905B, x);
|
|
|
|
+
|
|
|
|
+ COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
|
|
+ outs(port, 0x0800);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int
|
|
int
|
|
elnk3reset(Ether* ether)
|
|
elnk3reset(Ether* ether)
|
|
{
|
|
{
|
|
- int anar, anlpar, phyaddr, phystat, timeo, xcvr;
|
|
|
|
- int busmaster, did, i, j, port, rxearly, rxstatus9, x;
|
|
|
|
- Block *bp, **bpp;
|
|
|
|
- Adapter *ap;
|
|
|
|
- uchar ea[Eaddrlen];
|
|
|
|
|
|
+ char *p;
|
|
Ctlr *ctlr;
|
|
Ctlr *ctlr;
|
|
|
|
+ uchar ea[Eaddrlen];
|
|
static int scandone;
|
|
static int scandone;
|
|
- char *p;
|
|
|
|
|
|
+ int anar, anlpar, i, j, phyaddr, phystat, port, timeo, x;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Scan for adapter on PCI, EISA and finally
|
|
* Scan for adapter on PCI, EISA and finally
|
|
* using the little ISA configuration dance.
|
|
* using the little ISA configuration dance.
|
|
*/
|
|
*/
|
|
if(scandone == 0){
|
|
if(scandone == 0){
|
|
- tcm59Xpci(ether);
|
|
|
|
|
|
+ tcm59Xpci();
|
|
tcm5XXeisa();
|
|
tcm5XXeisa();
|
|
tcm509isa();
|
|
tcm509isa();
|
|
scandone = 1;
|
|
scandone = 1;
|
|
@@ -1579,74 +1623,78 @@ elnk3reset(Ether* ether)
|
|
* Any adapter matches if no ether->port is supplied,
|
|
* Any adapter matches if no ether->port is supplied,
|
|
* otherwise the ports must match.
|
|
* otherwise the ports must match.
|
|
*/
|
|
*/
|
|
- port = 0;
|
|
|
|
- bpp = &adapter;
|
|
|
|
- for(bp = *bpp; bp; bp = bp->next){
|
|
|
|
- ap = (Adapter*)bp->rp;
|
|
|
|
- if(ether->port == 0 || ether->port == ap->port){
|
|
|
|
- port = ap->port;
|
|
|
|
- ether->irq = ap->irq;
|
|
|
|
- ether->tbdf = ap->tbdf;
|
|
|
|
- ether->mem = ap->cbfns; /* Misuse the mem ref for the cardbus functions */
|
|
|
|
- *bpp = bp->next;
|
|
|
|
- freeb(bp);
|
|
|
|
|
|
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
|
|
|
|
+ if(ctlr->active)
|
|
|
|
+ continue;
|
|
|
|
+ if(ether->port == 0 || ether->port == ctlr->port){
|
|
|
|
+ ctlr->active = 1;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- bpp = &bp->next;
|
|
|
|
}
|
|
}
|
|
- if(port == 0 && (port = tcm5XXpcmcia(ether)) == 0)
|
|
|
|
|
|
+ if(ctlr == nil && (ctlr = tcm5XXpcmcia(ether)) == 0)
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
|
|
+ ether->ctlr = ctlr;
|
|
|
|
+ port = ctlr->port;
|
|
|
|
+ ether->port = port;
|
|
|
|
+ ether->irq = ctlr->irq;
|
|
|
|
+ if(ctlr->pcidev != nil)
|
|
|
|
+ ether->tbdf = ctlr->pcidev->tbdf;
|
|
|
|
+ else
|
|
|
|
+ ether->tbdf = BUSUNKNOWN;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Read the DeviceID from the EEPROM, it's at offset 0x03,
|
|
* Read the DeviceID from the EEPROM, it's at offset 0x03,
|
|
* and do something depending on capabilities.
|
|
* and do something depending on capabilities.
|
|
*/
|
|
*/
|
|
- switch(did = eepromdata(port, 0x03)){
|
|
|
|
-
|
|
|
|
- case 0x9000:
|
|
|
|
- case 0x9001:
|
|
|
|
- case 0x9005:
|
|
|
|
- case 0x9050:
|
|
|
|
- case 0x9051:
|
|
|
|
- case 0x9055:
|
|
|
|
- case 0x4500: /* 3C450 HomePNA Tornado */
|
|
|
|
|
|
+ switch(ctlr->did = eepromdata(ctlr, 0x03)){
|
|
|
|
+ case 0x5157: /* 3C575 Cyclone */
|
|
case 0x6056:
|
|
case 0x6056:
|
|
- case 0x9200: /* 3C905C-TX */
|
|
|
|
|
|
+ /*FALLTHROUGH*/
|
|
|
|
+ case 0x4500: /* 3C450 HomePNA Tornado */
|
|
case 0x7646: /* 3CSOHO100-TX */
|
|
case 0x7646: /* 3CSOHO100-TX */
|
|
- case 0x5157: /* 3C575 Cyclone */
|
|
|
|
|
|
+ case 0x9055: /* 3C905B-TX */
|
|
|
|
+ case 0x9200: /* 3C905C-TX */
|
|
|
|
+ case 0x9201: /* 3C920 */
|
|
|
|
+ /*FALLTHROUGH*/
|
|
|
|
+ case 0x9000: /* 3C900-TPO */
|
|
|
|
+ case 0x9001: /* 3C900-COMBO */
|
|
|
|
+ case 0x9005: /* 3C900B-COMBO */
|
|
|
|
+ case 0x9050: /* 3C905-TX */
|
|
|
|
+ case 0x9051: /* 3C905-T4 */
|
|
if(BUSTYPE(ether->tbdf) != BusPCI)
|
|
if(BUSTYPE(ether->tbdf) != BusPCI)
|
|
goto buggery;
|
|
goto buggery;
|
|
- busmaster = 2;
|
|
|
|
|
|
+ ctlr->busmaster = 2;
|
|
goto vortex;
|
|
goto vortex;
|
|
-
|
|
|
|
- case 0x5900:
|
|
|
|
- case 0x5920:
|
|
|
|
- case 0x5950:
|
|
|
|
- case 0x5951:
|
|
|
|
- case 0x5952:
|
|
|
|
- case 0x5970:
|
|
|
|
- case 0x5971:
|
|
|
|
- case 0x5972:
|
|
|
|
- busmaster = 1;
|
|
|
|
|
|
+ case 0x5900: /* 3C590-[TP|COMBO|TPO] */
|
|
|
|
+ case 0x5920: /* 3C592-[TP|COMBO|TPO] */
|
|
|
|
+ case 0x5950: /* 3C595-TX */
|
|
|
|
+ case 0x5951: /* 3C595-T4 */
|
|
|
|
+ case 0x5952: /* 3C595-MII */
|
|
|
|
+ case 0x5970: /* 3C597-TX */
|
|
|
|
+ case 0x5971: /* 3C597-T4 */
|
|
|
|
+ case 0x5972: /* 3C597-MII */
|
|
|
|
+ ctlr->busmaster = 1;
|
|
vortex:
|
|
vortex:
|
|
COMMAND(port, SelectRegisterWindow, Wfifo);
|
|
COMMAND(port, SelectRegisterWindow, Wfifo);
|
|
- xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
|
|
|
|
- rxearly = 8188;
|
|
|
|
- rxstatus9 = 0;
|
|
|
|
|
|
+ ctlr->xcvr = inl(port+InternalConfig) & (autoSelect|xcvrMask);
|
|
|
|
+ ctlr->rxearly = 8188;
|
|
|
|
+ ctlr->rxstatus9 = 0;
|
|
break;
|
|
break;
|
|
-
|
|
|
|
buggery:
|
|
buggery:
|
|
default:
|
|
default:
|
|
- busmaster = 0;
|
|
|
|
|
|
+ ctlr->busmaster = 0;
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
COMMAND(port, SelectRegisterWindow, Wsetup);
|
|
x = ins(port+AddressConfig);
|
|
x = ins(port+AddressConfig);
|
|
- xcvr = ((x & xcvrMask9)>>14)<<20;
|
|
|
|
|
|
+ ctlr->xcvr = ((x & xcvrMask9)>>14)<<20;
|
|
if(x & autoSelect9)
|
|
if(x & autoSelect9)
|
|
- xcvr |= autoSelect;
|
|
|
|
- rxearly = 2044;
|
|
|
|
- rxstatus9 = 1;
|
|
|
|
|
|
+ ctlr->xcvr |= autoSelect;
|
|
|
|
+ ctlr->rxearly = 2044;
|
|
|
|
+ ctlr->rxstatus9 = 1;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ if(ctlr->rxearly >= 2048)
|
|
|
|
+ ctlr->ts = 2;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Check if the adapter's station address is to be overridden.
|
|
* Check if the adapter's station address is to be overridden.
|
|
@@ -1657,7 +1705,7 @@ elnk3reset(Ether* ether)
|
|
memset(ea, 0, Eaddrlen);
|
|
memset(ea, 0, Eaddrlen);
|
|
if(memcmp(ea, ether->ea, Eaddrlen) == 0){
|
|
if(memcmp(ea, ether->ea, Eaddrlen) == 0){
|
|
for(i = 0; i < Eaddrlen/2; i++){
|
|
for(i = 0; i < Eaddrlen/2; i++){
|
|
- x = eepromdata(port, i);
|
|
|
|
|
|
+ x = eepromdata(ctlr, i);
|
|
ether->ea[2*i] = x>>8;
|
|
ether->ea[2*i] = x>>8;
|
|
ether->ea[2*i+1] = x;
|
|
ether->ea[2*i+1] = x;
|
|
}
|
|
}
|
|
@@ -1672,7 +1720,7 @@ elnk3reset(Ether* ether)
|
|
* busmastering can be used. Due to bugs in the first revision
|
|
* busmastering can be used. Due to bugs in the first revision
|
|
* of the 3C59[05], don't use busmastering at 10Mbps.
|
|
* of the 3C59[05], don't use busmastering at 10Mbps.
|
|
*/
|
|
*/
|
|
- XCVRDEBUG("reset: xcvr %uX\n", xcvr);
|
|
|
|
|
|
+ XCVRDEBUG("reset: xcvr %uX\n", ctlr->xcvr);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Allow user to specify desired media in plan9.ini
|
|
* Allow user to specify desired media in plan9.ini
|
|
@@ -1683,38 +1731,41 @@ elnk3reset(Ether* ether)
|
|
p = ether->opt[i]+6;
|
|
p = ether->opt[i]+6;
|
|
for(j = 0; j < nelem(media); j++)
|
|
for(j = 0; j < nelem(media); j++)
|
|
if(cistrcmp(p, media[j].name) == 0)
|
|
if(cistrcmp(p, media[j].name) == 0)
|
|
- xcvr = media[j].xcvr;
|
|
|
|
|
|
+ ctlr->xcvr = media[j].xcvr;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
* forgive me, but i am weak
|
|
* forgive me, but i am weak
|
|
*/
|
|
*/
|
|
- if(did == 0x9055 || did == 0x7646 || did == 0x9200 || did == 0x5157){
|
|
|
|
- xcvr = xcvrMii;
|
|
|
|
- txrxreset(port);
|
|
|
|
- XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
|
|
|
|
-
|
|
|
|
- if (did == 0x5157) {
|
|
|
|
- ushort reset_opts;
|
|
|
|
-
|
|
|
|
- COMMAND(port, SelectRegisterWindow, Wstation);
|
|
|
|
- reset_opts = ins(port + ResetOp905B);
|
|
|
|
- reset_opts |= 0x0010; /* Invert LED */
|
|
|
|
- outs(port + ResetOp905B, reset_opts);
|
|
|
|
- }
|
|
|
|
|
|
+ switch(ctlr->did){
|
|
|
|
+ default:
|
|
|
|
+ if(ctlr->xcvr & autoSelect)
|
|
|
|
+ ctlr->xcvr = autoselect(ctlr);
|
|
|
|
+ break;
|
|
|
|
+ case 0x5157:
|
|
|
|
+ case 0x6056:
|
|
|
|
+ case 0x4500:
|
|
|
|
+ case 0x7646:
|
|
|
|
+ case 0x9055:
|
|
|
|
+ case 0x9200:
|
|
|
|
+ case 0x9201:
|
|
|
|
+ ctlr->xcvr = xcvrMii;
|
|
|
|
+ resetctlr(ctlr);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
- else if(xcvr & autoSelect)
|
|
|
|
- xcvr = autoselect(port, xcvr, rxstatus9);
|
|
|
|
- XCVRDEBUG("autoselect returns: xcvr %uX, did 0x%uX\n", xcvr, did);
|
|
|
|
-
|
|
|
|
- switch(xcvr){
|
|
|
|
|
|
+ XCVRDEBUG("xcvr selected: %uX, did 0x%uX\n", ctlr->xcvr, ctlr->did);
|
|
|
|
|
|
|
|
+ switch(ctlr->xcvr){
|
|
case xcvrMii:
|
|
case xcvrMii:
|
|
/*
|
|
/*
|
|
* Quick hack.
|
|
* Quick hack.
|
|
- scanphy(port);
|
|
|
|
*/
|
|
*/
|
|
- phyaddr = (did == 0x5157)? 0: 24;
|
|
|
|
|
|
+ if(ctlr->did == 0x5157)
|
|
|
|
+ phyaddr = 0;
|
|
|
|
+ else if(ctlr->did == 0x6056)
|
|
|
|
+ phyaddr = scanphy(port);
|
|
|
|
+ else
|
|
|
|
+ phyaddr = 24;
|
|
for(i = 0; i < 7; i++)
|
|
for(i = 0; i < 7; i++)
|
|
XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
|
|
XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
|
|
XCVRDEBUG("\n");
|
|
XCVRDEBUG("\n");
|
|
@@ -1746,13 +1797,14 @@ elnk3reset(Ether* ether)
|
|
}
|
|
}
|
|
XCVRDEBUG("mii anar: %uX\n", anar);
|
|
XCVRDEBUG("mii anar: %uX\n", anar);
|
|
if(anar & 0x0100){ /* 100BASE-TXFD */
|
|
if(anar & 0x0100){ /* 100BASE-TXFD */
|
|
|
|
+ //ether->mbps = 100;
|
|
setfullduplex(port);
|
|
setfullduplex(port);
|
|
}
|
|
}
|
|
else if(anar & 0x0200){ /* 100BASE-T4 */
|
|
else if(anar & 0x0200){ /* 100BASE-T4 */
|
|
/* nothing to do */
|
|
/* nothing to do */
|
|
}
|
|
}
|
|
else if(anar & 0x0080){ /* 100BASE-TX */
|
|
else if(anar & 0x0080){ /* 100BASE-TX */
|
|
- /* nothing to do */;
|
|
|
|
|
|
+ //ether->mbps = 100;
|
|
}
|
|
}
|
|
else if(anar & 0x0040) /* 10BASE-TFD */
|
|
else if(anar & 0x0040) /* 10BASE-TFD */
|
|
setfullduplex(port);
|
|
setfullduplex(port);
|
|
@@ -1771,6 +1823,9 @@ elnk3reset(Ether* ether)
|
|
x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
|
|
x = ins(port+MediaStatus) & ~(dcConverterEnabled|jabberGuardEnable);
|
|
x |= linkBeatEnable;
|
|
x |= linkBeatEnable;
|
|
outs(port+MediaStatus, x);
|
|
outs(port+MediaStatus, x);
|
|
|
|
+
|
|
|
|
+ //if(x & dataRate100)
|
|
|
|
+ // ether->mbps = 100;
|
|
break;
|
|
break;
|
|
|
|
|
|
case xcvr10BaseT:
|
|
case xcvr10BaseT:
|
|
@@ -1783,8 +1838,8 @@ elnk3reset(Ether* ether)
|
|
x |= linkBeatEnable|jabberGuardEnable;
|
|
x |= linkBeatEnable|jabberGuardEnable;
|
|
outs(port+MediaStatus, x);
|
|
outs(port+MediaStatus, x);
|
|
|
|
|
|
- if((did & 0xFF00) == 0x5900)
|
|
|
|
- busmaster = 0;
|
|
|
|
|
|
+ if((ctlr->did & 0xFF00) == 0x5900)
|
|
|
|
+ ctlr->busmaster = 0;
|
|
break;
|
|
break;
|
|
|
|
|
|
case xcvr10Base2:
|
|
case xcvr10Base2:
|
|
@@ -1809,7 +1864,7 @@ elnk3reset(Ether* ether)
|
|
* Clear out any lingering Tx status.
|
|
* Clear out any lingering Tx status.
|
|
*/
|
|
*/
|
|
COMMAND(port, SelectRegisterWindow, Wop);
|
|
COMMAND(port, SelectRegisterWindow, Wop);
|
|
- if(busmaster == 2)
|
|
|
|
|
|
+ if(ctlr->busmaster == 2)
|
|
x = port+TxStatus905;
|
|
x = port+TxStatus905;
|
|
else
|
|
else
|
|
x = port+TxStatus;
|
|
x = port+TxStatus;
|
|
@@ -1817,27 +1872,14 @@ elnk3reset(Ether* ether)
|
|
outb(x, 0);
|
|
outb(x, 0);
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Allocate a controller structure, clear out the
|
|
|
|
- * adapter statistics, clear the statistics logged into ctlr
|
|
|
|
- * and enable statistics collection. Xcvr is needed in order
|
|
|
|
- * to collect the BadSSD statistics.
|
|
|
|
|
|
+ * Clear out the
|
|
|
|
+ * adapter statistics, clear the statistics logged into ctlr.
|
|
*/
|
|
*/
|
|
- ether->ctlr = malloc(sizeof(Ctlr));
|
|
|
|
- ctlr = ether->ctlr;
|
|
|
|
-
|
|
|
|
ilock(&ctlr->wlock);
|
|
ilock(&ctlr->wlock);
|
|
- ctlr->xcvr = xcvr;
|
|
|
|
statistics(ether);
|
|
statistics(ether);
|
|
memset(ctlr->stats, 0, sizeof(ctlr->stats));
|
|
memset(ctlr->stats, 0, sizeof(ctlr->stats));
|
|
|
|
|
|
- ctlr->busmaster = busmaster;
|
|
|
|
- ctlr->xcvr = xcvr;
|
|
|
|
- ctlr->rxstatus9 = rxstatus9;
|
|
|
|
- ctlr->rxearly = rxearly;
|
|
|
|
- if(rxearly >= 2048)
|
|
|
|
- ctlr->ts = 2;
|
|
|
|
-
|
|
|
|
- COMMAND(port, StatisticsEnable, 0);
|
|
|
|
|
|
+ //COMMAND(port, StatisticsEnable, 0);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Allocate any receive buffers.
|
|
* Allocate any receive buffers.
|
|
@@ -1855,7 +1897,7 @@ elnk3reset(Ether* ether)
|
|
* until the whole packet has been received.
|
|
* until the whole packet has been received.
|
|
*/
|
|
*/
|
|
ctlr->upenabled = 1;
|
|
ctlr->upenabled = 1;
|
|
- x = eepromdata(port, 0x0F);
|
|
|
|
|
|
+ x = eepromdata(ctlr, 0x0F);
|
|
if(!(x & 0x01))
|
|
if(!(x & 0x01))
|
|
outl(port+PktStatus, upRxEarlyEnable);
|
|
outl(port+PktStatus, upRxEarlyEnable);
|
|
|
|
|
|
@@ -1872,14 +1914,13 @@ elnk3reset(Ether* ether)
|
|
*/
|
|
*/
|
|
ctlr->txthreshold = ETHERMAXTU/2;
|
|
ctlr->txthreshold = ETHERMAXTU/2;
|
|
COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
|
|
COMMAND(port, SetTxStartThresh, ctlr->txthreshold>>ctlr->ts);
|
|
- COMMAND(port, SetRxEarlyThresh, rxearly>>ctlr->ts);
|
|
|
|
|
|
+ COMMAND(port, SetRxEarlyThresh, ctlr->rxearly>>ctlr->ts);
|
|
|
|
|
|
iunlock(&ctlr->wlock);
|
|
iunlock(&ctlr->wlock);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Linkage to the generic ethernet driver.
|
|
* Linkage to the generic ethernet driver.
|
|
*/
|
|
*/
|
|
- ether->port = port;
|
|
|
|
ether->attach = attach;
|
|
ether->attach = attach;
|
|
ether->transmit = transmit;
|
|
ether->transmit = transmit;
|
|
ether->interrupt = interrupt;
|
|
ether->interrupt = interrupt;
|