## diffname pc/ether509.c 1992/0922
## diff -e /dev/null /n/bootesdump/1992/0922/sys/src/9/pc/ether509.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"
#define NEXT(x, l) (((x)+1)%(l))
#define OFFSETOF(t, m) ((unsigned)&(((t*)0)->m))
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
enum {
Nrb = 16, /* software receive buffers */
Ntb = 4, /* software transmit buffers */
};
enum {
IDport = 0x0100, /* anywhere between 0x0100 and 0x01F0 */
/* Commands */
SelectWindow = 0x01, /* SelectWindow command */
StartCoax = 0x02, /* Start Coaxial Transceiver */
RxDisable = 0x03, /* RX Disable */
RxEnable = 0x04, /* RX Enable */
RxDiscard = 0x08, /* RX Discard Top Packet */
TxEnable = 0x09, /* TX Enable */
TxDisable = 0x0A, /* TX Disable */
AckIntr = 0x0D, /* Acknowledge Interrupt */
SetIntrMask = 0x0E, /* Set Interrupt Mask */
SetReadZeroMask = 0x0F, /* Set Read Zero Mask */
SetRxFilter = 0x10, /* Set RX Filter */
SetTxAvailable = 0x12, /* Set TX Available Threshold */
/* RX Filter Command Bits */
MyEtherAddr = 0x01, /* Individual address */
Multicast = 0x02, /* Group (multicast) addresses */
Broadcast = 0x04, /* Broadcast address */
Promiscuous = 0x08, /* All addresses (promiscuous mode */
/* Window Register Offsets */
Command = 0x0E, /* all windows */
Status = 0x0E,
EEPROMdata = 0x0C, /* window 0 */
EEPROMcmd = 0x0A,
ResourceConfig = 0x08,
ConfigControl = 0x04,
TxFreeBytes = 0x0C, /* window 1 */
TxStatus = 0x0B,
RxStatus = 0x08,
Fifo = 0x00,
/* Status/Interrupt Bits */
Latch = 0x0001, /* Interrupt Latch */
TxComplete = 0x0004, /* TX Complete */
TxAvailable = 0x0008, /* TX Available */
RxComplete = 0x0010, /* RX Complete */
AllIntr = 0x00FE, /* All Interrupt Bits */
CmdInProgress = 0x1000, /* Command In Progress */
/* RxStatus Bits */
RxByteMask = 0x07FF, /* RX Bytes (0-1514) */
RxErrMask = 0x3800, /* Type of Error: */
RxErrOverrun = 0x0000, /* Overrrun */
RxErrOversize = 0x0800, /* Oversize Packet (>1514) */
RxErrDribble = 0x1000, /* Dribble Bit(s) */
RxErrRunt = 0x1800, /* Runt Packet */
RxErrFraming = 0x2000, /* Alignment (Framing) */
RxErrCRC = 0x2800, /* CRC */
RxError = 0x4000, /* Error */
RxEmpty = 0x8000, /* Incomplete or FIFO empty */
};
#define COMMAND(hw, cmd, a) outs(hw->addr+Command, ((cmd)<<11)|(a))
/*
* get configuration parameters
*/
static int
reset(EtherCtlr *cp)
{
EtherHw *hw = cp->hw;
int i, ea;
ushort acr;
uchar al;
cp->rb = xspanalloc(sizeof(EtherBuf)*Nrb, BY2PG, 0);
cp->nrb = Nrb;
cp->tb = xspanalloc(sizeof(EtherBuf)*Ntb, BY2PG, 0);
cp->ntb = Ntb;
/*
* Do the little configuration dance. We only look
* at the first board that responds, if we ever have more
* than one we'll need to modify this sequence.
*
* 2. Write two 0 bytes then the ID sequence to the IDport.
*/
outb(IDport, 0);
outb(IDport, 0);
outb(IDport, 0xc0);
delay(100)
outb(IDport, 0);
outb(IDport, 0);
for(al = 0xFF, i = 0; i < 255; i++){
outb(IDport, al);
if(al & 0x80){
al <<= 1;
al ^= 0xCF;
}
else
al <<= 1;
}
/*
* 3. Read the Product ID from the EEPROM.
* This is done by writing the IDPort with 0x83 (0x80
* is the 'read EEPROM command, 0x03 is the offset of
* the Product ID field in the EEPROM).
* The data comes back 1 bit at a time.
* We seem to need a delay here between reading the bits.
*
* If the ID doesn't match the 3C509 ID code, the adapter
* probably isn't there, so barf.
*/
outb(IDport, 0x83);
for(acr = 0, i = 0; i < 16; i++){
delay(5);
acr <<= 1;
acr |= inb(IDport) & 0x01;
}
if((acr & 0xF0FF) != 0x9050)
return -1;
/*
* 3. Read the Address Configuration from the EEPROM.
* The Address Configuration field is at offset 0x08 in the EEPROM).
* 6. Activate the adapter by writing the Activate command
* (0xFF).
*/
outb(IDport, 0x88);
for(acr = 0, i = 0; i < 16; i++){
delay(20);
acr <<= 1;
acr |= inb(IDport) & 0x01;
}
outb(IDport, 0xFF);
/*
* 8. Now we can talk to the adapter's I/O base addresses.
* We get the I/O base address from the acr just read.
*
* Enable the adapter.
*/
hw->addr = (acr & 0x1F)*0x10 + 0x200;
outb(hw->addr+ConfigControl, 0x01);
/*
* Read the IRQ from the Resource Configuration Register
* and the ethernet address from the EEPROM.
* The EEPROM command is 8bits, the lower 6 bits being
* the address offset.
*/
hw->irq = (ins(hw->addr+ResourceConfig)>>12) & 0x0F;
for(ea = 0, i = 0; i < 3; i++, ea += 2){
while(ins(hw->addr+EEPROMcmd) & 0x8000)
;
outs(hw->addr+EEPROMcmd, (2<<6)|i);
while(ins(hw->addr+EEPROMcmd) & 0x8000)
;
acr = ins(hw->addr+EEPROMdata);
cp->ea[ea] = (acr>>8) & 0xFF;
cp->ea[ea+1] = acr & 0xFF;
}
/*
* Finished with window 0. Now set the ethernet address
* in window 2.
* Commands have the format 'CCCCCAAAAAAAAAAA' where C
* is a bit in the command and A is a bit in the argument.
*/
COMMAND(hw, SelectWindow, 2);
for(i = 0; i < 6; i++)
outb(hw->addr+i, cp->ea[i]);
/*
* Finished with window 2.
* Set window 1 for normal operation.
*/
COMMAND(hw, SelectWindow, 1);
/*
* If we have a 10BASE2 transceiver, start the DC-DC
* converter. Wait > 800 microseconds.
*/
if(((acr>>14) & 0x03) == 0x03){
COMMAND(hw, StartCoax, 0);
delay(1);
}
print("3C509 I/O addr %lux irq %d:", hw->addr, hw->irq);
for(i = 0; i < sizeof(cp->ea); i++)
print(" %2.2ux", cp->ea[i]);
print("\n");
return 0;
}
static void
mode(EtherCtlr *cp, int on)
{
EtherHw *hw = cp->hw;
qlock(cp);
if(on){
cp->prom++;
if(cp->prom == 1)
COMMAND(hw, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
}
else{
cp->prom--;
if(cp->prom == 0)
COMMAND(hw, SetRxFilter, Broadcast|MyEtherAddr);
}
qunlock(cp);
}
static void
online(EtherCtlr *cp, int on)
{
EtherHw *hw = cp->hw;
USED(on); /* BUG */
/*
* Set the receiver packet filter for our own and
* and broadcast addresses, set the interrupt masks
* for all interrupts, and enable the receiver and transmitter.
* The only interrupt we should see under normal conditions
* is the receiver interrupt. If the transmit FIFO fills up,
* we will also see TxAvailable interrupts.
*/
COMMAND(hw, SetRxFilter, Broadcast|MyEtherAddr);
COMMAND(hw, SetReadZeroMask, AllIntr|Latch);
COMMAND(hw, SetIntrMask, AllIntr|Latch);
COMMAND(hw, RxEnable, 0);
COMMAND(hw, TxEnable, 0);
}
static int
getdiag(EtherHw *hw)
{
int bytes;
COMMAND(hw, SelectWindow, 4);
bytes = ins(hw->addr+0x04);
COMMAND(hw, SelectWindow, 1);
return bytes & 0xFFFF;
}
static void
receive(EtherCtlr *cp)
{
EtherHw *hw = cp->hw;
ushort status;
EtherBuf *rb;
int len;
while(((status = ins(hw->addr+RxStatus)) & RxEmpty) == 0){
/*
* If we had an error, log it and continue
* without updating the ring.
*/
if(status & RxError){
print("error #%ux, #%ux\n", status, getdiag(hw));
switch(status & RxErrMask){
case RxErrOverrun: /* Overrrun */
cp->overflows++;
break;
case RxErrOversize: /* Oversize Packet (>1514) */
case RxErrRunt: /* Runt Packet */
cp->buffs++;
break;
case RxErrFraming: /* Alignment (Framing) */
cp->frames++;
break;
case RxErrCRC: /* CRC */
cp->crcs++;
break;
}
}
else {
/*
* We have a packet. Read it into the next
* free ring buffer, if any.
* The CRC is already stripped off.
*/
rb = &cp->rb[cp->ri];
if(rb->owner == Interface){
len = (status & RxByteMask);
rb->len = len;
/*
* Must read len bytes padded to a
* doubleword. We can pick them out 16-bits
* at a time (can try 32-bits at a time
* later).
insl(hw->addr+Fifo, rb->pkt, HOWMANY(len, 4));
*/
inss(hw->addr+Fifo, rb->pkt, HOWMANY(len, 2));
/*
* Update the ring.
*/
rb->owner = Host;
cp->ri = NEXT(cp->ri, cp->nrb);
}
}
/*
* Discard the packet as we're done with it.
* Wait for discard to complete.
*/
COMMAND(hw, RxDiscard, 0);
while(ins(hw->addr+Status) & CmdInProgress)
;
}
}
static void
transmit(EtherCtlr *cp)
{
EtherHw *hw = cp->hw;
EtherBuf *tb;
int s;
ushort len;
s = splhi();
for(tb = &cp->tb[cp->ti]; tb->owner == Interface; tb = &cp->tb[cp->ti]){
/*
* If there's no room in the FIFO for this packet,
* set up an interrupt for when space becomes available.
*/
if(tb->len > ins(hw->addr+TxFreeBytes)){
COMMAND(hw, SetTxAvailable, tb->len);
break;
}
/*
* There's room, copy the packet to the FIFO and free
* the buffer back to the host.
* Output packet muat be a multiple of 4 in length.
*/
len = ROUNDUP(tb->len, 4)/2;
outs(hw->addr+Fifo, tb->len);
outs(hw->addr+Fifo, 0);
outss(hw->addr+Fifo, tb->pkt, len);
tb->owner = Host;
cp->ti = NEXT(cp->ti, cp->ntb);
}
splx(s);
}
static void
interrupt(EtherCtlr *cp)
{
EtherHw *hw = cp->hw;
ushort status;
status = ins(hw->addr+Status);
if(status & RxComplete){
(*cp->hw->receive)(cp);
wakeup(&cp->rr);
status &= ~RxComplete;
}
if(status & TxComplete){
/*
* Needs work here.
*/
print("txstat %ux\n", inb(hw->addr+TxStatus));
}
if(status & TxAvailable){
(*cp->hw->transmit)(cp);
wakeup(&cp->tr);
status &= ~TxAvailable;
}
/*
* Panic if there are any interrupt bits on we haven't
* dealt with other than Latch.
*/
if(status & AllIntr)
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(hw));
/*
* Acknowledge the interrupt.
*/
COMMAND(hw, AckIntr, Latch);
}
EtherHw ether509 = {
reset,
0, /* init */
mode,
online,
receive,
transmit,
interrupt,
0, /* tweak */
0, /* I/O base address */
};
.
## diffname pc/ether509.c 1992/0923
## diff -e /n/bootesdump/1992/0922/sys/src/9/pc/ether509.c /n/bootesdump/1992/0923/sys/src/9/pc/ether509.c
175,177c
x = ins(hw->addr+EEPROMdata);
cp->ea[ea] = (x>>8) & 0xFF;
cp->ea[ea+1] = x & 0xFF;
.
136c
if((x & 0xF0FF) != 0x9050)
.
133,134c
x <<= 1;
x |= inb(IDport) & 0x01;
.
131c
for(x = 0, i = 0; i < 16; i++){
.
103,117c
idseq();
outb(IDport, 0xC1);
delay(2);
idseq();
.
101c
* 2. get to cammand state, reset, then return to command state
.
88,89c
ushort x, acr;
.
80a
* Write two 0 bytes to idnetify the IDport and them reset the
* ID sequence. Then send the ID sequenced to the card to get
* the card it into command state.
*/
void
idseq(void)
{
int i;
uchar al;
outb(IDport, 0);
outb(IDport, 0);
for(al = 0xFF, i = 0; i < 255; i++){
outb(IDport, al);
if(al & 0x80){
al <<= 1;
al ^= 0xCF;
}
else
al <<= 1;
}
}
/*
.
## diffname pc/ether509.c 1992/0924
## diff -e /n/bootesdump/1992/0923/sys/src/9/pc/ether509.c /n/bootesdump/1992/0924/sys/src/9/pc/ether509.c
408c
status &= ~(TxAvailable|TxComplete);
.
405c
if(status & (TxAvailable|TxComplete)){
.
402c
txstatus = 0;
while(ins(hw->addr+Status) & TxComplete){
txstatus |= inb(hw->addr+TxStatus);
outb(hw->addr+TxStatus, 0);
}
if(txstatus & (TxJabber|TxUnderrun))
COMMAND(hw, TxReset, 0);
COMMAND(hw, TxEnable, 0);
.
400c
* Pop the TX Status stack, accumulating errors.
* If there was a Jabber or Underrun error, reset
* the transmitter. For all conditions enable
* the transmitter.
.
388a
uchar txstatus;
.
64a
/* TxStatus Bits */
TxJabber = 0x20, /* Jabber Error */
TxUnderrun = 0x10, /* Underrun */
TxMaxColl = 0x08, /* Maximum Collisions */
.
30a
TxReset = 0x0B, /* TX Reset */
.
## diffname pc/ether509.c 1992/0925
## diff -e /n/bootesdump/1992/0924/sys/src/9/pc/ether509.c /n/bootesdump/1992/0925/sys/src/9/pc/ether509.c
419a
cp->oerrs++;
.
## diffname pc/ether509.c 1992/0926
## diff -e /n/bootesdump/1992/0925/sys/src/9/pc/ether509.c /n/bootesdump/1992/0926/sys/src/9/pc/ether509.c
378c
* Output packet must be a multiple of 4 in length.
.
## diffname pc/ether509.c 1992/1015
## diff -e /n/bootesdump/1992/0926/sys/src/9/pc/ether509.c /n/bootesdump/1992/1015/sys/src/9/pc/ether509.c
414,415c
x = inb(hw->addr+TxStatus);
if(x)
outb(hw->addr+TxStatus, 0);
txstatus |= x;
.
395c
uchar txstatus, x;
.
298d
## diffname pc/ether509.c 1992/1016
## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/ether509.c /n/bootesdump/1992/1016/sys/src/9/pc/ether509.c
424a
/*
* Reset the Tx FIFO threshold.
*/
if(status & TxAvailable)
COMMAND(hw, AckIntr, TxAvailable);
.
417c
}while(ins(hw->addr+Status) & TxComplete);
.
412,414c
do{
if(x = inb(hw->addr+TxStatus))
.
## diffname pc/ether509.c 1992/1102
## diff -e /n/bootesdump/1992/1016/sys/src/9/pc/ether509.c /n/bootesdump/1992/1102/sys/src/9/pc/ether509.c
87c
* Write two 0 bytes to identify the IDport and them reset the
.
## diffname pc/ether509.c 1992/1222
## diff -e /n/bootesdump/1992/1102/sys/src/9/pc/ether509.c /n/bootesdump/1992/1222/sys/src/9/pc/ether509.c
455,456c
0, /* watch */
.
451,452c
0, /* receive */
.
449c
0, /* init */
attach,
.
447c
Board ether509 = {
.
441,444c
COMMAND(board, AckIntr, Latch);
.
439c
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(board));
.
436a
* Otherwise, acknowledge the interrupt.
.
428,430c
COMMAND(board, AckIntr, TxAvailable);
transmit(ctlr);
wakeup(&ctlr->tr);
.
418,420c
COMMAND(board, TxReset, 0);
COMMAND(board, TxEnable, 0);
ctlr->oerrs++;
.
416c
}while(ins(board->io+Status) & TxComplete);
.
413,414c
if(x = inb(board->io+TxStatus))
outb(board->io+TxStatus, 0);
.
399,400c
receive(ctlr);
wakeup(&ctlr->rr);
.
396c
status = ins(board->io+Status);
.
392c
Board *board = ctlr->board;
.
390c
interrupt(Ctlr *ctlr)
.
384c
ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
.
380,382c
outs(board->io+Fifo, tb->len);
outs(board->io+Fifo, 0);
outss(board->io+Fifo, tb->pkt, len);
.
369,370c
if(tb->len > ins(board->io+TxFreeBytes)){
COMMAND(board, SetTxAvailable, tb->len);
.
363,364c
for(tb = &ctlr->tb[ctlr->ti]; tb->owner == Interface; tb = &ctlr->tb[ctlr->ti]){
.
357,358c
Board *board = ctlr->board;
RingBuf *tb;
.
355c
transmit(Ctlr *ctlr)
.
348,349c
COMMAND(board, RxDiscard, 0);
while(ins(board->io+Status) & CmdInProgress)
.
343a
.
341c
ctlr->ri = NEXT(ctlr->ri, ctlr->nrb);
.
335c
inss(board->io+Fifo, rb->pkt, HOWMANY(len, 2));
.
333c
insl(board->io+Fifo, rb->pkt, HOWMANY(len, 4));
.
323c
rb = &ctlr->rb[ctlr->ri];
.
313c
ctlr->crcs++;
.
309c
ctlr->frames++;
.
306c
ctlr->buffs++;
.
301c
ctlr->overflows++;
.
291,292c
while(((status = ins(board->io+RxStatus)) & RxEmpty) == 0){
.
288c
RingBuf *rb;
.
286c
Board *board = ctlr->board;
.
284c
receive(Ctlr *ctlr)
.
277,279c
COMMAND(board, SelectWindow, 4);
bytes = ins(board->io+0x04);
COMMAND(board, SelectWindow, 1);
.
273c
getdiag(Board *board)
.
271a
if(on)
COMMAND(board, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
else
COMMAND(board, SetRxFilter, Broadcast|MyEtherAddr);
}
.
270a
static void
mode(Ctlr *ctlr, int on)
{
Board *board = ctlr->board;
.
264,268c
COMMAND(board, SetRxFilter, Broadcast|MyEtherAddr);
COMMAND(board, SetReadZeroMask, AllIntr|Latch);
COMMAND(board, SetIntrMask, AllIntr|Latch);
COMMAND(board, RxEnable, 0);
COMMAND(board, TxEnable, 0);
.
236,255d
234c
Board *board = ctlr->board;
.
232c
attach(Ctlr *ctlr)
.
223,225c
print("3C509 I/O addr %lux irq %d:", board->io, board->irq);
for(i = 0; i < sizeof(ctlr->ea); i++)
print(" %2.2ux", ctlr->ea[i]);
.
219c
COMMAND(board, StartCoax, 0);
.
212c
COMMAND(board, SelectWindow, 1);
.
206c
outb(board->io+i, ctlr->ea[i]);
.
204c
COMMAND(board, SelectWindow, 2);
.
193,195c
x = ins(board->io+EEPROMdata);
ctlr->ea[ea] = (x>>8) & 0xFF;
ctlr->ea[ea+1] = x & 0xFF;
.
190,191c
outs(board->io+EEPROMcmd, (2<<6)|i);
while(ins(board->io+EEPROMcmd) & 0x8000)
.
188c
while(ins(board->io+EEPROMcmd) & 0x8000)
.
186c
board->irq = (ins(board->io+ResourceConfig)>>12) & 0x0F;
.
177,178c
board->io = (acr & 0x1F)*0x10 + 0x200;
outb(board->io+ConfigControl, 0x01);
.
130c
* 2. get to command state, reset, then return to command state
.
120,124d
116c
Board *board = ctlr->board;
.
114c
reset(Ctlr *ctlr)
.
111c
* Get configuration parameters.
.
91c
static void
.
87,89c
* Write two 0 bytes to identify the IDport and then reset the
* ID sequence. Then send the ID sequence to the card to get
* the card into command state.
.
84c
#define COMMAND(board, cmd, a) outs(board->io+Command, ((cmd)<<11)|(a))
.
16,20d
10,13c
#include "ether.h"
.
## diffname pc/ether509.c 1993/0123
## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/ether509.c /n/bootesdump/1993/0123/sys/src/9/pc/ether509.c
372a
if(status & Failure){
/*
* Adapter failure, try to find out why.
* Reset if necessary.
* What happens if Tx is active and we reset,
* need to retransmit?
* This probably isn't right.
*/
diag = getdiag(board);
print("ether509: status #%ux, diag #%ux\n", status, diag);
if(diag & TxOverrun){
COMMAND(board, TxReset, 0);
COMMAND(board, TxEnable, 0);
}
if(diag & RxUnderrun){
COMMAND(board, RxReset, 0);
attach(ctlr);
}
if(diag & TxOverrun)
transmit(ctlr);
return;
}
.
369c
ushort status, diag;
.
358c
outss(board->io+Fifo, tb->pkt, len/2);
.
355d
353d
345,346c
len = ROUNDUP(tb->len, 4);
if(len > ins(board->io+TxFreeBytes)+4){
COMMAND(board, SetTxAvailable, len);
.
343a
* Output packet must be a multiple of 4 in length and
* we need 4 bytes for the preamble.
.
255c
bytes = ins(board->io+FIFOdiag);
.
73a
FIFOdiag = 0x04, /* window 4 */
/* FIFOdiag bits */
TxOverrun = 0x0400, /* TX Overrrun */
RxOverrun = 0x0800, /* RX Overrun */
RxStatusOverrun = 0x1000, /* RX Status Overrun */
RxUnderrun = 0x2000, /* RX Underrun */
RxReceiving = 0x8000, /* RX Receiving */
.
51a
Failure = 0x0002, /* Adapter Failure */
.
19a
RxReset = 0x05, /* RX Reset */
.
## diffname pc/ether509.c 1993/0212
## diff -e /n/bootesdump/1993/0123/sys/src/9/pc/ether509.c /n/bootesdump/1993/0212/sys/src/9/pc/ether509.c
461,469c
Card ether509 = {
"3Com509", /* ident */
reset, /* reset */
0, /* init */
attach, /* attach */
mode, /* mode */
0, /* read */
0, /* write */
0, /* receive */
transmit, /* transmit */
interrupt, /* interrupt */
0, /* watch */
0, /* overflow */
.
458c
COMMAND(ctlr, AckIntr, Latch);
.
456c
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ctlr));
.
444c
COMMAND(ctlr, AckIntr, TxAvailable);
.
434,435c
COMMAND(ctlr, TxReset, 0);
COMMAND(ctlr, TxEnable, 0);
.
431c
}while(ins(ctlr->card.io+Status) & TxComplete);
.
428,429c
if(x = inb(ctlr->card.io+TxStatus))
outb(ctlr->card.io+TxStatus, 0);
.
403c
COMMAND(ctlr, RxReset, 0);
.
398,399c
COMMAND(ctlr, TxReset, 0);
COMMAND(ctlr, TxEnable, 0);
.
394c
diag = getdiag(ctlr);
.
384c
status = ins(ctlr->card.io+Status);
.
380d
376a
static ushort
getdiag(Ctlr *ctlr)
{
ushort bytes;
COMMAND(ctlr, SelectWindow, 4);
bytes = ins(ctlr->card.io+FIFOdiag);
COMMAND(ctlr, SelectWindow, 1);
return bytes & 0xFFFF;
}
.
374d
368,370c
outs(ctlr->card.io+Fifo, tb->len);
outs(ctlr->card.io+Fifo, 0);
outss(ctlr->card.io+Fifo, tb->pkt, len/2);
.
359,360c
if(len > ins(ctlr->card.io+TxFreeBytes)+4){
COMMAND(ctlr, SetTxAvailable, len);
.
350d
347d
345d
336,337c
COMMAND(ctlr, RxDiscard, 0);
while(ins(ctlr->card.io+Status) & CmdInProgress)
.
322c
inss(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 2));
.
320c
insl(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 4));
.
279c
while(((status = ins(ctlr->card.io+RxStatus)) & RxEmpty) == 0){
.
274d
260,270d
257c
COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr);
.
255c
COMMAND(ctlr, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
.
252,253d
242,246c
COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr);
COMMAND(ctlr, SetReadZeroMask, AllIntr|Latch);
COMMAND(ctlr, SetIntrMask, AllIntr|Latch);
COMMAND(ctlr, RxEnable, 0);
COMMAND(ctlr, TxEnable, 0);
.
232,233d
221,225d
217c
COMMAND(ctlr, StartCoax, 0);
.
210c
COMMAND(ctlr, SelectWindow, 1);
.
204c
outb(ctlr->card.io+i, ctlr->ea[i]);
.
202c
COMMAND(ctlr, SelectWindow, 2);
.
191c
x = ins(ctlr->card.io+EEPROMdata);
.
188,189c
outs(ctlr->card.io+EEPROMcmd, (2<<6)|i);
while(ins(ctlr->card.io+EEPROMcmd) & 0x8000)
.
186c
while(ins(ctlr->card.io+EEPROMcmd) & 0x8000)
.
184c
ctlr->card.irq = (ins(ctlr->card.io+ResourceConfig)>>12) & 0x0F;
.
175,176c
ctlr->card.io = (acr & 0x1F)*0x10 + 0x200;
outb(ctlr->card.io+ConfigControl, 0x01);
.
125c
* at the first card that responds, if we ever have more
.
119d
87c
#define COMMAND(ctlr, cmd, a) outs(ctlr->card.io+Command, ((cmd)<<11)|(a))
.
## diffname pc/ether509.c 1993/0427
## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/ether509.c /n/bootesdump/1993/0427/sys/src/9/pc/ether509.c
334c
if(len+4 > ins(ctlr->card.io+TxFreeBytes)){
.
## diffname pc/ether509.c 1993/0915
## diff -e /n/bootesdump/1993/0427/sys/src/9/pc/ether509.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether509.c
456,461c
/*
* Do the little configuration dance. We only look
* at the first card that responds, if we ever have more
* than one we'll need to modify this sequence.
*
* 2. get to command state, reset, then return to command state
*/
idseq();
outb(IDport, 0xC1);
delay(2);
idseq();
/*
* 3. Read the Product ID from the EEPROM.
* This is done by writing the IDPort with 0x83 (0x80
* is the 'read EEPROM command, 0x03 is the offset of
* the Product ID field in the EEPROM).
* The data comes back 1 bit at a time.
* We seem to need a delay here between reading the bits.
*
* If the ID doesn't match the 3C509 ID code, the adapter
* probably isn't there, so barf.
*/
outb(IDport, 0x83);
for(x = 0, i = 0; i < 16; i++){
delay(5);
x <<= 1;
x |= inb(IDport) & 0x01;
}
if((x & 0xF0FF) != 0x9050)
return -1;
/*
* 3. Read the Address Configuration from the EEPROM.
* The Address Configuration field is at offset 0x08 in the EEPROM).
* 6. Activate the adapter by writing the Activate command
* (0xFF).
*/
outb(IDport, 0x88);
for(acr = 0, i = 0; i < 16; i++){
delay(20);
acr <<= 1;
acr |= inb(IDport) & 0x01;
}
outb(IDport, 0xFF);
/*
* 8. Now we can talk to the adapter's I/O base addresses.
* We get the I/O base address from the acr just read.
*
* Enable the adapter.
*/
ctlr->card.port = (acr & 0x1F)*0x10 + 0x200;
port = ctlr->card.port;
outb(port+ConfigControl, 0x01);
/*
* Read the IRQ from the Resource Configuration Register
* and the ethernet address from the EEPROM.
* The EEPROM command is 8bits, the lower 6 bits being
* the address offset.
*/
ctlr->card.irq = (ins(port+ResourceConfig)>>12) & 0x0F;
for(ea = 0, i = 0; i < 3; i++, ea += 2){
while(ins(port+EEPROMcmd) & 0x8000)
;
outs(port+EEPROMcmd, (2<<6)|i);
while(ins(port+EEPROMcmd) & 0x8000)
;
x = ins(port+EEPROMdata);
ctlr->ea[ea] = (x>>8) & 0xFF;
ctlr->ea[ea+1] = x & 0xFF;
}
/*
* Finished with window 0. Now set the ethernet address
* in window 2.
* Commands have the format 'CCCCCAAAAAAAAAAA' where C
* is a bit in the command and A is a bit in the argument.
*/
COMMAND(port, SelectWindow, 2);
for(i = 0; i < 6; i++)
outb(port+i, ctlr->ea[i]);
/*
* Finished with window 2.
* Set window 1 for normal operation.
*/
COMMAND(port, SelectWindow, 1);
/*
* If we have a 10BASE2 transceiver, start the DC-DC
* converter. Wait > 800 microseconds.
*/
if(((acr>>14) & 0x03) == 0x03){
COMMAND(port, StartCoax, 0);
delay(1);
}
/*
* Set up the software configuration.
*/
ctlr->card.reset = ccc509reset;
ctlr->card.attach = attach;
ctlr->card.mode = mode;
ctlr->card.transmit = transmit;
ctlr->card.intr = interrupt;
ctlr->card.bit16 = 1;
return 0;
}
void
ether509link(void)
{
addethercard("3C509", ccc509reset);
}
.
453,454c
/*
* Get configuration parameters.
*/
int
ccc509reset(Ctlr *ctlr)
{
int i, ea;
ushort x, acr;
ulong port;
.
448,451c
outb(IDport, 0);
outb(IDport, 0);
for(al = 0xFF, i = 0; i < 255; i++){
outb(IDport, al);
if(al & 0x80){
al <<= 1;
al ^= 0xCF;
}
else
al <<= 1;
}
}
.
445,446c
/*
* Write two 0 bytes to identify the IDport and then reset the
* ID sequence. Then send the ID sequence to the card to get
* the card into command state.
*/
static void
idseq(void)
{
int i;
uchar al;
.
442c
COMMAND(port, AckIntr, Latch);
.
428c
COMMAND(port, AckIntr, TxAvailable);
.
418,419c
COMMAND(port, TxReset, 0);
COMMAND(port, TxEnable, 0);
.
415c
}while(ins(port+Status) & TxComplete);
.
412,413c
if(x = inb(port+TxStatus))
outb(port+TxStatus, 0);
.
387c
COMMAND(port, RxReset, 0);
.
382,383c
COMMAND(port, TxReset, 0);
COMMAND(port, TxEnable, 0);
.
368c
port = ctlr->card.port;
status = ins(port+Status);
.
366a
ulong port;
.
356,358c
port = ctlr->card.port;
COMMAND(port, SelectWindow, 4);
bytes = ins(port+FIFOdiag);
COMMAND(port, SelectWindow, 1);
.
354a
ulong port;
.
343,345c
outs(port+Fifo, tb->len);
outs(port+Fifo, 0);
outss(port+Fifo, tb->pkt, len/2);
.
334,335c
if(len+4 > ins(port+TxFreeBytes)){
COMMAND(port, SetTxAvailable, len);
.
325a
port = ctlr->card.port;
.
324a
ulong port;
.
314,315c
COMMAND(port, RxDiscard, 0);
while(ins(port+Status) & CmdInProgress)
.
300c
inss(port+Fifo, rb->pkt, HOWMANY(len, 2));
.
298c
insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
.
257c
port = ctlr->card.port;
while(((status = ins(port+RxStatus)) & RxEmpty) == 0){
.
255a
ulong port;
.
247c
COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
.
245c
COMMAND(port, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
.
243a
ulong port;
port = ctlr->card.port;
.
234,238c
COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
COMMAND(port, SetReadZeroMask, AllIntr|Latch);
COMMAND(port, SetIntrMask, AllIntr|Latch);
COMMAND(port, RxEnable, 0);
COMMAND(port, TxEnable, 0);
.
123,226d
100,121c
port = ctlr->card.port;
.
97,98c
ulong port;
.
95c
attach(Ctlr *ctlr)
.
89,93d
87c
#define COMMAND(port, cmd, a) outs(port+Command, ((cmd)<<11)|(a))
.
## diffname pc/ether509.c 1993/1113
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/ether509.c
474c
addethercard("3C509", reset);
.
467a
ether->promiscuous = promiscuous;
ether->arg = ether;
.
461,466c
ether->attach = attach;
ether->write = write;
ether->interrupt = interrupt;
.
441c
outb(port+i, ether->ea[i]);
.
429,430c
ether->ea[ea] = (x>>8) & 0xFF;
ether->ea[ea+1] = x & 0xFF;
.
421c
ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F;
.
411,412c
ether->port = (acr & 0x1F)*0x10 + 0x200;
port = ether->port;
.
360,362c
* Do the little configuration dance:
.
352,353c
static int
reset(Ether *ether)
.
320c
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ether));
.
309,310c
wakeup(ðer->tr);
}
.
307c
if(status & TxAvailable){
.
300c
ether->oerrs++;
.
278,279c
receive(ether);
.
271,273d
268c
attach(ether);
.
263a
wakeup(ðer->tr);
.
258c
diag = getdiag(ether);
.
249a
print("I%2.2ux|", status);
.
247c
port = ether->port;
.
241c
interrupt(Ether *ether)
.
233c
port = ether->port;
.
228c
getdiag(Ether *ether)
.
224a
/*
* We know there's room, copy the packet to the FIFO.
* To save copying the packet into a local buffer just
* so we can set the source address, stuff the packet
* into the FIFO in 3 pieces.
* Transmission won't start until the entire packet is
* in the FIFO, so it's OK to fault here.
*/
outs(port+Fifo, ether->tlen);
outs(port+Fifo, 0);
outss(port+Fifo, buf, Eaddrlen/2);
outss(port+Fifo, ether->ea, Eaddrlen/2);
outss(port+Fifo, (uchar*)buf+2*Eaddrlen, (len-2*Eaddrlen)/2);
return n;
.
215,223c
static long
write(Ether *ether, void *buf, long n)
{
ushort len;
ulong port;
print("W|");
port = ether->port;
ether->tlen = n;
len = ROUNDUP(ether->tlen, 4);
tsleep(ðer->tr, istxfifo, ether, 10000);
if(len+4 > ins(port+TxFreeBytes)){
print("ether509: transmitter jammed\n");
return 0;
.
201,213c
ether = arg;
port = ether->port;
/*
* If there's no room in the FIFO for this packet,
* set up an interrupt for when space becomes available.
* Output packet must be a multiple of 4 in length and
* we need 4 bytes for the preamble.
* Assume here that when we are called (via tsleep) that
* we are safe from interrupts.
*/
len = ROUNDUP(ether->tlen, 4);
if(len+4 > ins(port+TxFreeBytes)){
COMMAND(port, SetTxAvailable, len);
return 0;
}
return 1;
}
.
197c
Ether *ether;
.
194,195c
static int
istxfifo(void *arg)
.
176,180c
/*
* Copy the packet to whoever wants it.
*/
type = (ether->rpkt.type[0]<<8)|ether->rpkt.type[1];
ep = ðer->f[Ntypes];
for(fp = ether->f; fp < ep; fp++) {
f = *fp;
if(f && (f->type == type || f->type < 0))
qproduce(f->in, ðer->rpkt, len);
.
162,174c
len = (status & RxByteMask);
inss(port+Fifo, ðer->rpkt, HOWMANY(len, 2));
.
158,160c
* We have a packet. Read it into the
* buffer. The CRC is already stripped off.
* Must read len bytes padded to a
* doubleword. We can pick them out 16-bits
* at a time (can try 32-bits at a time
* later).
insl(port+Fifo, ether->rpkt, HOWMANY(len, 4));
.
152c
ether->crcs++;
.
148c
ether->frames++;
.
145c
ether->buffs++;
.
140c
ether->overflows++;
.
130c
port = ether->port;
.
128a
Netfile *f, **fp, **ep;
.
125,126c
ushort status, type;
.
123c
receive(Ether *ether)
.
115c
port = ((Ether*)arg)->port;
.
111c
promiscuous(void *arg, int on)
.
94c
port = ether->port;
.
90c
attach(Ether *ether)
.
10c
#include "etherif.h"
.
8c
#include "../port/error.h"
#include "../port/netif.h"
.
6d
## diffname pc/ether509.c 1993/1116
## diff -e /n/fornaxdump/1993/1113/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether509.c
270d
222d
## diffname pc/ether509.c 1993/1118
## diff -e /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether509.c
242a
poperror();
qunlock(ðer->tlock);
.
228,229c
.
226c
if(len+4 > ins(port+TxFreeBytes))
.
222a
qlock(ðer->tlock);
if(waserror()) {
qunlock(ðer->tlock);
nexterror();
}
.
## diffname pc/ether509.c 1993/1119
## diff -e /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether509.c
249,251d
234a
return 0;
}
.
233c
if(len+4 > ins(port+TxFreeBytes)){
.
224,229d
## diffname pc/ether509.c 1993/1124
## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether509.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether509.c
269a
.
268a
USED(ur);
ether = arg;
.
267a
Ether *ether;
.
263c
interrupt(Ureg *ur, void *arg)
.
## diffname pc/ether509.c 1994/0202
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether509.c
172,178c
etherrloop(ether, ðer->rpkt, len);
.
128d
125c
ushort status;
.
## diffname pc/ether509.c 1994/0205
## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0205/sys/src/brazil/pc/ether509.c
468c
if((acr & XcvrTypeMask) == XcvrBNC){
.
455c
for(i = 0; i < Eaddrlen; i++)
.
453a
if((ether->ea[0]|ether->ea[1]|ether->ea[2]|ether->ea[3]|ether->ea[4]|ether->ea[5]) == 0){
for(i = 0; i < sizeof(ether->ea); i++)
ether->ea[i] = ea[i];
}
.
446a
acr = ins(port+AddressConfig);
.
444,445c
ea[eax] = (x>>8) & 0xFF;
ea[eax+1] = x & 0xFF;
.
437c
for(eax = 0, i = 0; i < 3; i++, eax += 2){
.
431,432c
* Read the IRQ from the Resource Configuration Register,
* the ethernet address from the EEPROM, and the address configuration.
.
428d
426a
outb(ether->port+ConfigControl, 0x01);
return 0;
}
/*
* Get configuration parameters.
*/
static int
reset(Ether *ether)
{
int i, eax;
uchar ea[Eaddrlen];
ushort x, acr;
ulong port;
/*
* Switch out to 509 activation code if a port is supplied and is
* not in the EISA slot space, otherwise check the EISA card is there.
*/
if(ether->port < 0x1000 && activate(ether) < 0)
return -1;
else if((ins(ether->port+ProductID) & 0xF0FF) != 0x9050)
return -1;
.
374d
372c
int i;
.
366,370c
static ulong
activate(Ether *ether)
.
237c
outsl(port+Fifo, (uchar*)buf+2*Eaddrlen, (len-2*Eaddrlen)/4);
ether->outpackets++;
.
166c
insl(port+Fifo, ðer->rpkt, HOWMANY(len, 4));
.
164a
ether->inpackets++;
.
160,163c
* doubleword. We can pick them out 32-bits
* at a time.
.
132,133c
* If we had an error, log it and continue.
.
45a
/* AddressConfig Bits */
XcvrTypeMask = 0xC000, /* Transceiver Type Select */
Xcvr10BaseT = 0x0000,
XcvrAUI = 0x4000,
XcvrBNC = 0xC000,
.
44a
ProductID = 0x02,
ManufacturerID = 0x00,
.
43a
AddressConfig = 0x06,
.
## diffname pc/ether509.c 1994/0209
## diff -e /n/fornaxdump/1994/0205/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0209/sys/src/brazil/pc/ether509.c
475a
port = ether->port;
.
456,457d
453,454d
451c
if(ether->port < 0x1000){
if((port = activate(ether)) < 0)
return -1;
}
else if(ins(ether->port+ManufacturerID) == 0x6D50)
port = ether->port+0xC80;
else
.
449a
* Port is set to either the newly activated ISA card address or
* the EISA slot configuration info where Window0 is always mapped.
.
433c
return ether->port;
.
407c
if((x & 0xF0FF) != 0x6D50)
.
401c
outb(IDport, 0x87);
.
391,394c
* 3. Read the Manufacturer ID from the EEPROM.
* This is done by writing the IDPort with 0x87 (0x80
* is the 'read EEPROM command, 0x07 is the offset of
* the Manufacturer ID field in the EEPROM).
.
56a
Timer = 0x0A,
.
## diffname pc/ether509.c 1994/0211
## diff -e /n/fornaxdump/1994/0209/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0211/sys/src/brazil/pc/ether509.c
511a
ether->port = port;
.
482,483d
458,460c
if(port == 0)
port = tcm579(ether);
if(port == 0)
port = tcm509(ether);
if(port == 0)
.
454,456c
port = 0;
for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){
if(ether->port == 0 || ether->port == ap->port){
port = ap->port;
*app = ap->next;
free(ap);
break;
}
.
449,452c
* Any adapter matches if no ether->port is supplied,
* otherwise the ports must match.
* See if we've already found an adapter that fits
* the bill.
* If no match then try for an EISA card and finally
* for an ISA card.
.
446a
Adapter *ap, **app;
.
436a
static ulong
tcm509(Ether *ether)
{
USED(ether);
return 0;
}
static ulong
tcm579(Ether *ether)
{
static int slot = 1;
ulong port;
Adapter *ap;
if(slot == 1 && strncmp((char*)(KZERO|0xFFFD9), "EISA", 4))
return 0;
while(slot < 8){
port = slot++*0x1000;
if(ins(port+0xC80+ManufacturerID) != 0x6D50)
continue;
COMMAND(port+0xC80, GlobalReset, 0);
delay(1000);
outb(port+0xC80+ConfigControl, 0x01);
COMMAND(port+0xC80, SelectWindow, 0);
if(ether->port == 0 || ether->port == port)
return port;
ap = malloc(sizeof(Adapter));
ap->port = port;
ap->next = adapter;
adapter = ap;
}
return 0;
}
.
399c
* If the ID doesn't match, the adapter
.
350a
typedef struct Adapter Adapter;
struct Adapter {
Adapter *next;
ulong port;
};
static Adapter *adapter;
.
15a
GlobalReset = 0x00, /* Global Reset */
.
## diffname pc/ether509.c 1994/0212
## diff -e /n/fornaxdump/1994/0211/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0212/sys/src/brazil/pc/ether509.c
461c
while(slot < 16){
.
442c
return port;
.
439,440c
port = (acr & 0x1F)*0x10 + 0x200;
outb(port+ConfigControl, 0x01);
.
416,417c
if(x != 0x6D50)
return 0;
.
402c
* is the 'read EEPROM' command, 0x07 is the offset of
.
395,397d
392c
* 2. write the ID sequence to get to command state.
.
387a
ulong port;
.
384c
activate(void)
.
## diffname pc/ether509.c 1994/0213
## diff -e /n/fornaxdump/1994/0212/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0213/sys/src/brazil/pc/ether509.c
447a
#ifdef notdef
ulong port;
Adapter *ap;
while(port = activate()){
}
return 0;
#endif /* notdef */
.
## diffname pc/ether509.c 1994/0215
## diff -e /n/fornaxdump/1994/0213/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0215/sys/src/brazil/pc/ether509.c
475c
outs(port+0xC80+ConfigControl, Ena);
.
457d
453a
if(ether->port == 0 || ether->port == port)
return port;
ap = malloc(sizeof(Adapter));
ap->port = port;
ap->next = adapter;
adapter = ap;
.
452a
/*
* One time only:
* write ID sequence to get the attention of all adapters;
* global-reset all adapters;
* untag all adapters.
*/
if(reset == 0){
idseq();
outb(IDport, 0xC0);
delay(2);
outb(IDport, 0xD0);
reset = 1;
}
/*
* Attempt to activate adapters until one matches our
* address criteria.
*/
.
446,449c
static int reset;
.
438c
outs(port+ConfigControl, Ena);
.
428a
outb(IDport, 0xD1);
.
419a
* 6. Tag the adapter so it won't respond in future.
.
405,406c
* If the ID doesn't match, there are no more adapters.
.
55a
/* ConfigControl */
Rst = 0x04, /* Reset Adapter */
Ena = 0x01, /* Enable Adapter */
.
48c
ConfigControl = 0x04,
AddressConfig = 0x06,
ResourceConfig = 0x08,
EEPROMcmd = 0x0A,
EEPROMdata = 0x0C,
.
42,46c
ManufacturerID = 0x00, /* window 0 */
.
13,14c
IDport = 0x0110, /* anywhere between 0x0100 and 0x01F0 */
.
## diffname pc/ether509.c 1994/0216
## diff -e /n/fornaxdump/1994/0215/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0216/sys/src/brazil/pc/ether509.c
587a
while(inb(port+TxStatus))
outb(port+TxStatus, 0);
.
585a
* Clear out any lingering Tx status.
.
553c
* The EEPROM command is 8 bits, the lower 6 bits being
.
547a
port = tcm589(ether);
if(port == 0)
.
531,532c
* If no match then try for an EISA card, an ISA card
* and finally for a PCMCIA card.
.
513a
static ulong
tcm589(Ether *ether)
{
USED(ether);
return 0;
}
.
498,501c
x = ins(port+0xC80+ProductID);
if((x & 0xF0FF) != 0x9050/* || (x != 0x9350 && x != 0x9250)*/)
continue;
COMMAND(port, SelectWindow, 0);
outs(port+ConfigControl, Ena);
COMMAND(port, TxReset, 0);
COMMAND(port, RxReset, 0);
COMMAND(port, AckIntr, 0xFF);
.
493a
/*
* Continue through the EISA slots looking for a match on both
* 3COM as the manufacturer and 3C579 or 3C579-TP as the product.
* If we find an adapter, select window 0, enable it and clear
* out any lingering status and interrupts.
* Trying to do a GlobalReset here to re-init the card (as in the
* 509 code) doesn't seem to work.
*/
.
491a
/*
* First time through, check if this is an EISA machine.
* If not, nothing to do.
*/
.
488a
ushort x;
.
472c
while(port = activate(0)){
if(port == 0x3F0){
outb(IDport, 0xD1);
continue;
}
outb(IDport, 0xC0);
if(activate(1) != port)
print("activate %d\n");
.
470c
* address criteria. If adapter is set for EISA mode,
* tag it and ignore. Otherwise, reset the adapter and
* activate it fully.
.
465c
untag = 1;
.
462,463d
460c
if(untag == 0){
.
458a
* If we do a global reset here on all adapters we'll confuse any
* ISA cards configured for EISA mode.
.
457d
450c
static int untag;
.
443a
if(tag){
/*
* 6. Tag the adapter so it won't respond in future.
* 6. Activate the adapter by writing the Activate command
* (0xFF).
*/
outb(IDport, 0xD1);
outb(IDport, 0xFF);
/*
* 8. Now we can talk to the adapter's I/O base addresses.
* We get the I/O base address from the acr just read.
*
* Enable the adapter.
*/
outs(port+ConfigControl, Ena);
}
.
442d
432,440d
422,424d
387c
activate(int tag)
.
## diffname pc/ether509.c 1994/0218
## diff -e /n/fornaxdump/1994/0216/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0218/sys/src/brazil/pc/ether509.c
485c
print("tcm509: activate\n");
.
483a
delay(2);
.
## diffname pc/ether509.c 1994/0628
## diff -e /n/fornaxdump/1994/0218/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0628/sys/src/brazil/pc/ether509.c
636,644d
629c
* Enable the transceiver if necessary.
*/
switch(acr & XcvrTypeMask){
case Xcvr10BaseT:
/*
* Enable Link Beat and Jabber to start the
* transceiver.
*/
COMMAND(port, SelectWindow, 4);
outb(port+MediaStatus, LinkBeatEna|JabberEna);
break;
case XcvrBNC:
/*
* Start the DC-DC converter.
* Wait > 800 microseconds.
*/
COMMAND(port, StartCoax, 0);
delay(1);
break;
}
/*
.
98a
/* MediaStatus bits */
JabberEna = 0x0040, /* Jabber Enabled (writeable) */
LinkBeatEna = 0x0080, /* Link Beat Enabled (writeable) */
.
91a
MediaStatus = 0x0A,
.
## diffname pc/ether509.c 1994/0715
## diff -e /n/fornaxdump/1994/0628/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether509.c
188c
etherrloop(ether, ðer->rpkt, len, 1);
.
## diffname pc/ether509.c 1994/1124
## diff -e /n/fornaxdump/1994/0715/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/1124/sys/src/brazil/pc/ether509.c
63c
Timer = 0x0A,
TxStatus = 0x0B,
TxFreeBytes = 0x0C,
.
59,61c
Fifo = 0x00, /* window 1 */
.
## diffname pc/ether509.c 1994/1207
## diff -e /n/fornaxdump/1994/1124/sys/src/brazil/pc/ether509.c /n/fornaxdump/1994/1207/sys/src/brazil/pc/ether509.c
35c
Promiscuous = 0x08, /* All addresses (promiscuous mode) */
.
## diffname pc/ether509.c 1995/0331
## diff -e /n/fornaxdump/1994/1207/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0331/sys/src/brazil/pc/ether509.c
683c
addethercard("3C509", ether509reset);
.
606c
if(strcmp(ether->type, "3C589") != 0)
ether->irq = (ins(port+ResourceConfig)>>12) & 0x0F;
.
596,597d
590a
if(strcmp(ether->type, "3C589") == 0)
port = ether->port;
.
565,566c
int
ether509reset(Ether *ether)
.
555,561d
282d
## diffname pc/ether509.c 1995/0401
## diff -e /n/fornaxdump/1995/0331/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0401/sys/src/brazil/pc/ether509.c
584c
port = ether->card.port;
.
## diffname pc/ether509.c 1995/0403
## diff -e /n/fornaxdump/1995/0401/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0403/sys/src/brazil/pc/ether509.c
584c
port = ether->port;
.
## diffname pc/ether509.c 1995/0419
## diff -e /n/fornaxdump/1995/0403/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0419/sys/src/brazil/pc/ether509.c
350c
* dealt with other than Latch. Should deal with UP (Update
* Statistics) for happier coexistence with Windows drivers.
.
## diffname pc/ether509.c 1995/0504
## diff -e /n/fornaxdump/1995/0419/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0504/sys/src/brazil/pc/ether509.c
70a
Update = 0x0080, /* Update Statistics */
.
## diffname pc/ether509.c 1995/0506
## diff -e /n/fornaxdump/1995/0504/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0506/sys/src/brazil/pc/ether509.c
346,358d
325,344c
if(status & AllIntr)
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ether));
.
320,323c
* Panic if there are any interrupt bits on we haven't
* dealt with. Should deal with UP (Update Statistics)
* for happier coexistence with Windows drivers.
.
309,318c
.
304,307c
if(status & (TxAvailable|TxComplete)){
/*
* Reset the Tx FIFO threshold.
*/
if(status & TxAvailable){
COMMAND(port, AckIntr, TxAvailable);
wakeup(ðer->tr);
}
status &= ~(TxAvailable|TxComplete);
.
302c
ether->oerrs++;
.
296,300c
COMMAND(port, AckIntr, Latch);
status = ins(port+Status);
if((status & AllIntr) == 0)
break;
if(status & Failure){
/*
* Adapter failure, try to find out why.
* Reset if necessary.
* What happens if Tx is active and we reset,
* need to retransmit?
* This probably isn't right.
*/
diag = getdiag(ether);
print("ether509: status #%ux, diag #%ux\n", status, diag);
if(diag & TxOverrun){
COMMAND(port, TxReset, 0);
COMMAND(port, TxEnable, 0);
wakeup(ðer->tr);
}
if(diag & RxUnderrun){
COMMAND(port, RxReset, 0);
attach(ether);
}
return;
}
if(status & RxComplete){
receive(ether);
status &= ~RxComplete;
}
if(status & TxComplete){
/*
* Pop the TX Status stack, accumulating errors.
* If there was a Jabber or Underrun error, reset
* the transmitter. For all conditions enable
* the transmitter.
*/
txstatus = 0;
do{
if(x = inb(port+TxStatus))
outb(port+TxStatus, 0);
txstatus |= x;
}while(ins(port+Status) & TxComplete);
if(txstatus & (TxJabber|TxUnderrun))
COMMAND(port, TxReset, 0);
.
290,294c
* Clear the interrupt latch.
* It's possible to receive a packet and for another
* to become complete before we exit the interrupt
* handler so this must be done first to ensure another
* interrupt will occur.
.
286,288c
for(;;){
.
## diffname pc/ether509.c 1995/0509
## diff -e /n/fornaxdump/1995/0506/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0509/sys/src/brazil/pc/ether509.c
367c
}
.
## diffname pc/ether509.c 1995/0517
## diff -e /n/fornaxdump/1995/0509/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0517/sys/src/brazil/pc/ether509.c
621c
if(pcicfg == 0)
acr = ins(port+AddressConfig);
else{
ether->irq = pcicfg->irq;
acr = Xcvr10BaseT;
COMMAND(port, SelectWindow, 3);
print("internal config = 0x%8.8luX\n", inl(port+0x00));
free(pcicfg);
}
.
609c
if(strcmp(ether->type, "3C589") != 0 && pcicfg == 0)
.
595a
if(port == 0 && (pcicfg = tcm590(ether)))
port = pcicfg->baseaddr[0] & ~0x01;
.
588a
pcicfg = ap->pcicfg;
.
585a
pcicfg = 0;
.
575a
PCIcfg *pcicfg;
.
564a
static PCIcfg*
tcm590(Ether *ether)
{
PCIcfg* pcicfg;
static uchar devno = 0;
ulong port;
Adapter *ap;
pcicfg = malloc(sizeof(PCIcfg));
while(devno < 16){
pcicfg->vid = 0x10B7;
pcicfg->did = 0;
if(pcimatch(0, devno++, pcicfg) == 0)
continue;
port = pcicfg->baseaddr[0] & ~0x01;
if(ether->port == 0 || ether->port == port)
return pcicfg;
ap = malloc(sizeof(Adapter));
ap->pcicfg = pcicfg;
pcicfg = malloc(sizeof(PCIcfg));
ap->port = port;
ap->next = adapter;
adapter = ap;
}
free(pcicfg);
return 0;
}
.
372,373c
Adapter* next;
ulong port;
PCIcfg* pcicfg;
.
## diffname pc/ether509.c 1995/0518
## diff -e /n/fornaxdump/1995/0517/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0518/sys/src/brazil/pc/ether509.c
581a
COMMAND(port, GlobalReset, 0);
while(ins(port+Status) & CmdInProgress)
;
.
## diffname pc/ether509.c 1995/0519
## diff -e /n/fornaxdump/1995/0518/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0519/sys/src/brazil/pc/ether509.c
696,697c
outs(port+MediaStatus, x|LinkBeatEna|JabberEna);
.
688a
COMMAND(port, SelectWindow, 4);
x = ins(port+MediaStatus) & ~(LinkBeatEna|JabberEna);
outs(port+MediaStatus, x);
.
682d
677a
COMMAND(port, SelectWindow, 2);
.
668c
l = inl(port+InternalCgf);
l &= ~0x700000;
outl(port+InternalCgf, l);
.
649a
COMMAND(port, SelectWindow, 0);
.
610c
ulong l, port;
.
594a
pcicfg = malloc(sizeof(PCIcfg));
.
591d
539c
while(slot < MaxEISA){
.
91a
InternalCgf = 0x00, /* window 3 */
.
## diffname pc/ether509.c 1995/0627
## diff -e /n/fornaxdump/1995/0519/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0627/sys/src/brazil/pc/ether509.c
106a
LinkBeatOk = 0x0800, /* Valid link beat detected (ro) */
.
## diffname pc/ether509.c 1995/0706
## diff -e /n/fornaxdump/1995/0627/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0706/sys/src/brazil/pc/ether509.c
127,128c
COMMAND(port, SetReadZeroMask, (AllIntr|Latch) & ~Update);
COMMAND(port, SetIntrMask, (AllIntr|Latch) & ~Update);
.
124a
* Disable Update interrupts for now.
.
## diffname pc/ether509.c 1995/0721
## diff -e /n/fornaxdump/1995/0706/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether509.c
582,583c
if((devno = pcimatch(0, devno, pcicfg)) == -1)
break;
.
579c
for(;;){
.
574,575c
static int devno = 0;
int port;
.
193c
etherrloop(ether, ðer->rpkt, len);
.
## diffname pc/ether509.c 1995/0801
## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether509.c
127c
x = Broadcast|MyEtherAddr;
if(ether->prom)
x |= Promiscuous;
COMMAND(port, SetRxFilter, x);
.
115a
int x;
.
## diffname pc/ether509.c 1995/1018
## diff -e /n/fornaxdump/1995/0801/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/1018/sys/src/brazil/pc/ether509.c
682a
else
acr = ins(port+AddressConfig);
.
679,680c
switch(l & 0x700000){
case 0x000000:
acr = Xcvr10BaseT;
break;
case 0x300000:
acr = XcvrBNC;
break;
}
.
677a
acr = XcvrAUI;
.
676d
672,674c
if(pcicfg){
.
## diffname pc/ether509.c 1995/1019
## diff -e /n/fornaxdump/1995/1018/sys/src/brazil/pc/ether509.c /n/fornaxdump/1995/1019/sys/src/brazil/pc/ether509.c
642,643c
if(port == 0)
port = tcm589(ether);
.
609a
static ulong
tcm589(ISAConf *isa)
{
if(strcmp(isa->type, "3C589") != 0)
return 0;
/*
* The 3com manual register description says that this a noop for
* PCMCIA but the flow chart at the end shows it.
*/
COMMAND(isa->port, SelectWindow, 0);
outs(isa->port+ConfigControl, Ena);
return isa->port;
}
.
## diffname pc/ether509.c 1996/0227
## diff -e /n/fornaxdump/1995/1019/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0227/sys/src/brazil/pc/ether509.c
506,510c
/*
* 6. Activate the adapter by writing the Activate command
* (0xFF).
*/
outb(IDport, 0xFF);
delay(20);
/*
* 8. Now we can talk to the adapter's I/O base addresses.
* Use the I/O base address from the acr just read.
*
* Enable the adapter.
*/
while(ins(port+Status) & CmdInProgress)
;
COMMAND(port, SelectWindow, 0);
outs(port+ConfigControl, Ena);
COMMAND(port, TxReset, 0);
COMMAND(port, RxReset, 0);
COMMAND(port, AckIntr, 0xFF);
.
502,504c
while(port = activate()){
/*
* 6. Tag the adapter so it won't respond in future.
*/
outb(IDport, 0xD1);
if(port == 0x3F0)
.
497,500c
* Attempt to activate adapters until one matches the
* address criteria. If adapter is set for EISA mode (0x3F0),
* tag it and ignore. Otherwise, activate it fully.
.
455,473c
return (acr & 0x1F)*0x10 + 0x200;
.
453d
436c
delay(20);
.
434a
delay(20);
.
415d
411c
activate(void)
.
407a
/*
* One time only:
* write ID sequence to get the attention of all adapters;
* untag all adapters.
* If we do a global reset here on all adapters we'll confuse any
* ISA cards configured for EISA mode.
*/
if(untag == 0){
outb(IDport, 0xD0);
untag = 1;
}
.
396a
/*
* One time only:
* reset any adapters listening
*/
if(reset == 0){
outb(IDport, 0);
outb(IDport, 0);
outb(IDport, 0xC0);
delay(20);
reset = 1;
}
.
395a
static int reset, untag;
.
## diffname pc/ether509.c 1996/0228
## diff -e /n/fornaxdump/1996/0227/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0228/sys/src/brazil/pc/ether509.c
523c
* 8. Can now talk to the adapter's I/O base addresses.
.
490,502d
485d
## diffname pc/ether509.c 1996/0607 # deleted
## diff -e /n/fornaxdump/1996/0228/sys/src/brazil/pc/ether509.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/ether509.c
1,785d
|