From 78ee7d5717807e6ac779293d0d3c78341de6130a Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Sun, 28 Dec 2025 12:27:31 +0300 Subject: Move existing boards into subdits split per arch --- os/cerf250/ether91c111.c | 1056 ---------------------------------------------- 1 file changed, 1056 deletions(-) delete mode 100644 os/cerf250/ether91c111.c (limited to 'os/cerf250/ether91c111.c') diff --git a/os/cerf250/ether91c111.c b/os/cerf250/ether91c111.c deleted file mode 100644 index 2a404d93..00000000 --- a/os/cerf250/ether91c111.c +++ /dev/null @@ -1,1056 +0,0 @@ -/* - * SMsC 91c111 ethernet controller - * Copyright © 2001,2004 Vita Nuova Holdings Limited. All rights reserved. - * - * TO DO: - * - use ethermii - * - use DMA where available - */ - -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/netif.h" - -#include "etherif.h" - -/* - * chip definitions - */ - -typedef struct Ctlr Ctlr; - -enum { - SMSC91C11x, - SMSC91C110, - SMSC91C111, - SMSC91C96, -}; - -struct Ctlr { - Lock; - uchar *base; - int type; - int rev; - int hasmii; - int phyad; - int bank; /* currently selected bank */ - Block* waiting; /* waiting for space in FIFO */ - - ulong collisions; - ulong toolongs; - ulong tooshorts; - ulong aligns; - ulong txerrors; - int oddworks; - int bus32bit; -}; - -#define MKREG(bank, off) ((bank << 8) | (off)) - -enum { - /* Bank 0 */ - Tcr= MKREG(0, 0), /* transmit control */ - TcrSwfdup= 1<<15, /* switched full duplex */ - TcrEphLoop= 1<<13, /* internal loopback */ - TcrStpSqet= 1<<12, /* stop transmission on SQET error */ - TcrFduplx= 1<<11, /* enable full duplex */ - TcrMonCsn= 1<<10, /* monitor collision (0 for MII operation) */ - TcrNoCRC= 1<<8, /* don't add CRC */ - TcrPadEn= 1<<7, /* pad short frames */ - TcrForceCol= 1<<2, /* force collision */ - TcrLoop= 1<<1, /* PHY loopback */ - TcrTxena= 1<<0, /* enable transmitter */ - Eph= MKREG(0, 2), /* there are more bits but we don't use them */ - EphLinkOk= 1<<14, - EphCtrRol= 1<<12, /* counter roll over; clear by reading Ecr */ - Rcr= MKREG(0, 4), /* receive control */ - RcrSoftRst= 1<<15, - RcrFiltCar= 1<<14, - RcrAbortEnb= 1<<13, - RcrStripCRC= 1<<9, - RcrRxEn= 1<<8, - RcrAlmul= 1<<2, /* ~=0, accept all multicast frames (=0, match multicast table) */ - RcrPrms= 1<<1, /* promiscuous mode */ - RcrRxAbort= 1<<0, /* set if receive frame longer than 2k bytes */ - Ecr= MKREG(0, 6), /* counter */ - EcrExcDeferred= 0xF<<12, /* excessively deferred Tx */ - EcrDeferred= 0xF<<8, /* deferred Tx */ - EcrMultCol= 0xF<<4, /* multiple collisions */ - EcrCollision= 0xF<<0, /* single collision */ - Mir= MKREG(0, 8), /* memory information */ - Mcr= MKREG(0, 0xA), /* memory config (91cxx) */ - Rpcr= Mcr, /* receive/phy control (91c111) */ - - /* Bank 1 */ - Config= MKREG(1, 0), - CfgMiiSelect= 1<<15, /* 91c110 */ - CfgEphPowerEn= CfgMiiSelect, /* =1, powered (after reset MMU); =0, low power mode (91c111) */ - CfgNoWait= 1<<12, /* don't request additional wait states */ - CfgSetSqlch= 1<<9, /* 91cxx */ - CfgGpcntrl= 1<<9, /* general purpose output (CNTRL), perhaps power-enable (91c111) */ - CfgAuiSelect= 1<<8, /* 91cxx */ - CfgExtPhy= 1<<8, /* enable external PHY/MII (91c111) */ - Cfg16Bit= 1<<7, /* 91cxx */ - BaseAddress= MKREG(1, 2), - Iaddr0_1= MKREG(1, 4), - Iaddr2_3= MKREG(1, 6), - Iaddr4_5= MKREG(1, 8), - Gpr= MKREG(1, 0xA), /* general purpose reg (EEPROM interface) */ - Control= MKREG(1, 0xC), /* control register */ - CtlRcvBad= 1<<14, /* allow bad CRC packets through */ - CtlAutoRelease= 1<<11, /* transmit pages released automatically w/out interrupt */ - CtlLeEnable= 1<<7, /* link error enable */ - CtlCrEnable= 1<<6, /* counter roll over enable */ - CtlTeEnable= 1<<5, /* transmit error enable */ - CtlEeSelect= 1<<2, /* EEPROM select */ - CtlReload= 1<<1, /* read EEPROM and update relevant registers */ - CtlStore= 1<<0, /* store relevant registers in EEPROM */ - - /* Bank 2 */ - Mmucr= MKREG(2, 0), /* MMU command */ - McrAllocTx= 1<<5, /* allocate space for outgoing packet */ - McrReset= 2<<5, /* reset to initial state */ - McrReadFIFO= 3<<5, /* remove frame from top of FIFO */ - McrRemove= 4<<5, /* remove and release top of Rx FIFO */ - McrFreeTx= 5<<5, /* release specific packet (eg, packets done Tx) */ - McrEnqueue= 6<<5, /* enqueue packet number to Tx FIFO */ - McrResetTx= 7<<5, /* reset both Tx FIFOs */ - McrBusy= 1<<0, - ArrPnr= MKREG(2, 2), /* Pnr (low byte), Arr (high byte) */ - ArrFailed= 1<<15, - FifoPorts= MKREG(2, 4), - FifoRxEmpty= 1<<15, - FifoTxEmpty= 1<<7, - Pointer= MKREG(2, 6), - PtrRcv= 1<<15, - PtrAutoIncr= 1<<14, - PtrRead= 1<<13, - PtrEtEn= 1<<12, - PtrNotEmpty= 1<<11, - Data= MKREG(2, 8), - Interrupt= MKREG(2, 0xC), /* status/ack (low byte), mask (high byte) */ - IntMii= 1<<7, /* PHY/MII state change */ - IntErcv= 1<<6, /* early receive interrupt (received > Ercv threshold) */ - IntEph= 1<<5, /* ethernet protocol interrupt */ - IntRxOvrn= 1<<4, /* overrun */ - IntAlloc= 1<<3, /* allocation complete */ - IntTxEmpty= 1<<2, /* TX FIFO now empty */ - IntTx= 1<<1, /* transmit done */ - IntRcv= 1<<0, /* packet received */ - IntrMask= MKREG(2, 0xD), - IntrMaskShift= 8, /* shift for Int... values to mask position in 16-bit register */ - IntrMaskField= 0xFF00, - - /* Bank 3 */ - Mt0_1= MKREG(3, 0), /* multicast table */ - Mt2_3= MKREG(3, 2), - Mt4_5= MKREG(3, 4), - Mt6_7= MKREG(3, 6), - Mgmt= MKREG(3, 8), /* management interface (MII) */ - MgmtMdo= 1<<0, /* MDO pin */ - MgmtMdi= 1<<1, /* MDI pin */ - MgmtMclk= 1<<2, /* drive MDCLK */ - MgmtMdoEn= 1<<3, /* MDO driven when high, tri-stated when low */ - Revision= MKREG(3, 0xA), - Ercv= MKREG(3, 0xC), /* early receive */ - - /* Bank 4 (91cxx only) */ - EcsrEcor= MKREG(4, 0), /* status and option registers */ - - /* all banks */ - BankSelect= MKREG(0, 0xe), -}; - -enum { - /* receive frame status word (p 38) */ - RsAlgnErr= 1<<15, - RsBroadcast= 1<<14, - RsBadCRC= 1<<13, - RsOddFrame= 1<<12, - RsTooLong= 1<<11, - RsTooShort= 1<<10, - RsMulticast= 1<<1, - RsError= RsBadCRC | RsAlgnErr | RsTooLong | RsTooShort, - - Framectlsize= 6, -}; - -static void miiw(Ctlr *ctlr, int regad, int val); -static int miir(Ctlr *ctlr, int regad); - -/* - * architecture dependent section - collected here in case - * we want to port the driver - */ - -#define PHYMIIADDR_91C110 3 -#define PHYMIIADDR_91C111 0 - -#define llregr(ctlr, reg) (*(ushort*)(ctlr->base + (reg))) -#define llregr32(ctlr, reg) (*(ulong*)(ctlr->base + (reg))) -#define llregw(ctlr, reg, val) (*(ushort*)(ctlr->base + (reg)) = (val)) - -static void -adinit(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - // TODO: code to turn on device clocks - ctlr->base = (uchar*)mmuphysmap(PHYSCS1, 0x100000) + ether->port; -iprint("adinit: %8.8lux -> %8.8lux mcs0=%8.8lux\n", (ulong)ctlr->base, PADDR(ctlr->base), MEMCFGREG->msc0); -{ulong v; v = *(ulong*)ctlr->base; iprint("value=%8.8lux\n", v);} - ctlr->bus32bit = 1; -} - -static void -adsetfd(Ctlr *ctlr) -{ - miiw(ctlr, 0x18, miir(ctlr, 0x18) | (1 << 5)); -} - -/* - * architecture independent section - */ - -static ushort -regr(Ctlr *ctlr, int reg) -{ - int bank; - ushort val; - - bank = reg >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - val = llregr(ctlr, reg & 0xff); - return val; -} - -static ulong -regr32(Ctlr *ctlr, int reg) -{ - int bank; - ulong val; - - bank = reg >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - val = llregr32(ctlr, reg & 0xff); - return val; -} - -static void -regw(Ctlr *ctlr, int reg, ushort val) -{ - int bank; - - bank = reg >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - llregw(ctlr, reg & 0xff, val); -} - -static void -regwdatam(Ctlr *ctlr, ushort *data, int ns) -{ - int bank; - ushort *faddr; - - bank = Data >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - faddr = (ushort*)(ctlr->base + (Data & 0xff)); - while(ns-- > 0){ - *faddr = *data; - data++; - } -} - -static void -regrdatam(Ctlr *ctlr, void *data, int nb) -{ - int bank; - ushort *f, *t; - int laps, ns; - - bank = Data >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - - if((ulong)data & 3) - iprint("bad buffer alignment\n"); - - t = data; - f = (ushort*)(ctlr->base + (Data & 0xff)); - ns = nb >> 1; - laps = ns / 8; - switch(ns & 7){ /* Duff's device */ - do { - *t++ = *f; - case 7: *t++ = *f; - case 6: *t++ = *f; - case 5: *t++ = *f; - case 4: *t++ = *f; - case 3: *t++ = *f; - case 2: *t++ = *f; - case 1: *t++ = *f; - case 0: - ; - } while(laps-- > 0); - } -} - -static void -regrdatam32(Ctlr *ctlr, void *data, int nb) -{ - int bank; - ulong *f, *t; - int laps, nw; - - bank = Data >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - - if((ulong)data & 3) - iprint("bad buffer alignment\n"); - - t = data; - f = (ulong*)(ctlr->base + (Data & 0xff)); - nw = nb>>2; - laps = nw / 8; - switch(nw & 7){ /* Duff's device */ - do { - *t++ = *f; - case 7: *t++ = *f; - case 6: *t++ = *f; - case 5: *t++ = *f; - case 4: *t++ = *f; - case 3: *t++ = *f; - case 2: *t++ = *f; - case 1: *t++ = *f; - case 0: - ; - } while(laps-- > 0); - } -} - -static void -regor(Ctlr *ctlr, int reg, ushort val) -{ - int bank; - - bank = reg >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - reg &= 0xff; - llregw(ctlr, reg, llregr(ctlr, reg) | val); -} - -static void -regclear(Ctlr *ctlr, int reg, ushort val) -{ - int bank; - - bank = reg >> 8; - if(ctlr->bank != bank){ - ctlr->bank = bank; - llregw(ctlr, BankSelect, bank); - } - reg &= 0xff; - llregw(ctlr, reg, llregr(ctlr, reg) & ~val); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *p; - int len; - - if(n == 0) - return 0; - - ctlr = ether->ctlr; - p = smalloc(READSTR); - if(waserror()){ - free(p); - nexterror(); - } - len = snprint(p, READSTR, "Overflow: %ud\n", ether->overflows); - len += snprint(p+len, READSTR, "Soft Overflow: %ud\n", ether->soverflows); - len += snprint(p+len, READSTR, "Transmit Error: %lud\n", ctlr->txerrors); - len += snprint(p+len, READSTR-len, "CRC Error: %ud\n", ether->crcs); - len += snprint(p+len, READSTR-len, "Collision: %lud\n", ctlr->collisions); - len += snprint(p+len, READSTR-len, "Align: %lud\n", ctlr->aligns); - len += snprint(p+len, READSTR-len, "Too Long: %lud\n", ctlr->toolongs); - snprint(p+len, READSTR-len, "Too Short: %lud\n", ctlr->tooshorts); - - n = readstr(offset, a, n, p); - poperror(); - free(p); - - return n; -} - -static void -promiscuous(void* arg, int on) -{ - Ether *ether; - Ctlr *ctlr; - int r; - - ether = arg; - ctlr = ether->ctlr; - ilock(ctlr); - r = regr(ctlr, Rcr); - if(on) - r |= RcrPrms; - else - r &= ~RcrPrms; - regw(ctlr, Rcr, r); - iunlock(ctlr); -} - -static void -attach(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - - /* - * enable transmit and receive - */ - regw(ctlr, Interrupt, (IntMii | IntTx | IntRcv | IntRxOvrn)<ctlr; - b = ctlr->waiting; - ctlr->waiting = nil; - if(b == nil) - return; /* shouldn't happen */ - pkt = regr(ctlr, ArrPnr); /* get packet number presumably just allocated */ - if(pkt & 0xC0){ - print("smc91c111: invalid packet number\n"); - freeb(b); - return; - } - - pointtotxpacket(ctlr, pkt, 0); - - lenb = BLEN(b); - odd = lenb & 1; - lenw = lenb >> 1; - regw(ctlr, Data, 0); // status word padding - regw(ctlr, Data, (lenw << 1) + Framectlsize); - regwdatam(ctlr, (ushort*)b->rp, lenw); // put packet into 91cxxx memory - lastw = 0x1000; - if(odd){ - lastw |= 0x2000; /* odd byte flag in control byte */ - lastw |= b->rp[lenb - 1]; - } - regw(ctlr, Data, lastw); - mmucommand(ctlr, McrEnqueue); // chip now owns buff - freeb(b); - regw(ctlr, Interrupt, (regr(ctlr, Interrupt) & IntrMaskField) | (IntTxEmpty << IntrMaskShift)); -} - -static void -txstart(Ether *ether) -{ - Ctlr *ctlr; - int n; - - ctlr = ether->ctlr; - if(ctlr->waiting != nil) /* allocate pending; must wait for that */ - return; - for(;;){ - if((ctlr->waiting = qget(ether->oq)) == nil) - break; - /* ctlr->waiting is a new block to transmit: allocate space */ - n = (BLEN(ctlr->waiting) & ~1) + Framectlsize; /* Framectlsize includes odd byte, if any */ - mmucommand(ctlr, McrAllocTx | (n >> 8)); - if(regr(ctlr, ArrPnr) & ArrFailed){ - regw(ctlr, Interrupt, (regr(ctlr, Interrupt) & IntrMaskField) | (IntAlloc << IntrMaskShift)); - break; - } - txloadpacket(ether); - } -} - -static void -transmit(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(ctlr); - txstart(ether); - iunlock(ctlr); -} - -static void -process(Ether *ether) -{ - Ctlr *ctlr; - int status, intrreg, intr, mask, fifo; - int pkt; - ulong data; - int count, len, alen; - Block *b; - - ctlr = ether->ctlr; - -Recheck: - intrreg = regr(ctlr, Interrupt); - regw(ctlr, Interrupt, 0); - mask = intrreg >> IntrMaskShift; - intr = intrreg & mask; - if(intr == 0){ - regw(ctlr, Interrupt, mask<waiting) - txloadpacket(ether); - mask &= ~IntAlloc; - mask |= IntTxEmpty; - } - - if(intr & IntRxOvrn){ - regw(ctlr, Interrupt, IntRxOvrn); - intr &= ~IntRxOvrn; - ether->overflows++; - } - if(intr & IntRcv){ - fifo = regr(ctlr, FifoPorts); - while((fifo & FifoRxEmpty) == 0){ - ether->inpackets++; - pointtorxpacket(ctlr, 0); - data = regr32(ctlr, Data); - status = data & 0xFFFF; - count = (data>>16) & 0x7FE; - if(status & RsBadCRC) - ether->crcs++; - else if(status & RsAlgnErr) - ether->frames++; - else if(status & (RsTooLong | RsTooShort)) - ether->buffs++; - else { - len = count - Framectlsize; - if(len < 0) - panic("smc:interrupt"); - if(ctlr->type == SMSC91C111 && !ctlr->oddworks) - len++; - else if(status & RsOddFrame) - len++; - alen = (len + 1) & ~1; - if(ctlr->bus32bit) - alen = (alen + 3) & ~3; - b = iallocb(alen); - if(b){ - (ctlr->bus32bit? regrdatam32: regrdatam)(ctlr, b->wp, alen); - b->wp += len; - etheriq(ether, b, 1); - }else - ether->soverflows++; - } - mmucommand(ctlr, McrRemove); - fifo = regr(ctlr, FifoPorts); - } - intr &= ~IntRcv; - } - if(intr & IntTx){ - /* some kind of failure */ - fifo = regr(ctlr, FifoPorts); - ctlr->txerrors++; - if((fifo & FifoTxEmpty) == 0){ - pkt = fifo & 0x3f; - pointtotxpacket(ctlr, pkt, PtrRead); - mmucommand(ctlr, McrFreeTx); - } - regw(ctlr, Interrupt, IntTx); - intr &= ~IntTx; - } - if(intr & IntTxEmpty){ - /* acknowledge and disable TX_EMPTY */ - regw(ctlr, Interrupt, IntTxEmpty); - mask &= ~IntTxEmpty; - intr &= ~IntTxEmpty; - } - if(intr) - panic("91c111: unhandled interrupts %.4ux\n", intr); - regw(ctlr, Interrupt, mask<ctlr; - ilock(ctlr); - bank = llregr(ctlr, BankSelect); - process(ether); - llregw(ctlr, BankSelect, bank); - ctlr->bank = bank; - iunlock(ctlr); -} - -#define MIIDELAY 5 - -static int -miimdi(Ctlr *ctlr, int n) -{ - int data, i; - - /* - * Read n bits from the MII Management Register. - */ - data = 0; - for(i = n - 1; i >= 0; i--){ - if(regr(ctlr, Mgmt) & MgmtMdi) - data |= (1 << i); - microdelay(MIIDELAY); - regw(ctlr, Mgmt, MgmtMclk); - microdelay(MIIDELAY); - regw(ctlr, Mgmt, 0); - microdelay(MIIDELAY); - } - - return data; -} - -static void -miimdo(Ctlr *ctlr, int bits, int n) -{ - int i, mdo; - - /* - * Write n bits to the MII Management Register. - */ - for(i = n - 1; i >= 0; i--){ - if(bits & (1 << i)) - mdo = MgmtMdoEn | MgmtMdo; - else - mdo = MgmtMdoEn; - regw(ctlr, Mgmt, mdo); - microdelay(MIIDELAY); - regw(ctlr, Mgmt, mdo | MgmtMclk); - microdelay(MIIDELAY); - regw(ctlr, Mgmt, mdo); - microdelay(MIIDELAY); - } -} - -static int -miir(Ctlr *ctlr, int regad) -{ - int data; - - /* - * Preamble; - * ST+OP+PHYAD+REGAD; - * TA + 16 data bits. - */ - miimdo(ctlr, 0xFFFFFFFF, 32); - miimdo(ctlr, 0x1800 | (ctlr->phyad << 5) | regad, 14); - data = miimdi(ctlr, 18); - regw(ctlr, Mgmt, 0); - microdelay(MIIDELAY); - - return data & 0xFFFF; -} - -static void -miiw(Ctlr* ctlr, int regad, int data) -{ - /* - * Preamble; - * ST+OP+PHYAD+REGAD+TA + 16 data bits; - * Z. - */ - miimdo(ctlr, 0xFFFFFFFF, 32); - data &= 0xFFFF; - data |= (0x05 << (5 + 5 + 2 + 16)) | (ctlr->phyad << (5 + 2 +16)) | (regad << (2 + 16)) | (0x02 << 16); - miimdo(ctlr, data, 32); - regw(ctlr, Mgmt, 0); - microdelay(MIIDELAY); -} - -static void -miinegostatus(Ctlr *ctlr, int *speed, int *full) -{ - int reg; - - switch(ctlr->type){ - case SMSC91C110: - reg = miir(ctlr, 25); - if((reg & (1<<4)) == 0) - break; - *speed = (reg & (1 << 5))? 100: 10; - *full = (reg & (1 << 6)) != 0; - return; - case SMSC91C111: - reg = miir(ctlr, 18); - *speed = (reg & (1 << 7))? 100: 10; - *full = (reg & (1 << 6)) != 0; - return; - } - *speed = 0; - *full = 0; -} - -void -dump111phyregs(Ctlr *ctlr) -{ - int x; - for(x = 0; x < 6; x++) - iprint("reg%d 0x%.4ux\n", x, miir(ctlr, x)); - for(x = 16; x <= 20; x++) - iprint("reg%d 0x%.4ux\n", x, miir(ctlr, x)); -} - -static void -miireset(Ctlr *ctlr) -{ - miiw(ctlr, 0, 0x8000); - while(miir(ctlr, 0) & 0x8000) - ; - delay(100); -} - -static int -miinegotiate(Ctlr *ctlr, int modes) -{ - ulong now, timeout; - int success; - int reg4; - - // Taken from TRM - don't argue - - miireset(ctlr); - miiw(ctlr, 0, 0); - regw(ctlr, Rpcr, 0x800 | (4 << 2)); - delay(50); - reg4 = miir(ctlr, 4); - reg4 &= ~(0x1f << 5); - reg4 |= ((modes & 0x1f) << 5); - miiw(ctlr, 4, reg4); - miir(ctlr, 18); // clear the status output so we can tell which bits got set... - miiw(ctlr, 0, 0x3300); - now = timer_start(); - timeout = ms2tmr(3000); - success = 0; - while(!success && (timer_start() - now) < timeout){ - ushort status; - status = miir(ctlr, 1); - if(status & (1 << 5)) - success = 1; - if(status & (1 << 4)){ - success = 0; - miiw(ctlr, 0, 0x3300); - } - } - return success; -} - -static int -ether91c111reset(Ether* ether) -{ - int i; - char *p; - uchar ea[Eaddrlen]; - Ctlr *ctlr; - ushort rev; - - if(ether->ctlr == nil){ - ether->ctlr = malloc(sizeof(Ctlr)); - if(ether->ctlr == nil) - return -1; - } - - ctlr = ether->ctlr; - ctlr->bank = -1; - - /* - * do architecture dependent intialisation - */ - adinit(ether); - - regw(ctlr, Rcr, RcrSoftRst); - regw(ctlr, Config, CfgEphPowerEn|CfgNoWait|Cfg16Bit); - delay(4*20); // rkw - (750us for eeprom alone)4x just to be ultra conservative 10 for linux. - regw(ctlr, Rcr, 0); // rkw - now remove reset and let the sig's fly. - regw(ctlr, Tcr, TcrSwfdup); - - regw(ctlr, Control, CtlAutoRelease | CtlTeEnable); - mmucommand(ctlr, McrReset); // rkw - reset the mmu - delay(5); - - /* - * Identify the chip by reading... - * 1) the bank select register - the top byte will be 0x33 - * 2) changing the bank to see if it reads back appropriately - * 3) check revision register for code 9 - */ - if((llregr(ctlr, BankSelect) >> 8) != 0x33){ - gopanic: - free(ctlr); - return -1; - } - - llregw(ctlr, BankSelect, 0xfffb); - if((llregr(ctlr, BankSelect) & 0xff07) != 0x3303) - goto gopanic; - - rev = regr(ctlr, Revision); - - if((rev >> 8) != 0x33) - goto gopanic; - - rev &= 0xff; - switch(rev){ - case 0x40: - /* 91c96 */ - ctlr->type = SMSC91C96; - ctlr->oddworks = 1; - break; - case 0x90: - ctlr->type = SMSC91C11x; - ctlr->hasmii = 1; - /* 91c110/9c111 */ - /* 91c111s are supposed to be revision one, but it's not the case */ - // See man page 112, revision history. rev not incremented till 08/01 - ctlr->oddworks = 0; // dont know if it works at this point - break; - case 0x91: - ctlr->type = SMSC91C111; - ctlr->hasmii = 1; - ctlr->oddworks = 1; - break; - default: - iprint("ether91c111: chip 0x%.1ux detected\n", rev); - goto gopanic; - } - - memset(ea, 0, sizeof(ea)); - if(memcmp(ether->ea, ea, Eaddrlen) == 0) - panic("ethernet address not set"); -#ifdef YYY - if((rev == 0x90) || (rev == 0x91)) // assuming no eeprom setup for these - panic("ethernet address not set in environment"); - for(i = 0; i < Eaddrlen; i += 2){ - ushort w; - w = regr(ctlr, Iaddr0_1 + i); - iprint("0x%.4ux\n", w); - ea[i] = w; - ea[i + 1] = w >> 8; - } - }else{ - for(i = 0; i < 6; i++){ - char buf[3]; - buf[0] = p[i * 2]; - buf[1] = p[i * 2 + 1]; - buf[2] = 0; - ea[i] = strtol(buf, 0, 16); - } - } - memmove(ether->ea, ea, Eaddrlen); -#endif - - /* - * set the local address - */ - for(i=0; iea[i] | (ether->ea[i+1] << 8)); - - /* - * initialise some registers - */ - regw(ctlr, Rcr, RcrRxEn | RcrAbortEnb | RcrStripCRC); // strip can now be used again - - if(rev == 0x90){ // its either a 110 or a 111 rev A at this point - int reg2, reg3; - /* - * how to tell the difference? - * the standard MII dev - */ - ctlr->phyad = PHYMIIADDR_91C110; - ctlr->type = SMSC91C110; - ctlr->oddworks = 1; // assume a 110 - reg2 = miir(ctlr, 2); // check if a 111 RevA - if(reg2 <= 0){ - ctlr->phyad = PHYMIIADDR_91C111; - ctlr->type = SMSC91C111; - reg2 = miir(ctlr, 2); - ctlr->oddworks = 0; // RevA - } - if(reg2 > 0){ - reg3 = miir(ctlr, 3); - iprint("reg2 0x%.4ux reg3 0x%.4ux\n", reg2, reg3); - } - else - panic("ether91c111: can't find phy on MII\n"); - } - - if(ctlr->type == SMSC91C110) - regor(ctlr, Config, CfgMiiSelect); - if(rev == 0x40){ - regor(ctlr, Config, CfgSetSqlch); - regclear(ctlr, Config, CfgAuiSelect); - regor(ctlr, Config, Cfg16Bit); - } - - if(ctlr->type == SMSC91C111){ - int modes; - char *ethermodes; - - miiw(ctlr, 0, 0x1000); /* clear MII_DIS and enable AUTO_NEG */ -// miiw(ctlr, 16, miir(ctlr, 16) | 0x8000); - // Rpcr set in INIT. - ethermodes=nil; /* was getconf("ethermodes"); */ - if(ethermodes == nil) - modes = 0xf; - else { - char *s; - char *args[10]; - int nargs; - int x; - - s = strdup(ethermodes); - if(s == nil) - panic("ether91c111reset: no memory for ethermodes"); - nargs = getfields(s, args, nelem(args), 1, ","); - modes = 0; - for(x = 0; x < nargs; x++){ - if(cistrcmp(args[x], "10HD") == 0) - modes |= 1; - else if(cistrcmp(args[x], "10FD") == 0) - modes |= 2; - else if(cistrcmp(args[x], "100HD") == 0) - modes |= 4; - else if(cistrcmp(args[x], "100FD") == 0) - modes |= 8; - } - free(s); - } - if(!miinegotiate(ctlr, modes)){ - iprint("ether91c111: negotiation timed out\n"); - return -1; - } - } - - if(ctlr->hasmii) - miinegostatus(ctlr, ðer->mbps, ðer->fullduplex); - else if(regr(ctlr, Eph) & EphLinkOk){ - ether->mbps = 10; - ether->fullduplex = 0; - } - else { - ether->mbps = 0; - ether->fullduplex = 0; - } - - if(ether->fullduplex && ctlr->type == SMSC91C110){ - // application note 79 - regor(ctlr, Tcr, TcrFduplx); - // application note 85 - adsetfd(ctlr); - } - - iprint("91c111 enabled: %dmbps %s\n", ether->mbps, ether->fullduplex ? "FDX" : "HDX"); - if(rev == 0x40){ - iprint("EcsrEcor 0x%.4ux\n", regr(ctlr, EcsrEcor)); - regor(ctlr, EcsrEcor, 1); - } - - /* - * Linkage to the generic ethernet driver. - */ - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - - return 0; -} - -void -ether91c111link(void) -{ - addethercard("91c111", ether91c111reset); -} -- cgit v1.2.3