diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
| commit | 78ee7d5717807e6ac779293d0d3c78341de6130a (patch) | |
| tree | a43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/mpc/etherscc.c | |
| parent | bdaf46cf45bbb59261da245d548a179d95a42768 (diff) | |
Move existing boards into subdits split per arch
Diffstat (limited to 'os/mpc/etherscc.c')
| -rw-r--r-- | os/mpc/etherscc.c | 528 |
1 files changed, 0 insertions, 528 deletions
diff --git a/os/mpc/etherscc.c b/os/mpc/etherscc.c deleted file mode 100644 index 8180140e..00000000 --- a/os/mpc/etherscc.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * SCCn ethernet - */ - -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" -#include "../port/netif.h" - -#include "etherif.h" - -enum { - Nrdre = 16, /* receive descriptor ring entries */ - Ntdre = 16, /* transmit descriptor ring entries */ - - Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */ - Bufsize = (Rbsize+7)&~7, /* aligned */ -}; - -enum { - /* ether-specific Rx BD bits */ - RxMiss= 1<<8, - RxeLG= 1<<5, - RxeNO= 1<<4, - RxeSH= 1<<3, - RxeCR= 1<<2, - RxeOV= 1<<1, - RxeCL= 1<<0, - RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */ - - /* ether-specific Tx BD bits */ - TxPad= 1<<14, /* pad short frames */ - TxTC= 1<<10, /* transmit CRC */ - TxeDEF= 1<<9, - TxeHB= 1<<8, - TxeLC= 1<<7, - TxeRL= 1<<6, - TxeUN= 1<<1, - TxeCSL= 1<<0, - - /* scce */ - RXB= 1<<0, - TXB= 1<<1, - BSY= 1<<2, - RXF= 1<<3, - TXE= 1<<4, - - /* psmr */ - PRO= 1<<9, /* promiscuous mode */ - - /* gsmrl */ - ENR= 1<<5, - ENT= 1<<4, - - /* port A */ - RXD1= SIBIT(15), - TXD1= SIBIT(14), - - /* port B */ - RTS1= IBIT(19), - - /* port C */ - CTS1= SIBIT(11), - CD1= SIBIT(10), -}; - -typedef struct Etherparam Etherparam; -struct Etherparam { - SCCparam; - ulong c_pres; /* preset CRC */ - ulong c_mask; /* constant mask for CRC */ - ulong crcec; /* CRC error counter */ - ulong alec; /* alighnment error counter */ - ulong disfc; /* discard frame counter */ - ushort pads; /* short frame PAD characters */ - ushort ret_lim; /* retry limit threshold */ - ushort ret_cnt; /* retry limit counter */ - ushort mflr; /* maximum frame length reg */ - ushort minflr; /* minimum frame length reg */ - ushort maxd1; /* maximum DMA1 length reg */ - ushort maxd2; /* maximum DMA2 length reg */ - ushort maxd; /* rx max DMA */ - ushort dma_cnt; /* rx dma counter */ - ushort max_b; /* max bd byte count */ - ushort gaddr[4]; /* group address filter */ - ulong tbuf0_data0; /* save area 0 - current frm */ - ulong tbuf0_data1; /* save area 1 - current frm */ - ulong tbuf0_rba0; - ulong tbuf0_crc; - ushort tbuf0_bcnt; - ushort paddr[3]; /* physical address LSB to MSB increasing */ - ushort p_per; /* persistence */ - ushort rfbd_ptr; /* rx first bd pointer */ - ushort tfbd_ptr; /* tx first bd pointer */ - ushort tlbd_ptr; /* tx last bd pointer */ - ulong tbuf1_data0; /* save area 0 - next frame */ - ulong tbuf1_data1; /* save area 1 - next frame */ - ulong tbuf1_rba0; - ulong tbuf1_crc; - ushort tbuf1_bcnt; - ushort tx_len; /* tx frame length counter */ - ushort iaddr[4]; /* individual address filter*/ - ushort boff_cnt; /* back-off counter */ - ushort taddr[3]; /* temp address */ -}; - -typedef struct { - Lock; - int port; - int init; - int active; - SCC* scc; - CPMdev* cpm; - - Ring; - - ulong interrupts; /* statistics */ - ulong deferred; - ulong heartbeat; - ulong latecoll; - ulong retrylim; - ulong underrun; - ulong overrun; - ulong carrierlost; - ulong retrycount; -} Ctlr; - -static int sccid[] = {-1, CPscc1, CPscc2, CPscc3, CPscc4}; - -static void -attach(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ctlr->active = 1; - ctlr->scc->gsmrl |= ENR|ENT; - eieio(); -} - -static void -closed(Ether *ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - if(ctlr->active){ - sccxstop(ctlr->cpm); - ilock(ctlr); - ctlr->active = 0; - iunlock(ctlr); - } -} - -static void -promiscuous(void* arg, int on) -{ - Ether *ether; - Ctlr *ctlr; - - ether = (Ether*)arg; - ctlr = ether->ctlr; - - ilock(ctlr); - if(on || ether->nmaddr) - ctlr->scc->psmr |= PRO; - else - ctlr->scc->psmr &= ~PRO; - iunlock(ctlr); -} - -static void -multicast(void* arg, uchar *addr, int on) -{ - Ether *ether; - Ctlr *ctlr; - - USED(addr, on); /* if on, could SetGroupAddress; if !on, it's hard */ - - ether = (Ether*)arg; - ctlr = ether->ctlr; - - ilock(ctlr); - if(ether->prom || ether->nmaddr) - ctlr->scc->psmr |= PRO; - else - ctlr->scc->psmr &= ~PRO; - iunlock(ctlr); -} - -static void -txstart(Ether *ether) -{ - int len; - Ctlr *ctlr; - Block *b; - BD *dre; - - ctlr = ether->ctlr; - while(ctlr->ntq < Ntdre-1){ - b = qget(ether->oq); - if(b == 0) - break; - - dre = &ctlr->tdr[ctlr->tdrh]; - if(dre->status & BDReady) - panic("ether: txstart"); - - /* - * Give ownership of the descriptor to the chip, increment the - * software ring descriptor pointer and tell the chip to poll. - */ - len = BLEN(b); - dcflush(b->rp, len); - if(ctlr->txb[ctlr->tdrh] != nil) - panic("scc/ether: txstart"); - ctlr->txb[ctlr->tdrh] = b; - if((ulong)b->rp&1) - panic("scc/ether: txstart align"); /* TO DO: ensure alignment */ - dre->addr = PADDR(b->rp); - dre->length = len; - eieio(); - dre->status = (dre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC; - eieio(); - ctlr->scc->todr = 1<<15; /* transmit now */ - eieio(); - ctlr->ntq++; - ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); - } -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(ctlr); - txstart(ether); - iunlock(ctlr); -} - -static void -interrupt(Ureg*, void *arg) -{ - Ether *ether; - int len, events, status; - Ctlr *ctlr; - BD *dre; - Block *b; - - ether = arg; - ctlr = ether->ctlr; - if(!ctlr->active) - return; /* not ours */ - - /* - * Acknowledge all interrupts and whine about those that shouldn't - * happen. - */ - events = ctlr->scc->scce; - eieio(); - ctlr->scc->scce = events; - eieio(); - ctlr->interrupts++; - - if(events & (TXE|BSY|RXB)){ - if(events & RXB) - ctlr->overrun++; - if(events & TXE) - ether->oerrs++; - if(0 || events & TXE) - print("ETHER.SCC#%d: scce = 0x%uX\n", ether->ctlrno, events); - } - /* - * Receiver interrupt: run round the descriptor ring logging - * errors and passing valid receive data up to the higher levels - * until we encounter a descriptor still owned by the chip. - */ - if(events & (RXF|RXB) || 1){ - dre = &ctlr->rdr[ctlr->rdrx]; - while(((status = dre->status) & BDEmpty) == 0){ - if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){ - if(status & (RxeLG|RxeSH)) - ether->buffs++; - if(status & RxeNO) - ether->frames++; - if(status & RxeCR) - ether->crcs++; - if(status & RxeOV) - ether->overflows++; - //print("eth rx: %ux\n", status); - } - else{ - /* - * We have a packet. Read it in. - */ - len = dre->length-4; - if((b = iallocb(len)) != 0){ - dcinval(KADDR(dre->addr), len); - memmove(b->wp, KADDR(dre->addr), len); - b->wp += len; - etheriq(ether, b, 1); - }else - ether->soverflows++; - } - - /* - * Finished with this descriptor, reinitialise it, - * give it back to the chip, then on to the next... - */ - dre->length = 0; - dre->status = (status & BDWrap) | BDEmpty | BDInt; - eieio(); - - ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); - dre = &ctlr->rdr[ctlr->rdrx]; - } - } - - /* - * Transmitter interrupt: handle anything queued for a free descriptor. - */ - if(events & TXB){ - lock(ctlr); - while(ctlr->ntq){ - dre = &ctlr->tdr[ctlr->tdri]; - status = dre->status; - if(status & BDReady) - break; - if(status & TxeDEF) - ctlr->deferred++; - if(status & TxeHB) - ctlr->heartbeat++; - if(status & TxeLC) - ctlr->latecoll++; - if(status & TxeRL) - ctlr->retrylim++; - if(status & TxeUN) - ctlr->underrun++; - if(status & TxeCSL) - ctlr->carrierlost++; - ctlr->retrycount += (status>>2)&0xF; - b = ctlr->txb[ctlr->tdri]; - if(b == nil) - panic("scce/interrupt: bufp"); - ctlr->txb[ctlr->tdri] = nil; - freeb(b); - ctlr->ntq--; - ctlr->tdri = NEXT(ctlr->tdri, Ntdre); - } - txstart(ether); - unlock(ctlr); - } - if(events & TXE) - cpmop(ctlr->cpm, RestartTx, 0); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - char *p; - int len; - Ctlr *ctlr; - - if(n == 0) - return 0; - - ctlr = ether->ctlr; - - p = malloc(READSTR); - len = snprint(p, READSTR, "interrupts: %lud\n", ctlr->interrupts); - len += snprint(p+len, READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost); - len += snprint(p+len, READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat); - len += snprint(p+len, READSTR-len, "retrylimit: %lud\n", ctlr->retrylim); - len += snprint(p+len, READSTR-len, "retrycount: %lud\n", ctlr->retrycount); - len += snprint(p+len, READSTR-len, "latecollisions: %lud\n", ctlr->latecoll); - len += snprint(p+len, READSTR-len, "rxoverruns: %lud\n", ctlr->overrun); - len += snprint(p+len, READSTR-len, "txunderruns: %lud\n", ctlr->underrun); - snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->deferred); - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -/* - * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence, - * except that it sets the right bits for the MPC823ADS board when SCC2 is used, - * and those for the 860/821 development board for SCC1. - */ -static void -sccsetup(Ctlr *ctlr, SCC *scc, Ether *ether) -{ - int i, rcs, tcs, w; - Etherparam *p; - IMM *io; - - - i = 2*(ctlr->port-1); - io = ioplock(); - w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */ - io->papar |= w; /* enable TXDn and RXDn pins */ - io->padir &= ~w; - io->paodr &= ~w; /* not open drain */ - - w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */ - io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */ - io->pcdir &= ~w; - io->pcso |= w; - iopunlock(); - - /* clocks and transceiver control: details depend on the board's wiring */ - archetherenable(sccid[ctlr->port], &rcs, &tcs, ether->mbps, ether->fullduplex); - - sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */ - - p = ctlr->cpm->param; - memset(p, 0, sizeof(*p)); - p->rfcr = 0x18; - p->tfcr = 0x18; - p->mrblr = Bufsize; - p->rbase = PADDR(ctlr->rdr); - p->tbase = PADDR(ctlr->tdr); - - cpmop(ctlr->cpm, InitRxTx, 0); - - p->c_pres = ~0; - p->c_mask = 0xDEBB20E3; - p->crcec = 0; - p->alec = 0; - p->disfc = 0; - p->pads = 0x8888; - p->ret_lim = 0xF; - p->mflr = Rbsize; - p->minflr = ETHERMINTU+4; - p->maxd1 = Bufsize; - p->maxd2 = Bufsize; - p->p_per = 0; /* only moderate aggression */ - - for(i=0; i<Eaddrlen; i+=2) - p->paddr[2-i/2] = (ether->ea[i+1]<<8)|ether->ea[i]; /* it's not the obvious byte order */ - - scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */ - scc->dsr = 0xd555; - scc->gsmrh = 0; /* normal operation */ - scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */ - eieio(); - scc->scce = ~0; /* clear all events */ - eieio(); - scc->sccm = TXE | RXF | TXB; /* enable interrupts */ - eieio(); - - io = ioplock(); - w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */ - io->pbpar |= w; - io->pbdir |= w; - iopunlock(); - - /* gsmrl enable is deferred until attach */ -} - -static int -reset(Ether* ether) -{ - uchar ea[Eaddrlen]; - CPMdev *cpm; - Ctlr *ctlr; - SCC *scc; - - if(m->speed < 24){ - print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type); - return -1; - } - - if(!(ether->port >= 1 && ether->port <= 4)){ - print("%s ether: no SCC port %lud\n", ether->type, ether->port); - return -1; - } - - /* - * Insist that the platform-specific code provide the Ethernet address - */ - memset(ea, 0, Eaddrlen); - if(memcmp(ea, ether->ea, Eaddrlen) == 0){ - print("no ether address"); - return -1; - } - - cpm = cpmdev(sccid[ether->port]); - if(cpm == nil) - return -1; - ether->irq = VectorCPIC + cpm->irq; - scc = cpm->regs; - ctlr = malloc(sizeof(*ctlr)); - ether->ctlr = ctlr; - memset(ctlr, 0, sizeof(*ctlr)); - ctlr->cpm = cpm; - ctlr->scc = scc; - ctlr->port = ether->port; - - if(ioringinit(ctlr, Nrdre, Ntdre, Bufsize) < 0) - panic("etherscc init"); - - sccsetup(ctlr, scc, ether); - - ether->attach = attach; - ether->closed = closed; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - ether->multicast = multicast; - - return 0; -} - -void -etherscclink(void) -{ - addethercard("SCC", reset); -} |
