From a49cf8bda50e1d0720798bcaf0606fb2141c4e05 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 22 Jan 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-01-22 --- mpc/clock.c | 4 +- mpc/cpm.c | 12 +- mpc/dat.h | 2 +- mpc/devrtc.c | 4 +- mpc/devuart.c | 1438 ++++++++++++++++++++++++++++++++++++++++++++++++ mpc/etherscc.c | 552 +++++++++++++++++++ mpc/fns.h | 2 + mpc/l.s | 13 +- mpc/main.c | 59 ++ mpc/mem.h | 5 + mpc/trap.c | 13 + port/chan.c | 4 +- port/dev.c | 4 +- port/devenv.c | 60 +- port/devsrv.c | 60 +- port/error.h | 1 + port/portdat.h | 5 +- port/portfns.h | 3 - port/sysfile.c | 2 - 19 files changed, 2167 insertions(+), 76 deletions(-) create mode 100644 mpc/devuart.c create mode 100644 mpc/etherscc.c diff --git a/mpc/clock.c b/mpc/clock.c index a4102af6f3cf8bd90a6f114304591fa510dbc32e..1beabcc2b724d9c0cec39d3571867673fbb54ec4 100644 --- a/mpc/clock.c +++ b/mpc/clock.c @@ -106,8 +106,8 @@ clockintr(Ureg *ur) putdec(clkreload-v); m->ticks++; - if(m->ticks%MS2TK(1000) == 0) - m->bcsr[4] ^= DisableLamp; +// if(m->ticks%MS2TK(1000) == 0) +// m->bcsr[4] ^= DisableLamp; if(up) up->pc = ur->pc; diff --git a/mpc/cpm.c b/mpc/cpm.c index bbb94097447a0582371de8523500200de784e360..12d3468fc0c1eb6548cca452266700d965b525b1 100644 --- a/mpc/cpm.c +++ b/mpc/cpm.c @@ -45,7 +45,7 @@ cpminit(void) io = m->iomem; io->rccr = 0; io->rmds = 0; - io->lccr &= ~1; /* disable LCD */ +// io->lccr &= ~1; /* disable LCD */ io->sdcr = 1; io->pcint = 0; /* disable all port C interrupts */ io->pcso = 0; @@ -145,7 +145,7 @@ scc2claim(int force, ulong enable, void (*stop)(void*), void *arg) clash = scc2owner.clash & ~enable; ilock(&scc2owner); - if(~m->bcsr[1] & clash){ + if(/* ~m->bcsr[1] & clash */ 0){ if(!force){ iunlock(&scc2owner); return 0; @@ -153,12 +153,12 @@ scc2claim(int force, ulong enable, void (*stop)(void*), void *arg) /* notify current owner */ if(scc2owner.stop) scc2owner.stop(scc2owner.arg); - m->bcsr[1] |= clash; +// m->bcsr[1] |= clash; } scc2owner.stop = stop; scc2owner.arg = arg; scc2owner.active = enable; - m->bcsr[1] &= ~enable; /* the bits are active low */ +// m->bcsr[1] &= ~enable; /* the bits are active low */ iunlock(&scc2owner); /* beware: someone else can claim it during the `successful' return */ return 1; @@ -178,7 +178,7 @@ scc2stop(void *a) cpmop(CloseRxBD, SCC2ID, 0); delay(1); scc->gsmrl &= ~(3<<4); /* disable current use */ - m->bcsr[1] |= scc2owner.clash; +// m->bcsr[1] |= scc2owner.clash; } } @@ -189,7 +189,7 @@ void scc2free(void) { ilock(&scc2owner); - m->bcsr[1] |= scc2owner.active; +// m->bcsr[1] |= scc2owner.active; scc2owner.active = 0; iunlock(&scc2owner); } diff --git a/mpc/dat.h b/mpc/dat.h index 0e92ca92fc5eb9ee33d8a30dc85bd54c84df69ad..ecc5ced40f52ac4ba563898387cd5596d5a4480c 100644 --- a/mpc/dat.h +++ b/mpc/dat.h @@ -126,7 +126,7 @@ struct Mach long clockgen; /* clock generator frequency (cycles) */ int cputype; ulong delayloop; - ulong* bcsr; +// ulong* bcsr; IMM* iomem; /* MPC8xx internal i/o control memory */ ulong fairness; /* for runproc */ diff --git a/mpc/devrtc.c b/mpc/devrtc.c index 0850eb97cb572194996524d3f0fc465d1ca2fa83..f03d026bcfbb9e5f54d3448151d11f8a38ff67a0 100644 --- a/mpc/devrtc.c +++ b/mpc/devrtc.c @@ -97,7 +97,7 @@ static long rtcread(Chan *c, void *buf, long n, vlong offset) { ulong t; - char *b; +// char *b; if(c->qid.path & CHDIR) return devdirread(c, buf, n, rtcdir, NRTC, devgen); @@ -108,7 +108,7 @@ rtcread(Chan *c, void *buf, long n, vlong offset) n = readnum(offset, buf, n, t, 12); return n; case Qswitch: - return readnum(offset, buf, n, (m->bcsr[2]>>19)&0xF, 12); + return readnum(offset, buf, n, 0xf/*(m->bcsr[2]>>19)&0xF*/, 12); } error(Egreg); return 0; /* not reached */ diff --git a/mpc/devuart.c b/mpc/devuart.c new file mode 100644 index 0000000000000000000000000000000000000000..e58d71878b2e44671a775c65dae5128d1d5190b1 --- /dev/null +++ b/mpc/devuart.c @@ -0,0 +1,1438 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#include "../port/netif.h" + +enum { + FADS823 = 1, + + Rbufsize= 512, + Nuart= 3, /* max per machine (SMC1, SMC2, SCC2) */ + CTLS= 's'&037, + CTLQ= 'q'&037, +}; + +enum { + /* status bits in SCC receive buffer descriptors */ + RxBRK= 1<<7, /* break ended frame (async hdlc) */ + RxDE= 1<<7, /* DPLL error (hdlc) */ + RxBOF= 1<<6, /* BOF ended frame (async hdlc) */ + RxLG= 1<<5, /* frame too large (hdlc) */ + RxNO= 1<<4, /* bad bit alignment (hdlc) */ + RxBR= 1<<5, /* break received during frame (uart) */ + RxFR= 1<<4, /* framing error (uart) */ + RxPR= 1<<3, /* parity error (uart) */ + RxAB= 1<<3, /* frame aborted (hdlc, async hdlc) */ + RxCR= 1<<2, /* bad CRC (hdlc, async hdlc) */ + RxOV= 1<<1, /* receiver overrun (all) */ + RxCD= 1<<0, /* CD lost (all) */ + + /* hdlc-specific Rx/Tx BDs */ + TxTC= 1<<10, +}; + +/* + * SMC in UART mode + */ +enum { + USESMC2 = 0 +}; + +typedef struct Uartsmc Uartsmc; +struct Uartsmc { + IOCparam; + ushort maxidl; + ushort idlc; + ushort brkln; + ushort brkec; + ushort brkcr; + ushort rmask; +}; + +/* + * SCC2 UART parameters + */ +enum { + USESCC2 = 0, + + /* special mode bits */ + SccAHDLC = 1<<0, + SccHDLC = 1<<1, + SccIR = 1<<2, + SccPPP = 1<<3, +}; + +typedef struct Uartscc Uartscc; +struct Uartscc { + SCCparam; + uchar rsvd[8]; + ushort max_idl; + ushort idlc; + ushort brkcr; + ushort parec; + ushort frmec; + ushort nosec; + ushort brkec; + ushort brkln; + ushort uaddr1; + ushort uaddr2; + ushort rtemp; + ushort toseq; + ushort character[8]; + ushort rccm; + ushort rccrp; + ushort rlbc; +}; + +typedef struct UartAHDLC UartAHDLC; +struct UartAHDLC { + SCCparam; + ulong rsvd1; + ulong c_mask; + ulong c_pres; + ushort bof; + ushort eof; + ushort esc; + ushort rsvd2[2]; + ushort zero; + ushort rsvd3; + ushort rfthr; + ushort resvd4[2]; + ulong txctl_tbl; + ulong rxctl_tbl; + ushort nof; + ushort rsvd5; +}; + +typedef struct UartHDLC UartHDLC; +struct UartHDLC { + SCCparam; + ulong rsvd1; + ulong c_mask; + ulong c_pres; + ushort disfc; + ushort crcec; + ushort abtsc; + ushort nmarc; + ushort retrc; + ushort mflr; + ushort max_cnt; + ushort rfthr; + ushort rfcnt; + ushort hmask; + ushort haddr[4]; + ushort tmp; + ushort tmp_mb; +}; + +enum { + /* SCC events of possible interest here eventually */ + AB= 1<<9, /* autobaud detected */ + GRA= 1<<7, /* graceful stop completed */ + CCR= 1<<3, /* control character detected */ + + /* SCC, SMC common interrupt events */ + BSY= 1<<2, /* receive buffer was busy (overrun) */ + TXB= 1<<1, /* block sent */ + RXB= 1<<0, /* block received */ + + /* SCC events */ + TXE = 1<<4, /* transmission error */ + RXF = 1<<3, /* final block received */ + + /* gsmr_l */ + ENR = 2<<4, /* enable receiver */ + ENT = 1<<4, /* enable transmitter */ +}; + +typedef struct Uart Uart; +struct Uart +{ + QLock; + + Uart *elist; /* next enabled interface */ + char name[NAMELEN]; + + int x; /* index: x in SMCx or SCCx */ + int cpmid; /* eg, SCC1ID, SMC1ID */ + int opens; + uchar bpc; /* bits/char */ + uchar parity; + uchar stopb; + uchar setup; + uchar enabled; + int dev; + + ulong frame; /* framing errors */ + ulong perror; + ulong overrun; /* rcvr overruns */ + ulong crcerr; + ulong interrupts; + int baud; /* baud rate */ + + /* flow control */ + int xonoff; /* software flow control on */ + int blocked; + int modem; /* hardware flow control on */ + int cts; /* ... cts state */ + int rts; /* ... rts state */ + Rendez r; + + /* buffers */ + int (*putc)(Queue*, int); + Queue *iq; + Queue *oq; + + /* staging areas to avoid some of the per character costs */ + uchar istage[Rbufsize][2]; /* double buffered */ + int rdrx; /* last buffer read */ + + Lock plock; /* for output variables */ + Block* outb; /* currently transmitting Block */ + + BD* rxb; + BD* txb; + + SMC* smc; + SCC* scc; + IOCparam* param; + ushort* brkcr; /* brkcr location in appropriate block */ + int brgc; + int mode; + Block* partial; + int loopback; +}; + +static Uart *uart[Nuart]; +static int nuart; + +struct Uartalloc { + Lock; + Uart *elist; /* list of enabled interfaces */ +} uartalloc; + +static void uartintr(Uart*, int); +static void smcuintr(Ureg*, void*); +static void sccuintr(Ureg*, void*); + +static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B}; +static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID}; +static int sccbase[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60}; +static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P}; + +static void +uartsetbuf(Uart *up) +{ + IOCparam *p; + BD *bd; + + p = up->param; + p->rfcr = 0x18; + p->tfcr = 0x18; + p->mrblr = Rbufsize; + + if((bd = up->rxb) == nil){ + bd = bdalloc(2); + up->rxb = bd; + } + p->rbase = (ushort)bd; + bd->status = BDEmpty|BDInt; + bd->length = 0; + bd->addr = PADDR(up->istage[0]); + bd++; + bd->status = BDEmpty|BDInt|BDWrap; + bd->length = 0; + bd->addr = PADDR(up->istage[1]); + dcflush(up->istage, sizeof(up->istage)); + up->rdrx = 0; + + if((bd = up->txb) == nil){ + bd = bdalloc(1); + up->txb = bd; + } + p->tbase = (ushort)bd; + bd->status = BDWrap|BDInt; + bd->length = 0; + bd->addr = 0; +} + +static void +smcsetup(Uart *up) +{ + IMM *io; + Uartsmc *p; + SMC *smc; + + up->brgc = brgalloc(); + if(up->brgc < 0) + error(Eio); +// m->bcsr[1] &= ~DisableRS232a; /* enable rs232-1 */ + + io = ioplock(); + io->pbpar |= IBIT(23)|IBIT(24)|IBIT(25); /* enable SMC1 TX/RX/SYN */ + io->pbdir &= ~(IBIT(23)|IBIT(24)|IBIT(25)); + io->brgc[up->brgc] = baudgen(up->baud, 16) | BaudEnable; + io->simode = (io->simode & ~0xF000) | (up->brgc<<12); /* SMC1 to NMSI mode, set Tx/Rx clock */ + iopunlock(); + + up->param = KADDR(SMC1P); + uartsetbuf(up); + + cpmop(InitRxTx, SMC1ID, 0); + + /* SMC protocol parameters */ + p = (Uartsmc*)up->param; + up->brkcr = &p->brkcr; + p->maxidl = 1; + p->brkln = 0; + p->brkec = 0; + p->brkcr = 1; + smc = IOREGS(0xA80, SMC); + smc->smce = 0xff; /* clear events */ + smc->smcm = BSY|RXB|TXB; /* enable all possible interrupts */ + up->smc = smc; + smc->smcmr = ((1+8+1-1)<<11)|(2<<4); /* 8-bit, 1 stop, no parity; UART mode */ +// intrenable(VectorCPIC+4, smcuintr, up, BUSUNKNOWN); + smc->smcmr |= 3; /* enable rx/tx */ +} + +static void +smcuintr(Ureg*, void *a) +{ + Uart *up; + int events; + + up = a; + events = up->smc->smce; + eieio(); + up->smc->smce = events; + uartintr(up, events&(BSY|RXB|TXB)); +} + +static void +sccustop(void *a) +{ + Uart *up; + + up = a; + if(up->setup){ + scc2stop(up->scc); + brgfree(up->brgc); + up->brgc = -1; + up->setup = 0; + } +} + +static void +sccsetup(Uart *up) +{ + IMM *io; + SCC *scc; + ulong bg; + int i; + + scc = IOREGS(sccbase[up->x], SCC); + if(up->x == 2){ /* BUG: 823FADS-specific */ + if(scc->gsmrl & (ENT|ENR)) + scc2stop(scc); + scc->gsmrl &= ~(ENT|ENR); + scc2claim(1, up->mode&SccIR? DisableIR: DisableRS232b, sccustop, scc); + } + up->scc = scc; + if(up->brgc < 0){ + up->brgc = brgalloc(); + if(up->brgc < 0) + error(Eio); + } + bg = baudgen(up->baud, 16) | BaudEnable; + + io = ioplock(); + io->papar |= SIBIT(12)|SIBIT(13); /* enable TXD2 and RXD2 pins */ + io->padir &= ~(SIBIT(12)|SIBIT(13)); + if((up->mode & SccIR) == 0) + io->paodr |= SIBIT(12); /* TO DO: is this right? */ + else + io->paodr &= ~(SIBIT(12)|SIBIT(13)); /* TO DO: is this right? */ + + io->pbpar &= ~IBIT(18); /* disable RTS2 */ + io->pbdir &= ~IBIT(18); + if((up->mode&SccIR) == 0) + io->pcpar |= SIBIT(14); /* RTS2~ */ + else + io->pcpar &= ~SIBIT(14); + io->pcpar &= ~(SIBIT(9)|SIBIT(8)); /* CTS2~ and CD2~ */ + io->pcdir &= ~(SIBIT(14)|SIBIT(9)|SIBIT(8)); + if(FADS823 || up->mode) + io->pcso &= ~(SIBIT(9)|SIBIT(8)); /* 82xFADS: force CTS and CD on */ + else + io->pcso |= SIBIT(9)|SIBIT(8); + eieio(); + + io->brgc[up->brgc] = bg; + iopunlock(); + + sccnmsi(2, up->brgc, up->brgc); + + up->param = KADDR(sccparam[up->x]); + uartsetbuf(up); + + cpmop(InitRxTx, up->cpmid, 0); + + /* SCC protocol parameters */ + if((up->mode & (SccAHDLC|SccHDLC)) == 0){ + Uartscc *sp; + sp = (Uartscc*)up->param; + sp->max_idl = 1; + sp->brkcr = 1; + sp->parec = 0; + sp->frmec = 0; + sp->nosec = 0; + sp->brkec = 0; + sp->brkln = 0; + sp->brkec = 0; + sp->uaddr1 = 0; + sp->uaddr2 = 0; + sp->toseq = 0; + for(i=0; i<8; i++) + sp->character[i] = 0x8000; + sp->rccm = 0xC0FF; + up->brkcr = &sp->brkcr; + scc->irmode = 0; + scc->dsr = ~0; + scc->gsmrh = 1<<5; /* 8-bit oriented receive fifo */ + scc->gsmrl = 0x28004; /* UART mode */ + }else{ + UartAHDLC *hp; + hp = (UartAHDLC*)up->param; + hp->c_mask = 0x0000F0B8; + hp->c_pres = 0x0000FFFF; + if(up->mode & SccIR){ + hp->bof = 0xC0; + hp->eof = 0xC1; + //scc->dsr = 0xC0C0; + scc->dsr = 0x7E7E; + }else{ + hp->bof = 0x7E; + hp->eof = 0x7E; + scc->dsr = 0x7E7E; + } + hp->esc = 0x7D; + hp->zero = 0; + if(up->mode & SccHDLC) + hp->rfthr = 1; + else + hp->rfthr = 0; /* receive threshold of 1 doesn't work properly for Async HDLC */ + hp->txctl_tbl = 0; + hp->rxctl_tbl = 0; + if(up->mode & SccIR){ + /* low-speed infrared */ + hp->nof = 12-1; /* 12 flags */ + scc->irsip = 0; + scc->irmode = (2<<8) | 1; +// m->bcsr[1] |= DisableIR; +// microdelay(2); +// m->bcsr[1] &= ~DisableIR; /* put TFDS6000 xcvr in low-speed mode (see 4.9.2.1 in FADS manual) */ + if(up->loopback) + scc->irmode = (3<<4)|1; /* loopback */ + }else{ + scc->irmode = 0; + hp->txctl_tbl = ~0; + hp->rxctl_tbl = ~0; + hp->nof = 1-1; /* one opening flag */ + } + up->brkcr = nil; + scc->gsmrh = 1<<5; /* 8-bit oriented receive fifo */ + if(up->mode & SccHDLC) + scc->gsmrl = 0x28000; /* HDLC */ + else + scc->gsmrl = 0x28006; /* async HDLC/IrDA */ + } + scc->scce = ~0; /* clear events */ + scc->sccm = TXE|BSY|RXF|TXB|RXB; /* enable all interesting interrupts */ + intrenable(VectorCPIC+sccirq[up->x], sccuintr, up, BUSUNKNOWN); + scc->psmr = 3<<12; /* 8-bit, 1 stop, no parity; UART mode */ + if(up->loopback && (up->mode & SccIR) == 0) + scc->gsmrl |= 1<<6; /* internal loop back */ + scc->gsmrl |= ENT|ENR; /* enable rx/tx */ + if(0){ + print("gsmrl=%8.8lux gsmrh=%8.8lux dsr=%4.4ux irmode=%4.4ux\n", scc->gsmrl, scc->gsmrh, scc->dsr, scc->irmode); + for(i=0; iparam+i)); + } +} + +static void +sccuintr(Ureg*, void *a) +{ + Uart *up; + int events; + + up = a; + if(/*(m->bcsr[1] & (DisableRS232b|DisableIR)) == (DisableRS232b|DisableIR) ||*/ up->scc == nil) + return; + events = up->scc->scce; + eieio(); + up->scc->scce = events; + if(up->enabled){ + if(0) + print("#%ux|", events); + uartintr(up, events); + } +} + +static void +uartsetbaud(Uart *p, int rate) +{ + if(rate <= 0 || p->brgc < 0) + return; + p->baud = rate; + m->iomem->brgc[p->brgc] = baudgen(rate, 16) | BaudEnable; +} + +static void +uartsetmode(Uart *p) +{ + int r, clen; + + ilock(&p->plock); + clen = p->bpc; + if(p->parity == 'e' || p->parity == 'o') + clen++; + clen++; /* stop bit */ + if(p->stopb == 2) + clen++; + if(p->smc){ + r = p->smc->smcmr & 0x3F; /* keep mode, enable bits */ + r |= (clen<<11); + if(p->parity == 'e') + r |= 3<<8; + else if(p->parity == 'o') + r |= 2<<8; + if(p->stopb == 2) + r |= 1<<10; + eieio(); + p->smc->smcmr = r; + }else if(p->scc && p->mode == 0){ + r = p->scc->psmr & 0x8FE0; /* keep mode bits */ + r |= ((p->bpc-5)&3)<<12; + if(p->parity == 'e') + r |= (6<<2)|2; + else if(p->parity == 'o') + r |= (4<<2)|0; + if(p->stopb == 2) + r |= 1<<14; + eieio(); + p->scc->psmr = r; + } + iunlock(&p->plock); +} + +static void +uartparity(Uart *p, char type) +{ + ilock(&p->plock); + p->parity = type; + iunlock(&p->plock); + uartsetmode(p); +} + +/* + * set bits/character + */ +static void +uartbits(Uart *p, int bits) +{ + if(bits < 5 || bits > 14 || bits > 8 && p->scc) + error(Ebadarg); + + ilock(&p->plock); + p->bpc = bits; + iunlock(&p->plock); + uartsetmode(p); +} + + +/* + * toggle DTR + */ +static void +uartdtr(Uart *p, int n) +{ + if(p->scc == nil) + return; /* not possible */ + USED(n); /* not possible on FADS */ +} + +/* + * toggle RTS + */ +static void +uartrts(Uart *p, int n) +{ + p->rts = n; + if(p->scc == nil) + return; /* not possible */ + USED(n); /* not possible on FADS */ +} + +/* + * send break + */ +static void +uartbreak(Uart *p, int ms) +{ + if(p->brkcr == nil) + return; + + if(ms <= 0) + ms = 200; + + if(waserror()){ + ilock(&p->plock); + *p->brkcr = 1; + cpmop(RestartTx, p->cpmid, 0); + iunlock(&p->plock); + nexterror(); + } + ilock(&p->plock); + *p->brkcr = ((p->baud/(p->bpc+2))*ms+500)/1000; + cpmop(StopTx, p->cpmid, 0); + iunlock(&p->plock); + + tsleep(&up->sleep, return0, 0, ms); + + poperror(); + ilock(&p->plock); + *p->brkcr = 1; + cpmop(RestartTx, p->cpmid, 0); + iunlock(&p->plock); +} + +/* + * modem flow control on/off (rts/cts) + */ +static void +uartmflow(Uart *p, int n) +{ + if(p->scc == nil) + return; /* not possible */ + if(n){ + p->modem = 1; + /* enable status interrupts ... */ + p->scc->psmr |= 1<<15; /* enable async flow control */ + p->cts = 1; + /* could change maxidl */ + }else{ + p->modem = 0; + /* stop status interrupts ... */ + p->scc->psmr &= ~(1<<15); + p->cts = 1; + } +} + +/* + * turn on a port's interrupts. set DTR and RTS + */ +void +uartenable(Uart *p) +{ + Uart **l; + + if(p->enabled) + return; + + if(p->setup == 0){ + if(p->cpmid == SMC1ID || p->cpmid == SMC2ID) + smcsetup(p); + else + sccsetup(p); + p->setup = 1; + } + + /* + * turn on interrupts + */ + if(p->smc){ + cpmop(RestartTx, p->cpmid, 0); + p->smc->smcmr |= 3; + p->smc->smcm = BSY|TXB|RXB; + eieio(); + }else if(p->scc){ + cpmop(RestartTx, p->cpmid, 0); + p->scc->gsmrl |= ENT|ENR; + p->scc->sccm = BSY|TXB|RXB; + eieio(); + } + + /* + * turn on DTR and RTS + */ + uartdtr(p, 1); + uartrts(p, 1); + + /* + * assume we can send + */ + p->cts = 1; + p->blocked = 0; + + /* + * set baud rate to the last used + */ + uartsetbaud(p, p->baud); + + lock(&uartalloc); + for(l = &uartalloc.elist; *l; l = &(*l)->elist){ + if(*l == p) + break; + } + if(*l == 0){ + p->elist = uartalloc.elist; + uartalloc.elist = p; + } + p->enabled = 1; + unlock(&uartalloc); + p->cts = 1; + p->blocked = 0; + p->xonoff = 0; + p->enabled = 1; +} + +/* + * turn off a port's interrupts. reset DTR and RTS + */ +void +uartdisable(Uart *p) +{ + Uart **l; + + /* + * turn off interrpts + */ + if(p->smc){ + cpmop(StopTx, p->cpmid, 0); + cpmop(CloseRxBD, p->cpmid, 0); + delay(1); + p->smc->smcmr &= ~3; + eieio(); + p->smc->smcm = 0; + }else if(p->scc){ + cpmop(GracefulStopTx, p->cpmid, 0); + delay(1); + cpmop(CloseRxBD, p->cpmid, 0); + p->scc->gsmrl &= ~(ENT|ENR); + eieio(); + p->scc->sccm = 0; + } + + /* + * revert to default settings + */ + p->bpc = 8; + p->parity = 0; + p->stopb = 0; + + /* + * turn off DTR, RTS, hardware flow control & fifo's + */ + uartdtr(p, 0); + uartrts(p, 0); + uartmflow(p, 0); + p->xonoff = p->blocked = 0; + + lock(&uartalloc); + for(l = &uartalloc.elist; *l; l = &(*l)->elist){ + if(*l == p){ + *l = p->elist; + break; + } + } + p->enabled = 0; + unlock(&uartalloc); +} + +/* + * set the next output buffer going + */ +static void +txstart(Uart *p) +{ + Block *b; + int n, flags; + + if(!p->cts || p->blocked || p->txb->status & BDReady) + return; + if((b = p->outb) == nil){ + if((b = qget(p->oq)) == nil) + return; + if(p->mode & SccPPP && + p->mode & SccAHDLC && + BLEN(b) >= 8){ /* strip framing data */ + UartAHDLC *hp; + hp = (UartAHDLC*)p->param; + if(hp != nil && (p->mode & SccIR) == 0){ + hp->txctl_tbl = nhgetl(b->rp); + hp->rxctl_tbl = nhgetl(b->rp+4); + } + b->rp += 8; + if(0) + print("tx #%lux rx #%lux\n", hp->txctl_tbl, hp->rxctl_tbl); + } + } + n = BLEN(b); + if(n <= 0) + print("txstart: 0\n"); + if(p->bpc > 8){ + /* half-word alignment and length if chars are long */ + if(PADDR(b->rp)&1){ /* must be even if chars are long */ + memmove(b->base, b->rp, n); + b->rp = b->base; + b->wp = b->rp+n; + } + if(n & 1) + n++; + } + dcflush(b->rp, n); + p->outb = b; + if(n > 0xFFFF) + n = 0xFFFE; + if(p->mode & SccHDLC) + flags = BDLast | TxTC; + else if(p->mode) + flags = BDLast; + else + flags = 0; + p->txb->addr = PADDR(b->rp); + p->txb->length = n; + eieio(); + p->txb->status = (p->txb->status & BDWrap) | flags | BDReady/*|BDInt */; + eieio(); + + while(p->txb->status & BDReady) + flash(); +} + +/* + * (re)start output + */ +static void +uartkick(Uart *p) +{ + ilock(&p->plock); + if(p->outb == nil) + txstart(p); + iunlock(&p->plock); +} + +/* + * restart input if its off + */ +static void +uartflow(Uart *p) +{ + if(p->modem) + uartrts(p, 1); +} + +static void +uartsetup(int x, int cpmid, char *name) +{ + Uart *p; + + if(nuart >= Nuart) + return; + + p = xalloc(sizeof(Uart)); + uart[nuart] = p; + strcpy(p->name, name); + p->dev = nuart; + nuart++; + p->x = x; + p->cpmid = cpmid; + p->brgc = -1; + p->mode = 0; + + /* + * set rate to 9600 baud. + * 8 bits/character. + * 1 stop bit. + * interrupts enabled. + */ + p->bpc = 8; + p->parity = 0; + p->baud = 9600; + + p->iq = qopen(4*1024, 0, uartflow, p); + p->oq = qopen(4*1024, 0, uartkick, p); +} + +/* + * called by main() to configure a duart port as a console or a mouse + */ +void +uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) +{ + Uart *p = uart[port]; + + uartenable(p); + if(baud) + uartsetbaud(p, baud); + p->putc = putc; + if(in) + *in = p->iq; + if(out) + *out = p->oq; + p->opens++; +} + +static int +uartinput(Uart *p, BD *bd) +{ + int ch, dokick, i, l; + uchar *bp; + + dokick = 0; + if(bd->status & RxFR) + p->frame++; + if(bd->status & RxOV) + p->overrun++; + l = bd->length; + if(bd->status & RxPR){ + p->perror++; + l--; /* it's the last character */ + } + bp = KADDR(bd->addr); + if(p->xonoff || p->putc){ + for(i=0; ixonoff){ + if(ch == CTLS){ + p->blocked = 1; + cpmop(StopTx, p->cpmid, 0); + }else if (ch == CTLQ){ + p->blocked = 0; + dokick = 1; + } + /* BUG? should discard on/off char? */ + } + if(p->putc) + (*p->putc)(p->iq, ch); + } + } + if(p->putc == nil && l > 0) + qproduce(p->iq, bp, l); + return dokick; +} + +static void +framedinput(Uart *p, BD *bd) +{ + Block *pkt; + int l; + + pkt = p->partial; + p->partial = nil; + if(bd->status & RxOV){ + p->overrun++; + goto Discard; + } + if(bd->status & (RxAB|RxCR|RxCD|RxLG|RxNO|RxDE|RxBOF|RxBRK)){ + if(bd->status & RxCR) + p->crcerr++; + else + p->frame++; + goto Discard; + } + if(pkt == nil){ + pkt = iallocb(1500); /* TO DO: allocate less if possible */ + if(pkt == nil) + return; + } + l = bd->length; + if(bd->status & BDLast) + l -= BLEN(pkt); /* last one gives size of entire frame */ + if(l > 0){ + if(pkt->wp+l > pkt->lim) + goto Discard; + memmove(pkt->wp, KADDR(bd->addr), l); + pkt->wp += l; + } + if(0) + print("#%ux|", bd->status); + if(bd->status & BDLast){ + if(p->mode & (SccHDLC|SccAHDLC)){ + if(BLEN(pkt) <= 2){ + p->frame++; + goto Discard; + } + pkt->wp -= 2; /* strip CRC */ + } + qpass(p->iq, pkt); + }else + p->partial = pkt; + return; + +Discard: + if(pkt != nil) + freeb(pkt); +} + +/* + * handle an interrupt to a single uart + */ +static void +uartintr(Uart *p, int events) +{ + int dokick; + BD *bd; + Block *b; + + if(events & BSY) + p->overrun++; + p->interrupts++; + dokick = 0; + while(p->rxb != nil && ((bd = &p->rxb[p->rdrx])->status & BDEmpty) == 0){ + if(p->mode) + framedinput(p, bd); + else if(uartinput(p, bd)) + dokick = 1; + dcflush(KADDR(bd->addr), bd->length); + eieio(); + bd->status = (bd->status & BDWrap) | BDEmpty|BDInt; + p->rdrx ^= 1; + } + if((bd = p->txb) != nil){ + if((bd->status & BDReady) == 0){ + ilock(&p->plock); + if((b = p->outb) != nil){ + b->rp += bd->length; + if(b->rp >= b->wp){ + p->outb = nil; + freeb(b); + } + } + txstart(p); + iunlock(&p->plock); + } + } + eieio(); + /* TO DO: modem status isn't available on 82xFADS */ + if(dokick && p->cts && !p->blocked){ + if(p->outb == nil){ + ilock(&p->plock); + txstart(p); + iunlock(&p->plock); + } + cpmop(RestartTx, p->cpmid, 0); + } else if (events & TXE) + cpmop(RestartTx, p->cpmid, 0); +} + +/* + * used to ensure uart console output when debugging + */ +void +uartwait(void) +{ + Uart *p = uart[0]; + int s; + + while(p && p->outb){ + s = splhi(); + if((p->txb->status & BDReady) == 0){ + p->blocked = 0; + p->cts = 1; + if(p->cpmid == SMC1ID || p->cpmid == SMC2ID) + smcuintr(nil, p); + else + sccuintr(nil, p); + } + splx(s); + } +} + +static Dirtab *uartdir; +static int ndir; + +static void +setlength(int i) +{ + Uart *p; + + if(i > 0){ + p = uart[i]; + if(p && p->opens && p->iq) + uartdir[3*i].length = qlen(p->iq); + } else for(i = 0; i < nuart; i++){ + p = uart[i]; + if(p && p->opens && p->iq) + uartdir[3*i].length = qlen(p->iq); + } + +} + +void +uartinstall(void) +{ + int port; + char *p, *q; + static int already; + + if(already) + return; + already = 1; + uartsetup(1, SMC1ID, "eia0"); +/* + if((p = getconf("console")) || (p = "0")){ + if(USESMC2) + port = strtol(p, &q, 0); + else + port = 0; + if(p != q && (port == 0 || port == 1)) + uartspecial(port, 9600, &kbdq, &printq, kbdcr2nl); + } +*/ + uartspecial(0, 19200, &kbdq, &printq, kbdcr2nl); + +// if(USESMC2) +// uartsetup(2, SMC2ID, "eia1"); +// if(USESCC2) +// uartsetup(2, SCC2ID, "eia2"); +} + +/* + * all uarts must be uartsetup() by this point or inside of uartinstall() + */ +static void +uartreset(void) +{ + int i; + Dirtab *dp; + + uartinstall(); /* architecture specific */ + + ndir = 4*nuart; + uartdir = xalloc(ndir * sizeof(Dirtab)); + dp = uartdir; + for(i = 0; i < nuart; i++){ + /* 3 directory entries per port */ + strcpy(dp->name, uart[i]->name); + dp->qid.path = NETQID(i, Ndataqid); + dp->perm = 0660; + dp++; + sprint(dp->name, "%sctl", uart[i]->name); + dp->qid.path = NETQID(i, Nctlqid); + dp->perm = 0660; + dp++; + sprint(dp->name, "%sstat", uart[i]->name); + dp->qid.path = NETQID(i, Nstatqid); + dp->perm = 0444; + dp++; + sprint(dp->name, "%smode", uart[i]->name); + dp->qid.path = NETQID(i, Ntypeqid); + dp->perm = 0660; + dp++; + } +} + +static Chan* +uartattach(char *spec) +{ + return devattach('t', spec); +} + +static int +uartwalk(Chan *c, char *name) +{ + return devwalk(c, name, uartdir, ndir, devgen); +} + +static void +uartstat(Chan *c, char *dp) +{ + if(NETTYPE(c->qid.path) == Ndataqid) + setlength(NETID(c->qid.path)); + devstat(c, dp, uartdir, ndir, devgen); +} + +static Chan* +uartopen(Chan *c, int omode) +{ + Uart *p; + + c = devopen(c, omode, uartdir, ndir, devgen); + + switch(NETTYPE(c->qid.path)){ + case Nctlqid: + case Ndataqid: + p = uart[NETID(c->qid.path)]; + qlock(p); + if(p->opens++ == 0){ + uartenable(p); + qreopen(p->iq); + qreopen(p->oq); + } + qunlock(p); + break; + } + + return c; +} + +static void +uartclose(Chan *c) +{ + Uart *p; + + if(c->qid.path & CHDIR) + return; + if((c->flag & COPEN) == 0) + return; + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + case Nctlqid: + p = uart[NETID(c->qid.path)]; + qlock(p); + if(--(p->opens) == 0){ + uartdisable(p); + qclose(p->iq); + qclose(p->oq); + } + qunlock(p); + break; + } +} + +static long +uartstatus(Chan*, Uart *p, void *buf, long n, long offset) +{ + IMM *io; + char str[256]; + + sprint(str, "opens %d ferr %lud oerr %lud crcerr %lud baud %lud perr %lud intr %lud", p->opens, + p->frame, p->overrun, p->crcerr, p->baud, p->perror, p->interrupts); + /* TO DO: cts, dsr, ring, dcd, dtr, rts aren't all available on 82xFADS */ + io = m->iomem; + if(p->scc){ + if((io->pcdat & SIBIT(9)) == 0) + strcat(str, " cts"); + if((io->pcdat & SIBIT(8)) == 0) + strcat(str, " dcd"); + if((io->pbdat & IBIT(22)) == 0) + strcat(str, " dtr"); + }else if(p->smc){ + if((io->pbdat & IBIT(23)) == 0) + strcat(str, " dtr"); + } + strcat(str, "\n"); + return readstr(offset, buf, n, str); +} + +static long +uartread(Chan *c, void *buf, long n, vlong offset) +{ + Uart *p; + + if(c->qid.path & CHDIR){ + setlength(-1); + return devdirread(c, buf, n, uartdir, ndir, devgen); + } + + p = uart[NETID(c->qid.path)]; + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + return qread(p->iq, buf, n); + case Nctlqid: + return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE); + case Nstatqid: + return uartstatus(c, p, buf, n, offset); + case Ntypeqid: + return readnum(offset, buf, n, p->mode, NUMSIZE); + } + + return 0; +} + +static Block* +uartbread(Chan *c, long n, ulong offset) +{ + if(c->qid.path & CHDIR || NETTYPE(c->qid.path) != Ndataqid) + return devbread(c, n, offset); + return qbread(uart[NETID(c->qid.path)]->iq, n); +} + +static void +uartctl(Uart *p, char *cmd) +{ + int i, n; + + /* let output drain for a while */ + for(i = 0; i < 16 && qlen(p->oq); i++) + tsleep(&p->r, qlen, p->oq, 125); + + if(strncmp(cmd, "break", 5) == 0){ + uartbreak(p, 0); + return; + } + + n = atoi(cmd+1); + switch(*cmd){ + case 'B': + case 'b': + uartsetbaud(p, n); + break; + case 'D': + case 'd': + uartdtr(p, n); + break; + case 'f': + case 'F': + qflush(p->oq); + break; + case 'H': + case 'h': + qhangup(p->iq, 0); + qhangup(p->oq, 0); + break; + case 'L': + case 'l': + uartbits(p, n); + break; + case 'm': + case 'M': + uartmflow(p, n); + break; + case 'n': + case 'N': + qnoblock(p->oq, n); + break; + case 'P': + case 'p': + uartparity(p, *(cmd+1)); + break; + case 'K': + case 'k': + uartbreak(p, n); + break; + case 'R': + case 'r': + uartrts(p, n); + break; + case 'Q': + case 'q': + qsetlimit(p->iq, n); + qsetlimit(p->oq, n); + break; + case 'W': + case 'w': + /* obsolete */ + break; + case 'X': + case 'x': + p->xonoff = n; + break; + case 'Z': + case 'z': + p->loopback = n; + break; + } +} + +static long +uartwrite(Chan *c, void *buf, long n, vlong offset) +{ + Uart *p; + char cmd[32]; + int m, inuse; + + USED(offset); + + if(c->qid.path & CHDIR) + error(Eperm); + + p = uart[NETID(c->qid.path)]; + + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + return qwrite(p->oq, buf, n); + case Nctlqid: + if(n >= sizeof(cmd)) + n = sizeof(cmd)-1; + memmove(cmd, buf, n); + cmd[n] = 0; + uartctl(p, cmd); + return n; + case Ntypeqid: + if(p->smc || p->putc) + error(Ebadarg); + if(n >= sizeof(cmd)) + n = sizeof(cmd)-1; + memmove(cmd, buf, n); + cmd[n] = 0; + m = strtoul(cmd, nil, 0); + inuse = 0; + qlock(p); + if(p->opens == 0){ + p->mode = m & 0x7F; + p->loopback = (m&0x80)!=0; + p->setup = 0; + }else + inuse = 1; + qunlock(p); + if(inuse) + error(Einuse); + return n; + } +} + +static long +uartbwrite(Chan *c, Block *bp, ulong offset) +{ + /* TO DO: better */ + return devbwrite(c, bp, offset); +} + +static void +uartwstat(Chan *c, char *dp) +{ + Dir d; + Dirtab *dt; + + if(!iseve()) + error(Eperm); + if(CHDIR & c->qid.path) + error(Eperm); + if(NETTYPE(c->qid.path) == Nstatqid) + error(Eperm); + + dt = &uartdir[3 * NETID(c->qid.path)]; + convM2D(dp, &d); + d.mode &= 0666; + dt[0].perm = dt[1].perm = d.mode; +} + +Dev uartdevtab = { + 't', + "uart", + + uartreset, + devinit, + uartattach, + devclone, + uartwalk, + uartstat, + uartopen, + devcreate, + uartclose, + uartread, + uartbread, + uartwrite, + uartbwrite, + devremove, + uartwstat, +}; diff --git a/mpc/etherscc.c b/mpc/etherscc.c new file mode 100644 index 0000000000000000000000000000000000000000..7343c38e619bdc7907ea5378c3d500083740050b --- /dev/null +++ b/mpc/etherscc.c @@ -0,0 +1,552 @@ +/* + * SCCn ethernet + */ + +#include "u.h" +#include "../port/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, +}; + +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 sccid; + int port; + int init; + int active; + SCC* scc; + + Ring; + + ulong interrupts; /* statistics */ + ulong deferred; + ulong heartbeat; + ulong latecoll; + ulong retrylim; + ulong underrun; + ulong overrun; + ulong carrierlost; + ulong retrycount; +} Ctlr; + +static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B}; +static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID}; +static int sccbase[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60}; +static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P}; + +static void +attach(Ether *ether) +{ + Ctlr *ctlr; + + ctlr = ether->ctlr; + ctlr->active = 1; + ctlr->scc->gsmrl |= ENR|ENT; + eieio(); +// m->bcsr[1] &= ~DisableEther; +} + +static void +closed(Ether *ether) +{ + Ctlr *ctlr; + + ctlr = ether->ctlr; + if(0){ + if(ether->port == 2) + scc2stop(ctlr->scc); + ilock(ctlr); + ctlr->active = 0; + iunlock(ctlr); + print("Ether closed\n"); + } +} + +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; + if(ctlr->init) + return; + 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*, Ether *ether) +{ + int len, events, status; + Ctlr *ctlr; + BD *dre; + Block *b; + + 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){ + memmove(b->wp, KADDR(dre->addr), len); + b->wp += len; + etheriq(ether, b, 1); + dcflush(KADDR(dre->addr), len); + }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(RestartTx, ctlr->sccid, 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, uchar *ea) +{ + int i, rcs, tcs; + Etherparam *p; + IMM *io; + + io = ioplock(); + if(ctlr->port == 2){ + io->papar |= SIBIT(12)|SIBIT(13); /* enable TXD2 and RXD2 pins */ + io->padir &= ~(SIBIT(12)|SIBIT(13)); + io->paodr &= ~SIBIT(12); + + io->pcpar &= ~(SIBIT(9)|SIBIT(8)); /* enable CLSN (CTS2) and RENA (CD2) */ + io->pcdir &= ~(SIBIT(9)|SIBIT(8)); + io->pcso |= SIBIT(9)|SIBIT(8); + + io->papar |= SIBIT(6)|SIBIT(5); /* enable CLK2 and CLK3 */ + io->padir &= ~(SIBIT(6)|SIBIT(5)); + eieio(); + + rcs = CLK2; + tcs = CLK3; + }else{ + io->papar |= SIBIT(14)|SIBIT(15); /* enable TXD1 and RXD1 pins */ + io->padir &= ~(SIBIT(14)|SIBIT(15)); + io->paodr &= ~SIBIT(14); + + io->pcpar &= ~(SIBIT(10)|SIBIT(11)); /* enable CLSN (CTS1) and RENA (CD1) */ + io->pcdir &= ~(SIBIT(10)|SIBIT(11)); + io->pcso |= SIBIT(10)|SIBIT(11); + eieio(); + + io->papar |= SIBIT(6)|SIBIT(7); /* enable CLK2 and CLK1 */ + io->padir &= ~(SIBIT(6)|SIBIT(7)); + eieio(); + + io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6)); /* ETHLOOP, TPFULDL~, TPSQEL~ */ + io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6); + io->pcdat &= ~SIBIT(4); + io->pcdat |= SIBIT(5)|SIBIT(6); + eieio(); + + rcs = CLK2; + tcs = CLK1; + } + iopunlock(); + + sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */ + + p = (Etherparam*)KADDR(ctlr->sccid==SCC1ID? SCC1P: SCC2P); + 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(InitRxTx, ctlr->sccid, 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; ipaddr[2-i/2] = (ea[i+1]<<8)|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(); + + if(ctlr->sccid == SCC2ID){ + io->pbpar |= IBIT(18); /* enable TENA pin (RTS2) */ + io->pbdir |= IBIT(18); + }else{ + io->pbpar |= IBIT(19); /* enable TENA pin (RTS1) */ + io->pbdir |= IBIT(19); + } + eieio(); + + /* enable is deferred until attach */ +} + +static int +reset(Ether* ether) +{ + uchar ea[Eaddrlen]; + 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 %d\n", ether->type, ether->port); + return -1; + } + + ether->irq = VectorCPIC + sccirq[ether->port]; + scc = IOREGS(sccbase[ether->port], SCC); + if(ether->port == 2) + scc2claim(1, DisableEther, scc2stop, scc); + + ctlr = malloc(sizeof(*ctlr)); + ether->ctlr = ctlr; + memset(ctlr, 0, sizeof(*ctlr)); + ctlr->scc = scc; + ctlr->port = ether->port; + ctlr->sccid = sccid[ether->port]; + + if(ioringinit(ctlr, Nrdre, Ntdre, Bufsize) < 0) + panic("etherscc init"); + + sccsetup(ctlr, scc, ether->ea); + + ether->mbps = 10; /* TO DO: could be 100mbps on 860T */ + ether->attach = attach; + ether->closed = closed; + ether->transmit = transmit; + ether->interrupt = interrupt; + ether->ifstat = ifstat; + + ether->arg = ether; + ether->promiscuous = promiscuous; + ether->multicast = multicast; + + /* + * Until we know where to find it, insist that the plan9.ini + * entry holds the Ethernet address. + */ + memset(ea, 0, Eaddrlen); + if(memcmp(ea, ether->ea, Eaddrlen) == 0){ + print("no ether address"); + return -1; + } + + return 0; +} + +void +etherscclink(void) +{ + addethercard("SCC", reset); + addethercard("SCC2", reset); +} diff --git a/mpc/fns.h b/mpc/fns.h index 0224c7874f467736f2c939834b25264f20c96100..4276b6078c7ff390eec52535d9b657e33d33a49b 100644 --- a/mpc/fns.h +++ b/mpc/fns.h @@ -89,3 +89,5 @@ ulong getcallerpc(void*); /* compatibility with inf2.1 */ #define bpenumenv(n) ((char*)0) + +#define IOREGS(x, T) ((T*)((char*)m->iomem+(x))) diff --git a/mpc/l.s b/mpc/l.s index 2a0299b0802609c1381ecb739f54eb367a4c3145..d1fc39849375a49d9e162953070caf0f6b346b73 100644 --- a/mpc/l.s +++ b/mpc/l.s @@ -122,17 +122,15 @@ MOVW R4, SPR(IMMR) /* set internal memory base */ MOVW $mach0(SB), R(MACH) - ADD $(MACHSIZE-8), R(MACH), R1 + ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */ SUB $4, R(MACH), R3 ADD $4, R1, R4 + clrmach: MOVWU R0, 4(R3) CMP R3, R4 BNE clrmach - MOVW R0, R(USER) - MOVW R0, 0(R(MACH)) - MOVW $edata(SB), R3 MOVW $end(SB), R4 ADD $4, R4 @@ -630,13 +628,6 @@ TEXT powerupled(SB), $0 MOVW R7,0(R11) RETURN -TEXT reset(SB), $-4 - MOVW $0,R4 - MOVW 0(R4), R5 -loop: - BR loop - - GLOBL mach0+0(SB), $MACHSIZE GLOBL spltbl+0(SB), $4 GLOBL intrtbl+0(SB), $4 diff --git a/mpc/main.c b/mpc/main.c index 49c1c263dd936c55427ade8f356ceaedaa58107f..9ce763493885f1f08dd9b6cb78ab5f3f115a2eea 100644 --- a/mpc/main.c +++ b/mpc/main.c @@ -15,10 +15,36 @@ int nconf; Conf conf; +void +flash(void) +{ + int i; + *(uchar*)(NIMMEM+0x2200) = 0; + for(i=0; i<1000000; i++) + ; + *(uchar*)(NIMMEM+0x2200) = 0x2; + for(i=0; i<1000000; i++) + ; +} + void main(void) { machinit(); + confinit(); + xinit(); + printinit(); + cpminit(); + uartinstall(); + print("hello world\n"); + + delay(100); + + reset(); + + *(uchar*)0 = 0; + for(;;) + ; } void @@ -37,6 +63,8 @@ machinit(void) mf = io->plprcr >> 20; m->oscclk = osc; m->speed = osc*(mf+1); + m->cpuhz = m->speed*MHz; /* general system clock (cycles) */ + m->clockgen = osc*MHz; /* clock generator frequency (cycles) */ } void @@ -110,6 +138,37 @@ iprint(char *fmt, ...) return n; } +void +confinit(void) +{ + int nbytes; + ulong pa; + + conf.nmach = 1; /* processors */ + conf.nproc = 200; /* processes */ + + // hard wire for now + pa = 0xff200000; // leave 2 Meg for kernel + nbytes = 10*1024*1024; // leave room at the top as well + + conf.npage0 = nbytes/BY2PG; + conf.base0 = pa; + + conf.npage1 = 0; + conf.base1 = 0; + + conf.npage = conf.npage0 + conf.npage1; + + conf.upages = (conf.npage*50)/100; + conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG; + + /* set up other configuration parameters */ + conf.nswap = conf.npage*3; + conf.nswppo = 4096; + conf.nimage = 200; + + conf.copymode = 0; /* copy on write */ +} int isaconfig(char *class, int ctlrno, ISAConf *isa) diff --git a/mpc/mem.h b/mpc/mem.h index 8aa6529303fd1aaa46ae99ade0fba99735375769..3255302707299187649f8eda67c1d6f734fc4c43 100644 --- a/mpc/mem.h +++ b/mpc/mem.h @@ -18,6 +18,8 @@ #define CACHELINELOG 4 #define CACHELINESZ (1<iomem; + io->plprcrk = KEEP_ALIVE_KEY; // unlock + io->plprcr |= IBIT(24); // enable checkstop reset + putmsr(getmsr() & ~MSR_ME); + // cause checkstop -> causes reset + *(ulong*)(0) = 0; +} diff --git a/port/chan.c b/port/chan.c index 176e07ea626351b8b0f9adf5993e90c18fe89ca4..7c5a39bc6c3a73c2579823945b5c0df6a9f8bcde 100644 --- a/port/chan.c +++ b/port/chan.c @@ -688,7 +688,7 @@ namec(char *name, int amode, int omode, ulong perm) if(omode == OEXEC) c->flag &= ~CCACHE; - c = devtab[c->type]->open(c, omode); + c = devtab[c->type]->open(c, omode&~OCEXEC); if(omode & OCEXEC) c->flag |= CCEXEC; @@ -749,7 +749,7 @@ namec(char *name, int amode, int omode, ulong perm) omode |= OTRUNC; goto Open; } - devtab[c->type]->create(c, elem, omode, perm); + devtab[c->type]->create(c, elem, omode&~OCEXEC, perm); if(omode & OCEXEC) c->flag |= CCEXEC; if(omode & ORCLOSE) diff --git a/port/dev.c b/port/dev.c index 0b6ed54a6070d1da23d72201fdeed9f7d638cdcf..af6fafcddaa0834bcb18f7f5d6afb2469aeb950a 100644 --- a/port/dev.c +++ b/port/dev.c @@ -159,7 +159,7 @@ devstat(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen) case 0: break; case 1: - if(eqqid(c->qid, dir.qid)) { + if(c->qid.path == dir.qid.path) { if(c->flag&CMSG) dir.mode |= CHMOUNT; convD2M(&dir, db); @@ -211,7 +211,7 @@ devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) case 0: break; case 1: - if(eqqid(c->qid, dir.qid)) { + if(c->qid.path == dir.qid.path) { if(strcmp(up->user, dir.uid) == 0) mode = dir.mode; else diff --git a/port/devenv.c b/port/devenv.c index 4e4695e217d752b6b8282dbecf72a10c0637f0f6..f712265ca5016eda835e6a6aba85381c003560ad 100644 --- a/port/devenv.c +++ b/port/devenv.c @@ -28,11 +28,21 @@ envgen(Chan *c, Dirtab*, int, int s, Dir *dp) return -1; } - devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp); + devdir(c, e->qid, e->name, e->len, eve, 0666, dp); qunlock(eg); return 1; } +static Evalue* +envlookup(Egrp *eg, char *name, ulong qidpath) +{ + Evalue *e; + for(e = eg->entries; e; e = e->link) + if(e->qid.path == qidpath || (name && strcmp(e->name, name) == 0)) + return e; + return nil; +} + static Chan* envattach(char *spec) { @@ -48,6 +58,8 @@ envwalk(Chan *c, char *name) static void envstat(Chan *c, char *db) { + if(c->qid.path & CHDIR) + c->qid.vers = up->egrp->vers; devstat(c, db, 0, 0, envgen); } @@ -64,15 +76,13 @@ envopen(Chan *c, int omode) } else { qlock(eg); - for(e = eg->entries; e; e = e->link) - if(e->path == c->qid.path) - break; - + e = envlookup(eg, nil, c->qid.path); if(e == 0) { qunlock(eg); error(Enonexist); } - if(omode == (OWRITE|OTRUNC) && e->value) { + if((omode & OTRUNC) && e->value) { + e->qid.vers++; free(e->value); e->value = 0; e->len = 0; @@ -103,18 +113,19 @@ envcreate(Chan *c, char *name, int omode, ulong) nexterror(); } - for(e = eg->entries; e; e = e->link) - if(strcmp(e->name, name) == 0) - error(Einuse); + if(envlookup(eg, name, -1)) + error(Eexist); e = smalloc(sizeof(Evalue)); e->name = smalloc(strlen(name)+1); strcpy(e->name, name); - e->path = ++eg->path; + e->qid.path = ++eg->path; + e->qid.vers = 0; + eg->vers++; e->link = eg->entries; eg->entries = e; - c->qid = (Qid){e->path, 0}; + c->qid = e->qid; qunlock(eg); poperror(); @@ -135,10 +146,9 @@ envremove(Chan *c) eg = up->egrp; qlock(eg); - l = &eg->entries; for(e = *l; e; e = e->link) { - if(e->path == c->qid.path) + if(e->qid.path == c->qid.path) break; l = &e->link; } @@ -149,6 +159,7 @@ envremove(Chan *c) } *l = e->link; + eg->vers++; qunlock(eg); free(e->name); if(e->value) @@ -157,8 +168,15 @@ envremove(Chan *c) } static void -envclose(Chan*) +envclose(Chan *c) { + /* + * close can't fail, so errors from remove will be ignored anyway. + * since permissions aren't checked, + * envremove can't not remove it if its there. + */ + if(c->flag & CRCLOSE) + envremove(c); } static long @@ -173,10 +191,7 @@ envread(Chan *c, void *a, long n, vlong off) eg = up->egrp; qlock(eg); - for(e = eg->entries; e; e = e->link) - if(e->path == c->qid.path) - break; - + e = envlookup(eg, nil, c->qid.path); if(e == 0) { qunlock(eg); error(Enonexist); @@ -210,10 +225,7 @@ envwrite(Chan *c, void *a, long n, vlong off) eg = up->egrp; qlock(eg); - for(e = eg->entries; e; e = e->link) - if(e->path == c->qid.path) - break; - + e = envlookup(eg, nil, c->qid.path); if(e == 0) { qunlock(eg); error(Enonexist); @@ -228,6 +240,8 @@ envwrite(Chan *c, void *a, long n, vlong off) e->len = vend; } memmove(e->value+offset, a, n); + e->qid.vers++; + eg->vers++; qunlock(eg); return n; } @@ -269,7 +283,7 @@ envcpy(Egrp *to, Egrp *from) memmove(ne->value, e->value, e->len); ne->len = e->len; } - ne->path = ++to->path; + ne->qid.path = ++to->path; *l = ne; l = &ne->link; } diff --git a/port/devsrv.c b/port/devsrv.c index 096bd2f0e0bce15ede0669d543f961b12463be78..3458d673432df8ac61ff248cdf9ebb2fb574d48c 100644 --- a/port/devsrv.c +++ b/port/devsrv.c @@ -63,12 +63,24 @@ srvstat(Chan *c, char *db) devstat(c, db, 0, 0, srvgen); } +static Srv* +srvlookup(char *name, ulong qidpath) +{ + Srv *sp; + for(sp = srv; sp; sp = sp->link) + if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0)) + return sp; + return nil; +} + static Chan* srvopen(Chan *c, int omode) { Srv *sp; if(c->qid.path == CHDIR){ + if(omode & ORCLOSE) + error(Eperm); if(omode != OREAD) error(Eisdir); c->mode = omode; @@ -82,16 +94,13 @@ srvopen(Chan *c, int omode) nexterror(); } - for(sp = srv; sp; sp = sp->link) - if(sp->path == c->qid.path) - break; - + sp = srvlookup(nil, c->qid.path); if(sp == 0 || sp->chan == 0) error(Eshutdown); if(omode&OTRUNC) error(Eperm); - if(omode!=sp->chan->mode && sp->chan->mode!=ORDWR) + if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); cclose(c); @@ -106,9 +115,12 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) { Srv *sp; - if(omode != OWRITE) + if(openmode(omode) != OWRITE) error(Eperm); + if(omode & OCEXEC) /* can't happen */ + panic("someone broke namec"); + sp = malloc(sizeof(Srv)); if(sp == 0) error(Enomem); @@ -118,6 +130,9 @@ srvcreate(Chan *c, char *name, int omode, ulong perm) qunlock(&srvlk); nexterror(); } + if(srvlookup(name, -1)) + error(Eexist); + sp->path = qidpath++; sp->link = srv; c->qid.path = sp->path; @@ -174,9 +189,7 @@ srvwstat(Chan *c, char *dp) Dir d; Srv *sp; - if(!iseve()) - error(Eperm); - if(CHDIR & c->qid.path) + if(c->qid.path & CHDIR) error(Eperm); qlock(&srvlk); @@ -185,11 +198,13 @@ srvwstat(Chan *c, char *dp) nexterror(); } - for(sp = srv; sp; sp = sp->link) - if(sp->path == c->qid.path) - break; - if(sp == 0 || sp->chan == 0) - error(Eshutdown); + sp = srvlookup(nil, c->qid.path); + if(sp == 0) + error(Enonexist); + + if(strcmp(sp->owner, up->user) && !iseve()) + error(Eperm); + convM2D(dp, &d); d.mode &= 0777; sp->perm = d.mode; @@ -199,8 +214,16 @@ srvwstat(Chan *c, char *dp) } static void -srvclose(Chan*) +srvclose(Chan *c) { + /* + * errors from srvremove will be caught by cclose and ignored. + * in theory we need to override any changes in removability + * since open, but since all that's checked is the owner, + * which is immutable, all is well. + */ + if(c->flag & CRCLOSE) + srvremove(c); } static long @@ -232,15 +255,12 @@ srvwrite(Chan *c, void *va, long n, vlong) cclose(c1); nexterror(); } - for(sp = srv; sp; sp = sp->link) - if(sp->path == c->qid.path) - break; - + sp = srvlookup(nil, c->qid.path); if(sp == 0) error(Enonexist); if(sp->chan) - panic("srvwrite"); + error(Ebadusefd); sp->chan = c1; qunlock(&srvlk); diff --git a/port/error.h b/port/error.h index 6cc752c0d9e1e7e0525c754cc252081b324000fb..98277d6328a42717f602e00565f0a5f1b907cccc 100644 --- a/port/error.h +++ b/port/error.h @@ -6,6 +6,7 @@ extern char Emountrpc[]; /* mount rpc error */ extern char Eshutdown[]; /* mounted device shut down */ extern char Enocreate[]; /* mounted directory forbids creation */ extern char Enonexist[]; /* file does not exist */ +extern char Eexist[]; /* file already exists */ extern char Ebadsharp[]; /* unknown device in # filename */ extern char Enotdir[]; /* not a directory */ extern char Eisdir[]; /* file is a directory */ diff --git a/port/portdat.h b/port/portdat.h index 76888f98ea565616b63106dee301e9e29cba42e0..55736d7cad04aec4119add597ad8cd3de0a11d2f 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -422,7 +422,8 @@ struct Egrp Ref; QLock; Evalue *entries; - ulong path; + ulong path; /* qid.path of next Evalue to be allocated */ + ulong vers; /* of Egrp */ }; struct Evalue @@ -430,8 +431,8 @@ struct Evalue char *name; char *value; int len; - ulong path; Evalue *link; + Qid qid; }; struct Fgrp diff --git a/port/portfns.h b/port/portfns.h index b700fe2098f7369c8c027e1a8ae91947054ec4ef..404e9a68c65197ca50f29b0d204d331e3172206d 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -258,9 +258,6 @@ long rtctime(void); void runlock(RWlock*); Proc* runproc(void); void savefpregs(FPsave*); -void sccclock(void); -int sccintr(void); -void sccsetup(void*, ulong, int); void sched(void); void scheddump(void); void schedinit(void); diff --git a/port/sysfile.c b/port/sysfile.c index 14c239e8350961116f52041e4766441d7a85500b..28c83fdcb4f3012be31bb3af4e50373c5231923e 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -96,8 +96,6 @@ fdtochan(int fd, int mode, int chkmnt, int iref) int openmode(ulong o) { - if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC)) - error(Ebadarg); o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg);