| plan 9 kernel history: overview | file list | diff list |
1999/0629/carrera/devether.c (diff list | history)
| 1993/0903/sys/src/9/carrera/devether.c:8,275 – 1993/0904/sys/src/9/carrera/devether.c:8,486 (short | long) | ||
| 1993/0903 | #include "../port/netif.h" /* | |
| 1993/0904 | * National Semiconductor DP83932 * Systems-Oriented Network Interface Controller * (SONIC) | |
| 1993/0903 | */ | |
| 1993/0904 | #define SONICADDR ((Sonic*)Sonicbase) | |
| 1993/0903 |
| |
| 1993/0904 | #define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v) | |
| 1993/0903 |
| |
| 1993/0904 | typedef struct { ulong cr; /* command */ ulong dcr; /* data configuration */ ulong rcr; /* receive control */ ulong tcr; /* transmit control */ ulong imr; /* interrupt mask */ ulong isr; /* interrupt status */ ulong utda; /* upper transmit descriptor address */ ulong ctda; /* current transmit descriptor address */ ulong pad0x08[5]; /* */ ulong urda; /* upper receive descriptor address */ ulong crda; /* current receive descriptor address */ ulong pad0x0F[4]; /* */ ulong eobc; /* end of buffer word count */ ulong urra; /* upper receive resource address */ ulong rsa; /* resource start address */ ulong rea; /* resource end address */ ulong rrp; /* resource read pointer */ ulong rwp; /* resource write pointer */ ulong pad0x19[8]; /* */ ulong cep; /* CAM entry pointer */ ulong cap2; /* CAM address port 2 */ ulong cap1; /* CAM address port 1 */ ulong cap0; /* CAM address port 0 */ ulong ce; /* CAM enable */ ulong cdp; /* CAM descriptor pointer */ ulong cdc; /* CAM descriptor count */ ulong sr; /* silicon revision */ ulong wt0; /* watchdog timer 0 */ ulong wt1; /* watchdog timer 1 */ ulong rsc; /* receive sequence counter */ ulong crct; /* CRC error tally */ ulong faet; /* FAE tally */ ulong mpt; /* missed packet tally */ ulong mdt; /* maximum deferral timer */ ulong pad0x30[15]; /* */ ulong dcr2; /* data configuration 2 */ } Sonic; | |
| 1993/0903 | enum { | |
| 1993/0904 | Nrb = 16, /* receive buffers */ Ntb = 8, /* transmit buffers */ }; | |
| 1993/0903 |
| |
| 1993/0904 | enum { Htx = 0x0001, /* halt transmission */ Txp = 0x0002, /* transmit packet(s) */ Rxdis = 0x0004, /* receiver disable */ Rxen = 0x0008, /* receiver enable */ Stp = 0x0010, /* stop timer */ St = 0x0020, /* start timer */ Rst = 0x0080, /* software reset */ Rrra = 0x0100, /* read RRA */ Lcam = 0x0200, /* load CAM */ | |
| 1993/0903 |
| |
| 1993/0904 | Dw32 = 0x0020, /* data width select */ Sterm = 0x0400, /* synchronous termination */ Lbr = 0x4000, /* latched bus retry */ Efm = 0x0010, /* Empty fill mode */ W14tf = 0x0003, /* 14 Word transmit fifo */ | |
| 1993/0903 |
| |
| 1993/0904 | Prx = 0x0001, /* packet received ok */ Fae = 0x0004, /* frame alignment error */ Crc = 0x0008, /* CRC error */ Lpkt = 0x0040, /* last packet in rba */ Bc = 0x0080, /* broadcast packet received */ Pro = 0x1000, /* physical promiscuous mode */ Brd = 0x2000, /* accept broadcast packets */ Rnt = 0x4000, /* accept runt packets */ Err = 0x8000, /* accept packets with errors */ | |
| 1993/0903 |
| |
| 1993/0904 | Ptx = 0x0001, /* packet transmitted ok */ Pintr = 0x8000, /* programmable interrupt */ | |
| 1993/0903 |
| |
| 1993/0904 | Rfo = 0x0001, /* receive fifo overrun */ MpTally = 0x0002, /* missed packet tally counter rollover */ FaeTally= 0x0004, /* frame alignment error tally counter rollover */ CrcTally= 0x0008, /* Crc tally counter rollover */ Rbae = 0x0010, /* receive buffer area exceeded */ Rbe = 0x0020, /* receive buffer exhausted */ Rde = 0x0040, /* receive descriptors exhausted */ Txer = 0x0100, /* transmit error */ Txdn = 0x0200, /* transmission done */ Pktrx = 0x0400, /* packet received */ Pint = 0x0800, /* programmed interrupt */ Lcd = 0x1000, /* load CAM done */ Hbl = 0x2000, /* CD heartbeat lost */ Br = 0x4000, /* bus retry occurred */ AllIntr = 0x7771, /* all of the above */ | |
| 1993/0903 | }; | |
| 1993/0904 | /* * Receive Resource Descriptor. */ typedef struct { uchar pad0[2]; ushort ptr0; /* buffer pointer in the RRA */ uchar pad1[2]; ushort ptr1; uchar pad2[2]; ushort wc0; /* buffer word count in the RRA */ uchar pad3[2]; ushort wc1; } RXrsc; | |
| 1993/0903 | /* | |
| 1993/0904 | * Receive Packet Descriptor. | |
| 1993/0903 | */ typedef struct { | |
| 1993/0904 | uchar pad0[2]; ushort status; /* receive status */ uchar pad1[2]; ushort count; /* packet byte count */ uchar pad2[2]; ushort ptr0; /* buffer pointer */ uchar pad3[2]; ushort ptr1; uchar pad4[2]; ushort seqno; /* */ uchar pad5[2]; ushort link; /* descriptor link and EOL */ uchar pad6[2]; ushort owner; /* in use */ } RXpkt; | |
| 1993/0903 | ||
| 1993/0904 | /* * Transmit Packet Descriptor. */ typedef struct { uchar pad0[2]; ushort status; /* transmit status */ uchar pad1[2]; ushort config; /* */ uchar pad2[2]; ushort size; /* byte count of entire packet */ uchar pad3[2]; ushort count; /* fragment count */ uchar pad4[2]; ushort ptr0; /* packet pointer */ uchar pad5[2]; ushort ptr1; uchar pad6[2]; ushort fsize; /* fragment size */ uchar pad7[2]; ushort link; /* descriptor link */ } TXpkt; enum{ Eol = 1, /* end of list bit in descriptor link */ Host = 0, /* descriptor belongs to host */ Interface = -1, /* descriptor belongs to interface */ Nether = 1, Ntypes= 8, }; /* * CAM Descriptor */ typedef struct { uchar pad0[2]; ushort cep; /* CAM entry pointer */ uchar pad1[2]; ushort cap0; /* CAM address port 0 */ uchar pad2[2]; ushort cap1; /* CAM address port 1 */ uchar pad3[2]; ushort cap2; /* CAM address port 2 */ uchar pad4[2]; ushort ce; /* CAM enable */ } Cam; typedef struct Ether Ether; | |
| 1993/0903 | struct Ether { uchar ea[6]; | |
| 1993/0904 | uchar ba[6]; | |
| 1993/0903 |
| |
| 1993/0904 | Sonic *sonic; /* SONIC registers */ | |
| 1993/0903 |
| |
| 1993/0904 | int th; /* first transmit buffer owned by host */ int ti; /* first transmit buffer owned by interface */ | |
| 1993/0903 | ||
| 1993/0904 | int rh; /* first receive buffer owned by host */ int ri; /* first receive buffer owned by interface */ RXrsc rra[Nrb]; /* receive resource area */ RXpkt rda[Nrb]; /* receive descriptor area */ uchar rb[Nrb][sizeof(Etherpkt)+4]; /* receive buffer area */ TXpkt tda[Ntb]; /* transmit descriptor area */ uchar tb[Ntb][sizeof(Etherpkt)]; /* transmit buffer area */ Cam cda; /* CAM descriptor area */ | |
| 1993/0903 | Netif; | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/0904 | Ether *ether[Nether]; | |
| 1993/0903 |
| |
| 1993/0904 | #define NEXT(x, l) (((x)+1)%(l)) #define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) #define LS16(addr) (PADDR(addr) & 0xFFFF) #define MS16(addr) ((PADDR(addr)>>16) & 0xFFFF) | |
| 1993/0903 | static void | |
| 1993/0904 | reset(Ether *ctlr) | |
| 1993/0903 | { | |
| 1993/0904 | int i; | |
| 1993/0903 |
| |
| 1993/0904 | iprint("reset sonic dcr=#%lux mydcr=#%lux\n", RD(dcr), Sterm|Dw32|Lbr|Efm|W14tf); /* * Reset the SONIC, toggle the Rst bit. * Set the data config register for synchronous termination * and 32-bit data-path width. * Clear the descriptor and buffer area. */ WR(cr, Rst); WR(dcr, Sterm|Dw32|Lbr|Efm|W14tf); WR(cr, 0); | |
| 1993/0903 |
| |
| 1993/0904 | /* * Initialise the receive resource area (RRA) and * the receive descriptor area (RDA). * * We use a simple scheme of one packet per descriptor. * We achieve this by setting the EOBC register to be * 2 (16-bit words) less than the buffer size; * thus the size of the receive buffers must be sizeof(Etherpkt)+4. * Set up the receive descriptors as a ring. */ for(i = 0; i < Nrb; i++){ ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF; ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF; | |
| 1993/0903 |
| |
| 1993/0904 | ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); ctlr->rda[i].owner = Interface; | |
| 1993/0903 |
| |
| 1993/0904 | ctlr->rra[i].ptr0 = ctlr->rda[i].ptr0 = LS16(ctlr->rb[i]); ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]); } | |
| 1993/0903 |
| |
| 1993/0904 | /* * Terminate the receive descriptor ring * and load the SONIC registers to describe the RDA. | |
| 1993/0903 | */ | |
| 1993/0904 | ctlr->rda[Nrb-1].link |= Eol; | |
| 1993/0903 |
| |
| 1993/0904 | WR(crda, LS16(ctlr->rda)); WR(urda, MS16(ctlr->rda)); WR(eobc, sizeof(ctlr->rb[0])/2 - 2); | |
| 1993/0903 |
| |
| 1993/0904 | /* * Load the SONIC registers to describe the RRA. * We set the rwp to beyond the area delimited by rsa and * rea. This means that since we've already allocated all * the buffers, we'll never get a 'receive buffer area * exhausted' interrupt and the rrp will just wrap round. * Tell the SONIC to load the RRA and wait for * it to complete. */ WR(urra, MS16(&ctlr->rra[0])); WR(rsa, LS16(&ctlr->rra[0])); WR(rrp, LS16(&ctlr->rra[0])); WR(rea, LS16(&ctlr->rra[Nrb])); WR(rwp, LS16(&ctlr->rra[Nrb+1])); | |
| 1993/0903 |
| |
| 1993/0904 | iprint("wait rra\n"); WR(cr, Rrra); while(RD(cr) & Rrra) ; iprint("rra done\n"); /* * Initialise the transmit descriptor area (TDA). * Each descriptor describes one packet, we make no use * of having the packet in multiple fragments. * The descriptors are linked in a ring; overlapping transmission * with buffer queueing will cause some packets to * go out back-to-back. * * Load the SONIC registers to describe the TDA. */ for(i = 0; i < Ntb; i++){ ctlr->tda[i].status = Host; ctlr->tda[i].config = 0; ctlr->tda[i].count = 1; ctlr->tda[i].ptr0 = LS16(ctlr->tb[i]); ctlr->tda[i].ptr1 = MS16(ctlr->tb[i]); ctlr->tda[i].link = LS16(&ctlr->tda[NEXT(i, Ntb)]); } WR(ctda, LS16(&ctlr->tda[0])); WR(utda, MS16(&ctlr->tda[0])); /* * Initialise the software receive and transmit * ring indexes. */ ctlr->rh = 0; ctlr->ri = 0; ctlr->th = 0; ctlr->ti = 0; /* * Initialise the CAM descriptor area (CDA). * We only have one ethernet address to load, * broadcast is defined by the SONIC as all 1s. * * Load the SONIC registers to describe the CDA. * Tell the SONIC to load the CDA and wait for it * to complete. */ ctlr->cda.cep = 0; ctlr->cda.cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; ctlr->cda.cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; ctlr->cda.cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; ctlr->cda.ce = 1; WR(cdp, LS16(&ctlr->cda)); WR(cdc, 1); WR(cr, Lcam); while(RD(cr) & Lcam) ; /* * Configure the receive control, transmit control * and interrupt-mask registers. * The SONIC is now initialised, but not enabled. */ WR(rcr, Err|Rnt|Brd); WR(tcr, 0); WR(imr, AllIntr); iprint("reset done\n"); | |
| 1993/0903 | } void etherintr(void) { | |
| 1993/0904 | Ether *ctlr; ulong status; TXpkt *txpkt; RXpkt *rxpkt; Etherpkt *p; Netfile *f, **fp; | |
| 1993/0903 |
| |
| 1993/0904 | ctlr = ether[0]; | |
| 1993/0903 |
| |
| 1993/0904 | for(;;) { status = RD(isr) & AllIntr; if(status == 0) break; WR(isr, status); /* * Transmission complete, for good or bad. */ if(status & (Txdn|Txer)){ txpkt = &ctlr->tda[ctlr->ti]; while(txpkt->status != Host){ if(txpkt->status == Interface){ WR(ctda, LS16(txpkt)); WR(cr, Txp); break; } if((txpkt->status & Ptx) == 0) ctlr->oerrs++; txpkt->status = Host; ctlr->ti = NEXT(ctlr->ti, Ntb); txpkt = &ctlr->tda[ctlr->ti]; } status &= ~(Txdn|Txer); | |
| 1993/0903 | } | |
| 1993/0904 | if((status & (Pktrx|Rde)) == 0) goto noinput; /* * A packet arrived or we ran out of descriptors. */ status &= ~(Pktrx|Rde); rxpkt = &ctlr->rda[ctlr->rh]; while(rxpkt->owner == Host){ ctlr->inpackets++; /* * If the packet was received OK, pass it up, * otherwise log the error. * SONIC gives us the CRC in the packet, so * remember to subtract it from the length. */ if(rxpkt->status & Prx) { x = (rxpkt->count & 0xFFFF)-4; p = (Etherpkt*)ctlr->rb[ctlr->rh]; t = (p->type[0]<<8) | p->type[1]; for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++){ f = *fp; if(f == 0) continue; if(f->type == t || f->type < 0) qproduce(f->in, p->d, x); } | |
| 1993/0903 | } | |
| 1993/0904 | else if(rxpkt->status & Fae) ctlr->frames++; else if(rxpkt->status & Crc) ctlr->crcs++; else ctlr->buffs++; /* * Finished with this packet, it becomes the * last free packet in the ring, so give it Eol, * and take the Eol bit off the previous packet. * Move the ring index on. */ rxpkt->link |= Eol; rxpkt->owner = Interface; ctlr->rda[PREV(ctlr->rh, Nrb)].link &= ~Eol; ctlr->rh = NEXT(ctlr->rh, Nrb); rxpkt = &ctlr->rda[ctlr->rh]; | |
| 1993/0903 | } | |
| 1993/0904 | status &= ~(Pktrx|Rde); | |
| 1993/0903 | ||
| 1993/0904 | noinput: | |
| 1993/0903 | /* | |
| 1993/0904 | * We get a 'load CAM done' interrupt * after initialisation. Ignore it. | |
| 1993/0903 | */ | |
| 1993/0904 | if(status & Lcd) status &= ~Lcd; /* * Warnings that something is afoot. */ if(status & Hbl){ print("sonic: cd heartbeat lost\n"); status &= ~Hbl; | |
| 1993/0903 | } | |
| 1993/0904 | if(status & Br){ print("sonic: bus retry occurred\n"); status &= ~Br; } if(status & AllIntr) print("sonic %ux\n", status); | |
| 1993/0903 | } | |
| 1993/0903/sys/src/9/carrera/devether.c:278,352 – 1993/0904/sys/src/9/carrera/devether.c:489,533 | ||
| 1993/0903 | static void promiscuous(void *arg, int on) { | |
| 1993/0904 | ushort reg; | |
| 1993/0903 | USED(arg); | |
| 1993/0904 | reg = RD(rcr); | |
| 1993/0903 | if(on) | |
| 1993/0904 | WR(rcr, reg|Pro); | |
| 1993/0903 | else | |
| 1993/0904 | WR(rcr, reg&~Pro); | |
| 1993/0903 | } void etherreset(void) { | |
| 1993/0904 | Ether *ctlr; | |
| 1993/0903 |
| |
| 1993/0904 | /* * Map the device registers and allocate * memory for the receive/transmit rings. * Set the physical ethernet address and * prime the interrupt handler. */ if(ether[0] == 0) { ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024); /* memmove(ether[0]->ea, eeprom.ea, sizeof(ether[0]->ea)); */ | |
| 1993/0903 | } | |
| 1993/0904 | ctlr = ether[0]; | |
| 1993/0903 |
| |
| 1993/0904 | reset(ctlr); | |
| 1993/0903 |
| |
| 1993/0904 | memset(ctlr->ba, 0xFF, sizeof(ctlr->ba)); | |
| 1993/0903 | /* general network interface structure */ | |
| 1993/0904 | netifinit(ether[0], "ether", Ntypes, 32*1024); ether[0]->alen = 6; memmove(ether[0]->addr, ether[0]->ea, 6); memmove(ether[0]->bcast, ctlr->ba, 6); ether[0]->promiscuous = promiscuous; ether[0]->arg = ether[0]; | |
| 1993/0903 | } void | |
| 1993/0903/sys/src/9/carrera/devether.c:369,381 – 1993/0904/sys/src/9/carrera/devether.c:550,562 | ||
| 1993/0903 | int etherwalk(Chan *c, char *name) { | |
| 1993/0904 | return netifwalk(ether[0], c, name); | |
| 1993/0903 | } Chan* etheropen(Chan *c, int omode) { | |
| 1993/0904 | return netifopen(ether[0], c, omode); | |
| 1993/0903 | } void | |
| 1993/0903/sys/src/9/carrera/devether.c:387,416 – 1993/0904/sys/src/9/carrera/devether.c:568,596 | ||
| 1993/0903 | void etherclose(Chan *c) { | |
| 1993/0904 | netifclose(ether[0], c); | |
| 1993/0903 | } long etherread(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0904 | return netifread(ether[0], c, buf, n, offset); | |
| 1993/0903 | } static int isoutbuf(void *arg) { | |
| 1993/0904 | Ether *ctlr = arg; | |
| 1993/0903 |
| |
| 1993/0904 | return ctlr->tda[ctlr->th].status == Host; | |
| 1993/0903 | } long etherwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0904 | Etherpkt *p; TXpkt *txpkt; Ether *ctlr = ether[0]; | |
| 1993/0903 | USED(offset); | |
| 1993/0903/sys/src/9/carrera/devether.c:419,445 – 1993/0904/sys/src/9/carrera/devether.c:599,632 | ||
| 1993/0903 | /* etherif.c handles structure */ if(NETTYPE(c->qid.path) != Ndataqid) | |
| 1993/0904 | return netifwrite(ether[0], c, buf, n); | |
| 1993/0903 | /* we handle data */ | |
| 1993/0904 | qlock(&ctlr->tlock); tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); if(!isoutbuf(ctlr)){ | |
| 1993/0903 | print("ether transmitter jammed\n"); | |
| 1993/0904 | } else { p =(Etherpkt*)ctlr->tb[ctlr->th]; | |
| 1993/0903 | memmove(p->d, buf, n); if(n < 60) { memset(p->d+n, 0, 60-n); n = 60; } | |
| 1993/0904 | memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); txpkt = &ctlr->tda[ctlr->th]; txpkt->size = n; txpkt->fsize = n; txpkt->link |= Eol; txpkt->status = Interface; ctlr->tda[PREV(ctlr->th, Ntb)].link &= ~Eol; ctlr->th = NEXT(ctlr->th, Ntb); WR(cr, Txp); | |
| 1993/0903 | } | |
| 1993/0904 | qunlock(&ctlr->tlock); | |
| 1993/0903 | return n; } | |
| 1993/0903/sys/src/9/carrera/devether.c:452,462 – 1993/0904/sys/src/9/carrera/devether.c:639,649 | ||
| 1993/0903 | void etherstat(Chan *c, char *dp) { | |
| 1993/0904 | netifstat(ether[0], c, dp); | |
| 1993/0903 | } void etherwstat(Chan *c, char *dp) { | |
| 1993/0904 | netifwstat(ether[0], c, dp); | |
| 1993/0903 | } | |
| 1993/0904/sys/src/9/carrera/devether.c:17,22 – 1993/0905/sys/src/9/carrera/devether.c:17,23 (short | long) | ||
| 1993/0903 | ||
| 1993/0904 | #define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v) | |
| 1993/0905 | #define ISquad(s) if((ulong)s & 0x7) panic("sonoc: Quad alignment"); | |
| 1993/0903 | ||
| 1993/0904 | typedef struct { | |
| 1993/0904/sys/src/9/carrera/devether.c:177,189 – 1993/0905/sys/src/9/carrera/devether.c:178,191 | ||
| 1993/0904 | Interface = -1, /* descriptor belongs to interface */ Nether = 1, | |
| 1993/0905 | Ntypes = 8, | |
| 1993/0904 | }; /* * CAM Descriptor */ | |
| 1993/0905 | typedef struct { | |
| 1993/0904 | uchar pad0[2]; ushort cep; /* CAM entry pointer */ uchar pad1[2]; | |
| 1993/0904/sys/src/9/carrera/devether.c:234,240 – 1993/0905/sys/src/9/carrera/devether.c:236,241 | ||
| 1993/0903 | { | |
| 1993/0904 | int i; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0904/sys/src/9/carrera/devether.c:242,248 – 1993/0905/sys/src/9/carrera/devether.c:243,250 | ||
| 1993/0904 | * Clear the descriptor and buffer area. */ WR(cr, Rst); | |
| 1993/0905 | WR(dcr, 0x2423); /* 5-19 Carrera manual */ iprint("eobc #%lux\n", RD(eobc)); | |
| 1993/0904 | WR(cr, 0); | |
| 1993/0903 | ||
| 1993/0904 | /* | |
| 1993/0904/sys/src/9/carrera/devether.c:255,261 – 1993/0905/sys/src/9/carrera/devether.c:257,263 | ||
| 1993/0904 | * thus the size of the receive buffers must be sizeof(Etherpkt)+4. * Set up the receive descriptors as a ring. */ | |
| 1993/0905 | for(i = 0; i < Nrb; i++) { | |
| 1993/0904 | ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF; ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF; | |
| 1993/0903 | ||
| 1993/0904/sys/src/9/carrera/devether.c:266,271 – 1993/0905/sys/src/9/carrera/devether.c:268,277 | ||
| 1993/0904 | ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]); } | |
| 1993/0903 | ||
| 1993/0905 | ISquad(ctlr->rra); ISquad(ctlr->rda); ISquad(ctlr->rb); | |
| 1993/0904 | /* * Terminate the receive descriptor ring * and load the SONIC registers to describe the RDA. | |
| 1993/0904/sys/src/9/carrera/devether.c:275,280 – 1993/0905/sys/src/9/carrera/devether.c:281,287 | ||
| 1993/0904 | WR(crda, LS16(ctlr->rda)); WR(urda, MS16(ctlr->rda)); WR(eobc, sizeof(ctlr->rb[0])/2 - 2); | |
| 1993/0905 | iprint("eobc #%lux\n", RD(eobc)); | |
| 1993/0903 | ||
| 1993/0904 | /* * Load the SONIC registers to describe the RRA. | |
| 1993/0904/sys/src/9/carrera/devether.c:291,301 – 1993/0905/sys/src/9/carrera/devether.c:298,306 | ||
| 1993/0904 | WR(rea, LS16(&ctlr->rra[Nrb])); WR(rwp, LS16(&ctlr->rra[Nrb+1])); | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0904/sys/src/9/carrera/devether.c:358,367 – 1993/0905/sys/src/9/carrera/devether.c:363,390 | ||
| 1993/0904 | WR(rcr, Err|Rnt|Brd); WR(tcr, 0); WR(imr, AllIntr); | |
| 1993/0903 | } void | |
| 1993/0905 | pxp(RXpkt *rxpkt) { print("%lux %lux\n", rxpkt->pad0[0], rxpkt->pad0[1]); print("status %lux\n", rxpkt->status); /* receive status */ print("%lux %lux\n", rxpkt->pad1[0], rxpkt->pad1[1]); print("count %lux\n", rxpkt->count); /* packet byte count */ print("%lux %lux\n", rxpkt->pad2[0], rxpkt->pad2[1]); print("ptr0 %lux\n", rxpkt->ptr0); /* buffer pointer */ print("%lux %lux\n", rxpkt->pad3[0], rxpkt->pad3[1]); print("ptr1 %lux\n", rxpkt->ptr1); print("%lux %lux\n", rxpkt->pad4[0], rxpkt->pad4[1]); print("seqno %lux\n", rxpkt->seqno); /* */ print("%lux %lux\n", rxpkt->pad5[0], rxpkt->pad5[1]); print("link %lux\n", rxpkt->link); /* descriptor link and EOL */ print("%lux %lux\n", rxpkt->pad6[0], rxpkt->pad6[1]); print("owner %lux\n", rxpkt->owner); /* in use */ } void | |
| 1993/0903 | etherintr(void) { int x; | |
| 1993/0904/sys/src/9/carrera/devether.c:379,384 – 1993/0905/sys/src/9/carrera/devether.c:402,408 | ||
| 1993/0904 | status = RD(isr) & AllIntr; if(status == 0) break; | |
| 1993/0905 | print("s %lux\n", status); | |
| 1993/0904 | WR(isr, status); | |
| 1993/0904/sys/src/9/carrera/devether.c:410,417 – 1993/0905/sys/src/9/carrera/devether.c:434,441 | ||
| 1993/0904 | /* * A packet arrived or we ran out of descriptors. */ | |
| 1993/0905 | pxp(rxpkt); | |
| 1993/0904 | while(rxpkt->owner == Host){ ctlr->inpackets++; | |
| 1993/0904/sys/src/9/carrera/devether.c:470,485 – 1993/0905/sys/src/9/carrera/devether.c:494,509 | ||
| 1993/0904 | * Warnings that something is afoot. */ if(status & Hbl){ | |
| 1993/0905 | iprint("sonic: cd heartbeat lost\n"); | |
| 1993/0904 | status &= ~Hbl; | |
| 1993/0903 | } | |
| 1993/0904 | if(status & Br){ | |
| 1993/0905 | iprint("sonic: bus retry occurred\n"); | |
| 1993/0904 | status &= ~Br; } if(status & AllIntr) | |
| 1993/0905 | iprint("sonic #%lux\n", status); | |
| 1993/0903 | } } | |
| 1993/0904/sys/src/9/carrera/devether.c:513,519 – 1993/0905/sys/src/9/carrera/devether.c:537,547 | ||
| 1993/0904 | */ if(ether[0] == 0) { ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024); | |
| 1993/0905 | if(PADDR(ether[0])+sizeof(Ether) > Ntranslation*BY2PG) panic("sonic: 16M io map"); enetaddr(ether[0]->ea); | |
| 1993/0903 | } | |
| 1993/0904 | ctlr = ether[0]; | |
| 1993/0903 | ||
| 1993/0904/sys/src/9/carrera/devether.c:531,536 – 1993/0905/sys/src/9/carrera/devether.c:559,570 | ||
| 1993/0903 | } void | |
| 1993/0905 | enab(void) { WR(cr, Rxen); } void | |
| 1993/0903 | etherinit(void) { } | |
| 1993/0904/sys/src/9/carrera/devether.c:538,543 – 1993/0905/sys/src/9/carrera/devether.c:572,584 | ||
| 1993/0903 | Chan* etherattach(char *spec) { | |
| 1993/0905 | static int enable; if(enable == 0) { enable = 1; WR(cr, Rxen); } | |
| 1993/0903 | return devattach('l', spec); } | |
| 1993/0904/sys/src/9/carrera/devether.c:594,599 – 1993/0905/sys/src/9/carrera/devether.c:635,642 | ||
| 1993/0903 | USED(offset); | |
| 1993/0905 | iprint("ether tx\n"); | |
| 1993/0903 | if(n > ETHERMAXTU) error(Ebadarg); | |
| 1993/0904/sys/src/9/carrera/devether.c:604,612 – 1993/0905/sys/src/9/carrera/devether.c:647,655 | ||
| 1993/0903 | /* we handle data */ | |
| 1993/0904 | qlock(&ctlr->tlock); tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); | |
| 1993/0905 | if(!isoutbuf(ctlr)) | |
| 1993/0903 | print("ether transmitter jammed\n"); | |
| 1993/0904 |
| |
| 1993/0903 | memmove(p->d, buf, n); | |
| 1993/0904/sys/src/9/carrera/devether.c:627,632 – 1993/0905/sys/src/9/carrera/devether.c:670,678 | ||
| 1993/0904 | WR(cr, Txp); | |
| 1993/0903 | } | |
| 1993/0904 | qunlock(&ctlr->tlock); | |
| 1993/0905 | iprint("tx done %d\n", n); | |
| 1993/0903 | return n; } | |
| 1993/0905/sys/src/9/carrera/devether.c:16,24 – 1993/0906/sys/src/9/carrera/devether.c:16,34 (short | long) | ||
| 1993/0904 | #define SONICADDR ((Sonic*)Sonicbase) | |
| 1993/0903 | ||
| 1993/0904 | #define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) | |
| 1993/0905 |
| |
| 1993/0906 | #define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) #define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment"); | |
| 1993/0903 | ||
| 1993/0906 | typedef struct Pbuf Pbuf; struct Pbuf { uchar d[6]; uchar s[6]; uchar type[2]; uchar data[1500]; uchar crc[4]; }; | |
| 1993/0904 | typedef struct { ulong cr; /* command */ | |
| 1993/0905/sys/src/9/carrera/devether.c:32,38 – 1993/0906/sys/src/9/carrera/devether.c:42,51 | ||
| 1993/0904 | ulong pad0x08[5]; /* */ ulong urda; /* upper receive descriptor address */ ulong crda; /* current receive descriptor address */ | |
| 1993/0906 | ulong crba0; /* DO NOT WRITE THESE */ ulong crba1; ulong rbwc0; ulong rbwc1; | |
| 1993/0904 | ulong eobc; /* end of buffer word count */ ulong urra; /* upper receive resource address */ ulong rsa; /* resource start address */ | |
| 1993/0905/sys/src/9/carrera/devether.c:111,116 – 1993/0906/sys/src/9/carrera/devether.c:124,132 | ||
| 1993/0904 | Hbl = 0x2000, /* CD heartbeat lost */ Br = 0x4000, /* bus retry occurred */ AllIntr = 0x7771, /* all of the above */ | |
| 1993/0906 | Rxbuf = sizeof(Pbuf)+4, Txbuf = sizeof(Pbuf), | |
| 1993/0903 | }; | |
| 1993/0904 | /* | |
| 1993/0905/sys/src/9/carrera/devether.c:118,131 – 1993/0906/sys/src/9/carrera/devether.c:134,147 | ||
| 1993/0904 | */ typedef struct { | |
| 1993/0906 | ushort pad1; ushort ptr1; /* buffer pointer in the RRA */ ushort pad2; ushort ptr0; ushort pad3; ushort wc1; /* buffer word count in the RRA */ ushort pad4; ushort wc0; | |
| 1993/0904 | } RXrsc; | |
| 1993/0903 | /* | |
| 1993/0905/sys/src/9/carrera/devether.c:133,152 – 1993/0906/sys/src/9/carrera/devether.c:149,169 | ||
| 1993/0903 | */ typedef struct { | |
| 1993/0904 |
| |
| 1993/0906 | ushort pad0; ushort count; /* packet byte count */ ushort pad1; ushort status; /* receive status */ ushort pad2; ushort ptr1; /* buffer pointer */ ushort pad3; ushort ptr0; ushort pad4; ushort link; /* descriptor link and EOL */ ushort pad5; ushort seqno; /* */ ulong pad6; ushort pad7; ushort owner; /* in use */ | |
| 1993/0904 | } RXpkt; | |
| 1993/0903 | ||
| 1993/0904 | /* | |
| 1993/0905/sys/src/9/carrera/devether.c:154,175 – 1993/0906/sys/src/9/carrera/devether.c:171,192 | ||
| 1993/0904 | */ typedef struct { | |
| 1993/0906 | ushort pad1; ushort config; /* */ ushort pad0; ushort status; /* transmit status */ ushort pad3; ushort count; /* fragment count */ ushort pad2; ushort size; /* byte count of entire packet */ ushort pad5; ushort ptr1; ushort pad4; ushort ptr0; /* packet pointer */ ushort pad7; ushort link; /* descriptor link */ ushort pad6; ushort fsize; /* fragment size */ | |
| 1993/0904 | } TXpkt; enum{ | |
| 1993/0905/sys/src/9/carrera/devether.c:186,201 – 1993/0906/sys/src/9/carrera/devether.c:203,219 | ||
| 1993/0904 | */ | |
| 1993/0905 | typedef struct { | |
| 1993/0904 |
| |
| 1993/0906 | ushort pad0; ushort cap0; /* CAM address port 0 */ ushort pad1; ushort cep; /* CAM entry pointer */ ushort pad2; ushort cap2; /* CAM address port 2 */ ushort pad3; ushort cap1; /* CAM address port 1 */ ulong pad4; ushort pad5; ushort ce; /* CAM enable */ | |
| 1993/0904 | } Cam; typedef struct Ether Ether; | |
| 1993/0905/sys/src/9/carrera/devether.c:204,211 – 1993/0906/sys/src/9/carrera/devether.c:222,227 | ||
| 1993/0903 | uchar ea[6]; | |
| 1993/0904 | uchar ba[6]; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 | int th; /* first transmit buffer owned by host */ | |
| 1993/0905/sys/src/9/carrera/devether.c:214,226 – 1993/0906/sys/src/9/carrera/devether.c:230,243 | ||
| 1993/0904 | int rh; /* first receive buffer owned by host */ int ri; /* first receive buffer owned by interface */ | |
| 1993/0906 | RXrsc *rra; /* receive resource area */ RXpkt *rda; /* receive descriptor area */ TXpkt *tda; /* transmit descriptor area */ Cam *cda; /* CAM descriptor area */ | |
| 1993/0904 | ||
| 1993/0906 | uchar *rb[Nrb]; /* receive buffer area */ uchar *tb[Ntb]; /* transmit buffer area */ | |
| 1993/0903 | Netif; | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/0905/sys/src/9/carrera/devether.c:231,251 – 1993/0906/sys/src/9/carrera/devether.c:248,276 | ||
| 1993/0904 | #define LS16(addr) (PADDR(addr) & 0xFFFF) #define MS16(addr) ((PADDR(addr)>>16) & 0xFFFF) | |
| 1993/0906 | void sonicswap(void*, int); | |
| 1993/0903 | static void | |
| 1993/0906 | wus(ushort *a, ushort v) { a[0] = v; a[-1] = v; } static void | |
| 1993/0904 | reset(Ether *ctlr) | |
| 1993/0903 | { | |
| 1993/0904 | int i; | |
| 1993/0906 | ushort lolen, hilen, loadr, hiadr; | |
| 1993/0903 | ||
| 1993/0904 | /* * Reset the SONIC, toggle the Rst bit. * Set the data config register for synchronous termination * and 32-bit data-path width. | |
| 1993/0906 | * Setup the descriptor and buffer area. | |
| 1993/0904 | */ WR(cr, Rst); | |
| 1993/0905 | WR(dcr, 0x2423); /* 5-19 Carrera manual */ | |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 | /* * Initialise the receive resource area (RRA) and | |
| 1993/0905/sys/src/9/carrera/devether.c:254,276 – 1993/0906/sys/src/9/carrera/devether.c:279,312 | ||
| 1993/0904 | * We use a simple scheme of one packet per descriptor. * We achieve this by setting the EOBC register to be * 2 (16-bit words) less than the buffer size; | |
| 1993/0906 | * thus the size of the receive buffers must be sizeof(Pbuf)+4. | |
| 1993/0904 | * Set up the receive descriptors as a ring. */ | |
| 1993/0906 | lolen = (Rxbuf/2) & 0xFFFF; hilen = ((Rxbuf/2)>>16) & 0xFFFF; | |
| 1993/0905 | for(i = 0; i < Nrb; i++) { | |
| 1993/0904 |
| |
| 1993/0906 | wus(&ctlr->rra[i].wc0, lolen); wus(&ctlr->rra[i].wc1, hilen); | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 | ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); | |
| 1993/0904 | ctlr->rda[i].owner = Interface; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 | loadr = LS16(ctlr->rb[i]); wus(&ctlr->rra[i].ptr0, loadr); wus(&ctlr->rda[i].ptr0, loadr); hiadr = MS16(ctlr->rb[i]); wus(&ctlr->rra[i].ptr1, hiadr); wus(&ctlr->rda[i].ptr1, hiadr); | |
| 1993/0904 | } | |
| 1993/0903 | ||
| 1993/0906 | /* * Check the important resources are QUAD aligned */ | |
| 1993/0905 | ISquad(ctlr->rra); ISquad(ctlr->rda); | |
| 1993/0904 | /* * Terminate the receive descriptor ring | |
| 1993/0905/sys/src/9/carrera/devether.c:280,287 – 1993/0906/sys/src/9/carrera/devether.c:316,322 | ||
| 1993/0903 | ||
| 1993/0904 | WR(crda, LS16(ctlr->rda)); WR(urda, MS16(ctlr->rda)); | |
| 1993/0905 |
| |
| 1993/0906 | WR(eobc, Rxbuf/2 - 2); | |
| 1993/0903 | ||
| 1993/0904 | /* * Load the SONIC registers to describe the RRA. | |
| 1993/0905/sys/src/9/carrera/devether.c:289,296 – 1993/0906/sys/src/9/carrera/devether.c:324,329 | ||
| 1993/0904 | * rea. This means that since we've already allocated all * the buffers, we'll never get a 'receive buffer area * exhausted' interrupt and the rrp will just wrap round. | |
| 1993/0905/sys/src/9/carrera/devether.c:298,307 – 1993/0906/sys/src/9/carrera/devether.c:331,336 | ||
| 1993/0904 | WR(rea, LS16(&ctlr->rra[Nrb])); WR(rwp, LS16(&ctlr->rra[Nrb+1])); | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0905/sys/src/9/carrera/devether.c:339,356 – 1993/0906/sys/src/9/carrera/devether.c:368,393 | ||
| 1993/0904 | * broadcast is defined by the SONIC as all 1s. * * Load the SONIC registers to describe the CDA. | |
| 1993/0906 | ctlr->cda->cep = 0; ctlr->cda->cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; ctlr->cda->cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; ctlr->cda->cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; ctlr->cda->ce = 1; | |
| 1993/0904 |
| |
| 1993/0906 | WR(cdp, LS16(ctlr->cda)); | |
| 1993/0904 | WR(cdc, 1); | |
| 1993/0906 | /* * End the reset * Load the Resource Descriptors and Cam contents */ WR(cr, 0); WR(cr, Rrra); while(RD(cr) & Rrra) ; | |
| 1993/0904 | WR(cr, Lcam); while(RD(cr) & Lcam) ; | |
| 1993/0905/sys/src/9/carrera/devether.c:366,408 – 1993/0906/sys/src/9/carrera/devether.c:403,444 | ||
| 1993/0903 | } void | |
| 1993/0905 |
| |
| 1993/0906 | sonicpkt(Ether *ctlr, RXpkt *r, Pbuf *p) | |
| 1993/0905 | { | |
| 1993/0906 | int len; ushort type; Netfile *f, **fp, **ep; /* * Sonic delivers CRC as part of the packet count */ len = (r->count & 0xFFFF)-4; sonicswap(p, len); type = (p->type[0]<<8) | p->type[1]; ep = &ctlr->f[Ntypes]; for(fp = ctlr->f; fp < ep; fp++) { f = *fp; if(f && (f->type == type || f->type < 0)) qproduce(f->in, p->d, len); } | |
| 1993/0905 | } void | |
| 1993/0903 | etherintr(void) { | |
| 1993/0904 |
| |
| 1993/0906 | Ether *c; | |
| 1993/0904 | ulong status; TXpkt *txpkt; RXpkt *rxpkt; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 | c = ether[0]; | |
| 1993/0903 | ||
| 1993/0904 | for(;;) { status = RD(isr) & AllIntr; if(status == 0) break; | |
| 1993/0905 |
| |
| 1993/0904 | WR(isr, status); | |
| 1993/0905/sys/src/9/carrera/devether.c:410,416 – 1993/0906/sys/src/9/carrera/devether.c:446,452 | ||
| 1993/0904 | * Transmission complete, for good or bad. */ if(status & (Txdn|Txer)){ | |
| 1993/0906 | txpkt = &c->tda[c->ti]; | |
| 1993/0904 | while(txpkt->status != Host){ if(txpkt->status == Interface){ WR(ctda, LS16(txpkt)); | |
| 1993/0905/sys/src/9/carrera/devether.c:419,429 – 1993/0906/sys/src/9/carrera/devether.c:455,465 | ||
| 1993/0904 | } if((txpkt->status & Ptx) == 0) | |
| 1993/0906 | c->oerrs++; | |
| 1993/0904 | txpkt->status = Host; | |
| 1993/0906 | c->ti = NEXT(c->ti, Ntb); txpkt = &c->tda[c->ti]; | |
| 1993/0904 | } status &= ~(Txdn|Txer); | |
| 1993/0903 | } | |
| 1993/0905/sys/src/9/carrera/devether.c:434,471 – 1993/0906/sys/src/9/carrera/devether.c:470,493 | ||
| 1993/0904 | /* * A packet arrived or we ran out of descriptors. */ | |
| 1993/0905 |
| |
| 1993/0906 | rxpkt = &c->rda[c->rh]; | |
| 1993/0904 | while(rxpkt->owner == Host){ | |
| 1993/0906 | c->inpackets++; | |
| 1993/0904 | /* * If the packet was received OK, pass it up, * otherwise log the error. | |
| 1993/0903 |
| |
| 1993/0906 | if(rxpkt->status & Prx) sonicpkt(c, rxpkt, (Pbuf*)c->rb[c->rh]); | |
| 1993/0904 | else if(rxpkt->status & Fae) | |
| 1993/0906 | c->frames++; | |
| 1993/0904 | else if(rxpkt->status & Crc) | |
| 1993/0906 | c->crcs++; | |
| 1993/0904 | else | |
| 1993/0906 | c->buffs++; | |
| 1993/0904 | /* * Finished with this packet, it becomes the | |
| 1993/0905/sys/src/9/carrera/devether.c:475,484 – 1993/0906/sys/src/9/carrera/devether.c:497,506 | ||
| 1993/0904 | */ rxpkt->link |= Eol; rxpkt->owner = Interface; | |
| 1993/0906 | c->rda[PREV(c->rh, Nrb)].link &= ~Eol; c->rh = NEXT(c->rh, Nrb); | |
| 1993/0904 |
| |
| 1993/0906 | rxpkt = &c->rda[c->rh]; | |
| 1993/0903 | } | |
| 1993/0904 | status &= ~(Pktrx|Rde); | |
| 1993/0903 | ||
| 1993/0905/sys/src/9/carrera/devether.c:494,509 – 1993/0906/sys/src/9/carrera/devether.c:516,531 | ||
| 1993/0904 | * Warnings that something is afoot. */ if(status & Hbl){ | |
| 1993/0905 |
| |
| 1993/0906 | print("sonic: cd heartbeat lost\n"); | |
| 1993/0904 | status &= ~Hbl; | |
| 1993/0903 | } | |
| 1993/0904 | if(status & Br){ | |
| 1993/0905 |
| |
| 1993/0906 | print("sonic: bus retry occurred\n"); | |
| 1993/0904 | status &= ~Br; } if(status & AllIntr) | |
| 1993/0905 |
| |
| 1993/0906 | print("sonic #%lux\n", status); | |
| 1993/0903 | } } | |
| 1993/0905/sys/src/9/carrera/devether.c:524,529 – 1993/0906/sys/src/9/carrera/devether.c:546,592 | ||
| 1993/0904 | WR(rcr, reg&~Pro); | |
| 1993/0903 | } | |
| 1993/0906 | static void initbufs(Ether *c) { int i; uchar *mem; mem = xspanalloc(64*1024, BY2PG, 0); mem = CACHELINE(uchar, mem); /* * Descriptors must be built in uncached space */ c->rra = UNCACHED(RXrsc, mem); mem = QUAD(uchar, mem+Nrb*sizeof(RXrsc)); c->rda = UNCACHED(RXpkt, mem); mem = QUAD(uchar, mem+Nrb*sizeof(RXpkt)); c->tda = UNCACHED(TXpkt, mem); mem = QUAD(uchar, mem+Ntb*sizeof(TXpkt)); c->cda = UNCACHED(Cam, mem); /* * DMA buffers are cache coherent - but we must not straddle * a cache line */ mem = CACHELINE(uchar, mem+sizeof(Cam)); for(i = 0; i < Nrb; i++) { c->rb[i] = UNCACHED(uchar, mem); mem += sizeof(Pbuf)+4; mem = QUAD(uchar, mem); } for(i = 0; i < Ntb; i++) { c->tb[i] = UNCACHED(uchar, mem); mem += sizeof(Pbuf); mem = QUAD(uchar, mem); } } | |
| 1993/0903 | void etherreset(void) { | |
| 1993/0905/sys/src/9/carrera/devether.c:535,546 – 1993/0906/sys/src/9/carrera/devether.c:598,608 | ||
| 1993/0904 | * Set the physical ethernet address and * prime the interrupt handler. */ | |
| 1993/0905 |
| |
| 1993/0906 | if(ether[0] == 0) { ctlr = malloc(sizeof(Ether)); ether[0] = ctlr; initbufs(ctlr); | |
| 1993/0905 | enetaddr(ether[0]->ea); | |
| 1993/0903 | } | |
| 1993/0904 | ctlr = ether[0]; | |
| 1993/0905/sys/src/9/carrera/devether.c:559,570 – 1993/0906/sys/src/9/carrera/devether.c:621,626 | ||
| 1993/0903 | } void | |
| 1993/0905 |
| |
| 1993/0903 | etherinit(void) { } | |
| 1993/0905/sys/src/9/carrera/devether.c:578,584 – 1993/0906/sys/src/9/carrera/devether.c:634,639 | ||
| 1993/0905 | enable = 1; WR(cr, Rxen); } | |
| 1993/0903 | return devattach('l', spec); } | |
| 1993/0905/sys/src/9/carrera/devether.c:629,642 – 1993/0906/sys/src/9/carrera/devether.c:684,695 | ||
| 1993/0903 | long etherwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0904 |
| |
| 1993/0906 | Pbuf *p; | |
| 1993/0904 | TXpkt *txpkt; Ether *ctlr = ether[0]; | |
| 1993/0903 | USED(offset); | |
| 1993/0905 |
| |
| 1993/0903 | if(n > ETHERMAXTU) error(Ebadarg); | |
| 1993/0905/sys/src/9/carrera/devether.c:651,657 – 1993/0906/sys/src/9/carrera/devether.c:704,710 | ||
| 1993/0905 | if(!isoutbuf(ctlr)) | |
| 1993/0903 | print("ether transmitter jammed\n"); | |
| 1993/0904 | else { | |
| 1993/0906 | p =(Pbuf*)ctlr->tb[ctlr->th]; | |
| 1993/0903 | memmove(p->d, buf, n); if(n < 60) { memset(p->d+n, 0, 60-n); | |
| 1993/0905/sys/src/9/carrera/devether.c:658,663 – 1993/0906/sys/src/9/carrera/devether.c:711,717 | ||
| 1993/0903 | n = 60; } | |
| 1993/0904 | memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); | |
| 1993/0906 | sonicswap(p, n); | |
| 1993/0904 | txpkt = &ctlr->tda[ctlr->th]; txpkt->size = n; | |
| 1993/0905/sys/src/9/carrera/devether.c:671,678 – 1993/0906/sys/src/9/carrera/devether.c:725,730 | ||
| 1993/0903 | } | |
| 1993/0904 | qunlock(&ctlr->tlock); | |
| 1993/0905 |
| |
| 1993/0903 | return n; } | |
| 1993/0905/sys/src/9/carrera/devether.c:692,695 – 1993/0906/sys/src/9/carrera/devether.c:744,766 | ||
| 1993/0903 | etherwstat(Chan *c, char *dp) { | |
| 1993/0904 | netifwstat(ether[0], c, dp); | |
| 1993/0906 | } #define swiz(s) (s<<24)|((s>>8)&0xff00)|((s<<8)&0xff0000)|(s>>24) void sonicswap(void *a, int n) { ulong *p, t0, t1; n = ((n+8)/8)*8; p = a; while(n) { t0 = p[0]; t1 = p[1]; p[0] = swiz(t1); p[1] = swiz(t0); p += 2; n -= 8; } | |
| 1993/0903 | } | |
| 1993/0906/sys/src/9/carrera/devether.c:462,467 – 1993/0918/sys/src/9/carrera/devether.c:462,468 (short | long) | ||
| 1993/0906 | txpkt = &c->tda[c->ti]; | |
| 1993/0904 | } status &= ~(Txdn|Txer); | |
| 1993/0918 | wakeup(&c->tr); | |
| 1993/0903 | } | |
| 1993/0904 | if((status & (Pktrx|Rde)) == 0) | |
| 1993/0906/sys/src/9/carrera/devether.c:699,704 – 1993/0918/sys/src/9/carrera/devether.c:700,710 | ||
| 1993/0903 | /* we handle data */ | |
| 1993/0904 | qlock(&ctlr->tlock); | |
| 1993/0918 | if(waserror()) { qunlock(&ctlr->tlock); nexterror(); } | |
| 1993/0904 | tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); | |
| 1993/0905 | if(!isoutbuf(ctlr)) | |
| 1993/0906/sys/src/9/carrera/devether.c:723,728 – 1993/0918/sys/src/9/carrera/devether.c:729,735 | ||
| 1993/0904 | ctlr->th = NEXT(ctlr->th, Ntb); WR(cr, Txp); | |
| 1993/0903 | } | |
| 1993/0918 | poperror(); | |
| 1993/0904 | qunlock(&ctlr->tlock); | |
| 1993/0905 | ||
| 1993/0903 | return n; | |
| 1993/0918/sys/src/9/carrera/devether.c:682,687 – 1993/1202/sys/src/9/carrera/devether.c:682,718 (short | long) | ||
| 1993/0904 | return ctlr->tda[ctlr->th].status == Host; | |
| 1993/0903 | } | |
| 1993/1202 | static int etherloop(Etherpkt *p, long n) { int s, different; ushort t; Netfile *f, **fp; different = memcmp(p->d, p->s, sizeof(p->s)); if(different && memcmp(p->d, ether.bcast, sizeof(p->d))) return 0; s = splhi(); t = (p->type[0]<<8) | p->type[1]; for(fp = ether.f; fp < ðer.f[Ntypes]; fp++) { f = *fp; if(f == 0) continue; if(f->type == t || f->type < 0) switch(qproduce(f->in, p->d, n)){ case -1: print("etherloop overflow\n"); break; case -2: print("etherloop memory\n"); break; } } splx(s); return !different; } | |
| 1993/0903 | long etherwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0918/sys/src/9/carrera/devether.c:699,704 – 1993/1202/sys/src/9/carrera/devether.c:730,738 | ||
| 1993/0904 | return netifwrite(ether[0], c, buf, n); | |
| 1993/0903 | /* we handle data */ | |
| 1993/1202 | if(etherloop(buf, n)) return n; | |
| 1993/0904 | qlock(&ctlr->tlock); | |
| 1993/0918 | if(waserror()) { qunlock(&ctlr->tlock); | |
| 1993/1202/sys/src/9/carrera/devether.c:690,701 – 1993/1208/sys/src/9/carrera/devether.c:690,701 (short | long) | ||
| 1993/1202 | Netfile *f, **fp; different = memcmp(p->d, p->s, sizeof(p->s)); | |
| 1993/1208 | if(different && memcmp(p->d, ether[0]->bcast, sizeof(p->d))) | |
| 1993/1202 | return 0; s = splhi(); t = (p->type[0]<<8) | p->type[1]; | |
| 1993/1208 | for(fp = ether[0]->f; fp < ðer[0]->f[Ntypes]; fp++) { | |
| 1993/1202 | f = *fp; if(f == 0) continue; | |
| 1993/1208/sys/src/9/carrera/devether.c:739,748 – 1993/1211/sys/src/9/carrera/devether.c:739,751 (short | long) | ||
| 1993/0918 | nexterror(); } | |
| 1993/0904 |
| |
| 1993/1211 | tsleep(&ctlr->tr, isoutbuf, ctlr, 1000); | |
| 1993/0905 |
| |
| 1993/1211 | if(!isoutbuf(ctlr)) { | |
| 1993/0903 | print("ether transmitter jammed\n"); | |
| 1993/1211 | reset(ctlr); WR(cr, Rxen); } | |
| 1993/0904 | else { | |
| 1993/0906 | p =(Pbuf*)ctlr->tb[ctlr->th]; | |
| 1993/0903 | memmove(p->d, buf, n); | |
| 1993/1211/sys/src/9/carrera/devether.c:75,81 – 1993/1212/sys/src/9/carrera/devether.c:75,81 (short | long) | ||
| 1993/0903 | enum { | |
| 1993/0904 | Nrb = 16, /* receive buffers */ | |
| 1993/1212 | Ntb = 16, /* transmit buffers */ | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/0904 | enum | |
| 1993/1211/sys/src/9/carrera/devether.c:425,430 – 1993/1212/sys/src/9/carrera/devether.c:425,438 | ||
| 1993/0906 | } | |
| 1993/0905 | } | |
| 1993/1212 | static int isoutbuf(void *arg) { Ether *ctlr = arg; return ctlr->tda[ctlr->th].status == Host; } | |
| 1993/0905 | void | |
| 1993/0903 | etherintr(void) { | |
| 1993/1211/sys/src/9/carrera/devether.c:462,468 – 1993/1212/sys/src/9/carrera/devether.c:470,477 | ||
| 1993/0906 | txpkt = &c->tda[c->ti]; | |
| 1993/0904 | } status &= ~(Txdn|Txer); | |
| 1993/0918 |
| |
| 1993/1212 | if(isoutbuf(c)) wakeup(&c->tr); | |
| 1993/0903 | } | |
| 1993/0904 | if((status & (Pktrx|Rde)) == 0) | |
| 1993/1211/sys/src/9/carrera/devether.c:514,520 – 1993/1212/sys/src/9/carrera/devether.c:523,529 | ||
| 1993/0904 | status &= ~Lcd; /* | |
| 1993/1212 | * Warnings that something is atoe. | |
| 1993/0904 | */ if(status & Hbl){ | |
| 1993/0906 | print("sonic: cd heartbeat lost\n"); | |
| 1993/1211/sys/src/9/carrera/devether.c:675,688 – 1993/1212/sys/src/9/carrera/devether.c:684,689 | ||
| 1993/0903 | } static int | |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/1202 |
| |
| 1993/1211/sys/src/9/carrera/devether.c:722,734 – 1993/1212/sys/src/9/carrera/devether.c:723,735 | ||
| 1993/0903 | USED(offset); | |
| 1993/0904 | return netifwrite(ether[0], c, buf, n); | |
| 1993/0903 | ||
| 1993/1212 | if(n > ETHERMAXTU) error(Ebadarg); | |
| 1993/0903 | /* we handle data */ | |
| 1993/1202 | if(etherloop(buf, n)) return n; | |
| 1993/1211/sys/src/9/carrera/devether.c:739,753 – 1993/1212/sys/src/9/carrera/devether.c:740,751 | ||
| 1993/0918 | nexterror(); } | |
| 1993/1211 |
| |
| 1993/1212 | tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); | |
| 1993/0905 | ||
| 1993/1211 |
| |
| 1993/0903 |
| |
| 1993/1211 |
| |
| 1993/1212 | if(!isoutbuf(ctlr)) print("ether transmitter jammed cr #%lux\n", RD(cr)); | |
| 1993/0904 | else { | |
| 1993/0906 |
| |
| 1993/1212 | p = (Pbuf*)ctlr->tb[ctlr->th]; | |
| 1993/0903 | memmove(p->d, buf, n); if(n < 60) { memset(p->d+n, 0, 60-n); | |
| 1993/1212/sys/src/9/carrera/devether.c:15,22 – 1993/1217/sys/src/9/carrera/devether.c:15,22 (short | long) | ||
| 1993/0903 | ||
| 1993/0904 | #define SONICADDR ((Sonic*)Sonicbase) | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/1217 | #define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) | |
| 1993/0906 | #define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment"); | |
| 1993/0903 | ||
| 1993/0906 | typedef struct Pbuf Pbuf; | |
| 1993/1212/sys/src/9/carrera/devether.c:74,81 – 1993/1217/sys/src/9/carrera/devether.c:74,81 | ||
| 1993/0903 | enum { | |
| 1993/0904 |
| |
| 1993/1212 |
| |
| 1993/1217 | Nrb = 8, /* receive buffers */ Ntb = 8, /* transmit buffers */ | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/0904 | enum | |
| 1993/1212/sys/src/9/carrera/devether.c:530,537 – 1993/1217/sys/src/9/carrera/devether.c:530,539 | ||
| 1993/0904 | status &= ~Hbl; | |
| 1993/0903 | } | |
| 1993/0904 | if(status & Br){ | |
| 1993/0906 |
| |
| 1993/1217 | WR(cr, 0); iprint("sonic: bus retry occurred\n"); | |
| 1993/0904 | status &= ~Br; | |
| 1993/1217 | for(;;); | |
| 1993/0904 | } if(status & AllIntr) | |
| 1993/1212/sys/src/9/carrera/devether.c:560,568 – 1993/1217/sys/src/9/carrera/devether.c:562,571 | ||
| 1993/0906 | initbufs(Ether *c) { int i; | |
| 1993/1217 | uchar *mem, *base; | |
| 1993/0906 | mem = xspanalloc(64*1024, BY2PG, 0); | |
| 1993/1217 | base = mem; | |
| 1993/0906 | mem = CACHELINE(uchar, mem); /* | |
| 1993/1212/sys/src/9/carrera/devether.c:595,600 – 1993/1217/sys/src/9/carrera/devether.c:598,605 | ||
| 1993/0906 | mem += sizeof(Pbuf); mem = QUAD(uchar, mem); } | |
| 1993/1217 | if(mem >= base+64*1024) panic("sonic init"); | |
| 1993/0906 | } | |
| 1993/0903 | void | |
| 1993/1217/sys/src/9/carrera/devether.c:15,22 – 1993/1218/sys/src/9/carrera/devether.c:15,22 (short | long) | ||
| 1993/0903 | ||
| 1993/0904 | #define SONICADDR ((Sonic*)Sonicbase) | |
| 1993/0903 | ||
| 1993/1217 |
| |
| 1993/1218 | #define RD(rn) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) | |
| 1993/0906 | #define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment"); | |
| 1993/0903 | ||
| 1993/0906 | typedef struct Pbuf Pbuf; | |
| 1993/1217/sys/src/9/carrera/devether.c:74,80 – 1993/1218/sys/src/9/carrera/devether.c:74,80 | ||
| 1993/0903 | enum { | |
| 1993/1217 |
| |
| 1993/1218 | Nrb = 16, /* receive buffers */ | |
| 1993/1217 | Ntb = 8, /* transmit buffers */ | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/1217/sys/src/9/carrera/devether.c:251,256 – 1993/1218/sys/src/9/carrera/devether.c:251,266 | ||
| 1993/0906 | void sonicswap(void*, int); | |
| 1993/0903 | static void | |
| 1993/1218 | sncdly(void) { int i, j, *pj; pj = &j; for(i = 0; i < 200; i++) *pj++; } static void | |
| 1993/0906 | wus(ushort *a, ushort v) { a[0] = v; | |
| 1993/1217/sys/src/9/carrera/devether.c:530,539 – 1993/1218/sys/src/9/carrera/devether.c:540,547 | ||
| 1993/0904 | status &= ~Hbl; | |
| 1993/0903 | } | |
| 1993/0904 | if(status & Br){ | |
| 1993/1217 |
| |
| 1993/1218 | print("sonic: bus retry occurred\n"); | |
| 1993/0904 | status &= ~Br; | |
| 1993/1217 |
| |
| 1993/0904 | } if(status & AllIntr) | |
| 1993/1218/sys/src/9/carrera/devether.c:15,22 – 1993/1219/sys/src/9/carrera/devether.c:15,22 (short | long) | ||
| 1993/0903 | ||
| 1993/0904 | #define SONICADDR ((Sonic*)Sonicbase) | |
| 1993/0903 | ||
| 1993/1218 |
| |
| 1993/1219 | #define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4)) #define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) | |
| 1993/0906 | #define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment"); | |
| 1993/0903 | ||
| 1993/0906 | typedef struct Pbuf Pbuf; | |
| 1993/1218/sys/src/9/carrera/devether.c:251,266 – 1993/1219/sys/src/9/carrera/devether.c:251,256 | ||
| 1993/0906 | void sonicswap(void*, int); | |
| 1993/0903 | static void | |
| 1993/1218 |
| |
| 1993/0906 | wus(ushort *a, ushort v) { a[0] = v; | |
| 1993/1218/sys/src/9/carrera/devether.c:458,469 – 1993/1219/sys/src/9/carrera/devether.c:448,460 | ||
| 1993/0904 | if(status == 0) break; | |
| 1993/1219 | /* Clear the interrupt cause */ | |
| 1993/0904 | WR(isr, status); /* * Transmission complete, for good or bad. */ | |
| 1993/1219 | if(status & (Txdn|Txer)) { | |
| 1993/0906 | txpkt = &c->tda[c->ti]; | |
| 1993/0904 | while(txpkt->status != Host){ if(txpkt->status == Interface){ | |
| 1993/1218/sys/src/9/carrera/devether.c:621,627 – 1993/1219/sys/src/9/carrera/devether.c:612,617 | ||
| 1993/0904 | * Set the physical ethernet address and * prime the interrupt handler. */ | |
| 1993/0905 | ||
| 1993/0906 | if(ether[0] == 0) { ctlr = malloc(sizeof(Ether)); ether[0] = ctlr; | |
| 1993/1219/sys/src/9/carrera/devether.c:563,569 – 1993/1231/sys/src/9/carrera/devether.c:563,569 (short | long) | ||
| 1993/0906 | int i; | |
| 1993/1217 | uchar *mem, *base; | |
| 1993/0906 |
| |
| 1993/1231 | mem = xspanalloc(64*1024, 8, 64*1024); | |
| 1993/1217 | base = mem; | |
| 1993/0906 | mem = CACHELINE(uchar, mem); | |
| 1993/1219/sys/src/9/carrera/devether.c:581,592 – 1993/1231/sys/src/9/carrera/devether.c:581,587 | ||
| 1993/0906 | c->cda = UNCACHED(Cam, mem); | |
| 1993/1231/sys/src/9/carrera/devether.c:271,276 – 1994/0107/sys/src/9/carrera/devether.c:271,277 (short | long) | ||
| 1993/0904 | */ WR(cr, Rst); | |
| 1993/0905 | WR(dcr, 0x2423); /* 5-19 Carrera manual */ | |
| 1994/0107 | WR(cr, 0); | |
| 1993/0903 | ||
| 1993/0904 | /* * Initialise the receive resource area (RRA) and | |
| 1993/1231/sys/src/9/carrera/devether.c:379,389 – 1994/0107/sys/src/9/carrera/devether.c:380,387 | ||
| 1993/0904 | WR(cdc, 1); | |
| 1993/0906 | /* | |
| 1993/1231/sys/src/9/carrera/devether.c:397,403 – 1994/0107/sys/src/9/carrera/devether.c:395,401 | ||
| 1993/0904 | * and interrupt-mask registers. * The SONIC is now initialised, but not enabled. */ | |
| 1994/0107 | WR(rcr, Brd); | |
| 1993/0904 | WR(tcr, 0); WR(imr, AllIntr); | |
| 1993/0903 | } | |
| 1993/1231/sys/src/9/carrera/devether.c:437,442 – 1994/0107/sys/src/9/carrera/devether.c:435,441 | ||
| 1993/0903 | etherintr(void) { | |
| 1993/0906 | Ether *c; | |
| 1994/0107 | ushort *s; | |
| 1993/0904 | ulong status; TXpkt *txpkt; RXpkt *rxpkt; | |
| 1993/1231/sys/src/9/carrera/devether.c:448,455 – 1994/0107/sys/src/9/carrera/devether.c:447,466 | ||
| 1993/0904 | if(status == 0) break; | |
| 1993/1219 |
| |
| 1993/0904 |
| |
| 1994/0107 | /* * Warnings that something is atoe. */ if(status & Hbl){ WR(isr, Hbl); status &= ~Hbl; print("sonic: cd heartbeat lost\n"); } if(status & Br){ WR(cr, Rst); print("sonic: bus retry occurred\n"); (*(void(*)(void))0xA001C020)(); status &= ~Br; } | |
| 1993/0904 | /* * Transmission complete, for good or bad. | |
| 1993/1231/sys/src/9/carrera/devether.c:470,475 – 1994/0107/sys/src/9/carrera/devether.c:481,487 | ||
| 1993/0906 | c->ti = NEXT(c->ti, Ntb); txpkt = &c->tda[c->ti]; | |
| 1993/0904 | } | |
| 1994/0107 | WR(isr, status & (Txdn|Txer)); | |
| 1993/0904 | status &= ~(Txdn|Txer); | |
| 1993/1212 | if(isoutbuf(c)) wakeup(&c->tr); | |
| 1993/1231/sys/src/9/carrera/devether.c:500,505 – 1994/0107/sys/src/9/carrera/devether.c:512,518 | ||
| 1993/0904 | else | |
| 1993/0906 | c->buffs++; | |
| 1993/0904 | ||
| 1994/0107 | rxpkt->status = 0; | |
| 1993/0904 | /* * Finished with this packet, it becomes the * last free packet in the ring, so give it Eol, | |
| 1993/1231/sys/src/9/carrera/devether.c:506,518 – 1994/0107/sys/src/9/carrera/devether.c:519,533 | ||
| 1993/0904 | * and take the Eol bit off the previous packet. * Move the ring index on. */ | |
| 1994/0107 | wus(&rxpkt->link, rxpkt->link|Eol); | |
| 1993/0904 | rxpkt->owner = Interface; | |
| 1993/0906 |
| |
| 1994/0107 | s = &c->rda[PREV(c->rh, Nrb)].link; wus(s, *s & ~Eol); | |
| 1993/0906 | c->rh = NEXT(c->rh, Nrb); | |
| 1993/0904 | ||
| 1993/0906 | rxpkt = &c->rda[c->rh]; | |
| 1993/0903 | } | |
| 1994/0107 | WR(isr, status & (Pktrx|Rde)); | |
| 1993/0904 | status &= ~(Pktrx|Rde); | |
| 1993/0903 | ||
| 1993/0904 | noinput: | |
| 1993/1231/sys/src/9/carrera/devether.c:520,542 – 1994/0107/sys/src/9/carrera/devether.c:535,549 | ||
| 1993/0904 | * We get a 'load CAM done' interrupt * after initialisation. Ignore it. | |
| 1993/0903 | */ | |
| 1993/0904 |
| |
| 1994/0107 | if(status & Lcd) { WR(isr, Lcd); | |
| 1993/0904 | status &= ~Lcd; | |
| 1993/1212 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0903 | } | |
| 1993/0904 |
| |
| 1993/1218 |
| |
| 1993/0904 |
| |
| 1994/0107 | if(status & AllIntr) { WR(isr, status); | |
| 1993/0906 | print("sonic #%lux\n", status); | |
| 1994/0107 | } | |
| 1993/0903 | } } | |
| 1993/1231/sys/src/9/carrera/devether.c:716,721 – 1994/0107/sys/src/9/carrera/devether.c:723,729 | ||
| 1993/0903 | etherwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0906 | Pbuf *p; | |
| 1994/0107 | ushort *s; | |
| 1993/0904 | TXpkt *txpkt; Ether *ctlr = ether[0]; | |
| 1993/0903 | ||
| 1993/1231/sys/src/9/carrera/devether.c:733,738 – 1994/0107/sys/src/9/carrera/devether.c:741,747 | ||
| 1993/1202 | return n; | |
| 1993/0904 | qlock(&ctlr->tlock); | |
| 1994/0107 | ctlr->outpackets++; | |
| 1993/0918 | if(waserror()) { qunlock(&ctlr->tlock); nexterror(); | |
| 1993/1231/sys/src/9/carrera/devether.c:755,763 – 1994/0107/sys/src/9/carrera/devether.c:764,773 | ||
| 1993/0904 | txpkt = &ctlr->tda[ctlr->th]; txpkt->size = n; txpkt->fsize = n; | |
| 1994/0107 | wus(&txpkt->link, txpkt->link|Eol); | |
| 1993/0904 | txpkt->status = Interface; | |
| 1994/0107 | s = &ctlr->tda[PREV(ctlr->th, Ntb)].link; wus(s, *s & ~Eol); | |
| 1993/0904 | ctlr->th = NEXT(ctlr->th, Ntb); WR(cr, Txp); | |
| 1994/0107/sys/src/9/carrera/devether.c:570,576 – 1994/0524/sys/src/9/carrera/devether.c:570,579 (short | long) | ||
| 1993/0906 | int i; | |
| 1993/1217 | uchar *mem, *base; | |
| 1993/0906 | ||
| 1993/1231 |
| |
| 1994/0524 | /* Put the ethernet buffers in the same place * as the bootrom */ mem = (void*)(KZERO|0x2000); | |
| 1993/1217 | base = mem; | |
| 1993/0906 | mem = CACHELINE(uchar, mem); | |
| 1994/0524/sys/src/9/carrera/devether.c:691,696 – 1995/0108/sys/src/9/carrera/devether.c:691,702 (short | long) | ||
| 1993/0904 | return netifread(ether[0], c, buf, n, offset); | |
| 1993/0903 | } | |
| 1995/0108 | Block* etherbread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } | |
| 1993/0903 | static int | |
| 1993/1202 | etherloop(Etherpkt *p, long n) { | |
| 1994/0524/sys/src/9/carrera/devether.c:779,784 – 1995/0108/sys/src/9/carrera/devether.c:785,796 | ||
| 1993/0904 | qunlock(&ctlr->tlock); | |
| 1993/0905 | ||
| 1993/0903 | return n; | |
| 1995/0108 | } long etherbwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); | |
| 1993/0903 | } void | |
| 1995/0108/sys/src/9/carrera/devether.c:703,716 – 1995/0114/sys/src/9/carrera/devether.c:703,717 (short | long) | ||
| 1993/1202 | int s, different; ushort t; Netfile *f, **fp; | |
| 1995/0114 | Ether *ctlr = ether[0]; | |
| 1993/1202 |
| |
| 1993/1208 |
| |
| 1995/0114 | different = memcmp(p->d, ctlr->ea, sizeof(ctlr->ea)); if(different && memcmp(p->d, ctlr->bcast, sizeof(p->d))) | |
| 1993/1202 | return 0; s = splhi(); t = (p->type[0]<<8) | p->type[1]; | |
| 1993/1208 |
| |
| 1995/0114 | for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++) { | |
| 1993/1202 | f = *fp; if(f == 0) continue; | |
| 1995/0108/sys/src/9/carrera/devether.c:745,750 – 1995/0114/sys/src/9/carrera/devether.c:746,754 | ||
| 1993/1212 | if(n > ETHERMAXTU) error(Ebadarg); | |
| 1995/0114 | p = buf; memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); | |
| 1993/0903 | /* we handle data */ | |
| 1993/1202 | if(etherloop(buf, n)) return n; | |
| 1995/0108/sys/src/9/carrera/devether.c:767,773 – 1995/0114/sys/src/9/carrera/devether.c:771,776 | ||
| 1993/0903 | memset(p->d+n, 0, 60-n); n = 60; } | |
| 1993/0904 |
| |
| 1993/0906 | sonicswap(p, n); | |
| 1993/0904 | txpkt = &ctlr->tda[ctlr->th]; | |
| 1995/0114/sys/src/9/carrera/devether.c:652,657 – 1995/0520/sys/src/9/carrera/devether.c:652,659 (short | long) | ||
| 1993/0905 | enable = 1; WR(cr, Rxen); } | |
| 1995/0520 | if(*spec && strcmp(spec, "0") != 0) error(Eio); | |
| 1993/0903 | return devattach('l', spec); } | |
| 1995/0520/sys/src/9/carrera/devether.c:241,247 – 1997/0327/sys/src/9/carrera/devether.c:241,247 (short | long) | ||
| 1993/0903 | Netif; | |
| 1993/0904 | }; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/0327 | static Ether *ether[Nether]; | |
| 1993/0903 | ||
| 1993/0904 | #define NEXT(x, l) (((x)+1)%(l)) #define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) | |
| 1995/0520/sys/src/9/carrera/devether.c:248,254 – 1997/0327/sys/src/9/carrera/devether.c:248,254 | ||
| 1993/0904 | #define LS16(addr) (PADDR(addr) & 0xFFFF) #define MS16(addr) ((PADDR(addr)>>16) & 0xFFFF) | |
| 1993/0906 |
| |
| 1997/0327 | static void sonicswap(void*, int); | |
| 1993/0906 | ||
| 1993/0903 | static void | |
| 1993/0906 | wus(ushort *a, ushort v) | |
| 1995/0520/sys/src/9/carrera/devether.c:400,406 – 1997/0327/sys/src/9/carrera/devether.c:400,406 | ||
| 1993/0904 | WR(imr, AllIntr); | |
| 1993/0903 | } | |
| 1997/0327 | static void | |
| 1993/0906 | sonicpkt(Ether *ctlr, RXpkt *r, Pbuf *p) | |
| 1993/0905 | { | |
| 1993/0906 | int len; | |
| 1995/0520/sys/src/9/carrera/devether.c:606,612 – 1997/0327/sys/src/9/carrera/devether.c:606,612 | ||
| 1993/1217 | panic("sonic init"); | |
| 1993/0906 | } | |
| 1993/0903 |
| |
| 1997/0327 | static void | |
| 1993/0903 | etherreset(void) { | |
| 1993/0904 | Ether *ctlr; | |
| 1995/0520/sys/src/9/carrera/devether.c:630,636 – 1997/0327/sys/src/9/carrera/devether.c:630,636 | ||
| 1993/0904 | memset(ctlr->ba, 0xFF, sizeof(ctlr->ba)); | |
| 1993/0903 | /* general network interface structure */ | |
| 1993/0904 |
| |
| 1997/0327 | netifinit(ether[0], "ether0", Ntypes, 32*1024); | |
| 1993/0904 | ether[0]->alen = 6; memmove(ether[0]->addr, ether[0]->ea, 6); memmove(ether[0]->bcast, ctlr->ba, 6); | |
| 1995/0520/sys/src/9/carrera/devether.c:638,649 – 1997/0327/sys/src/9/carrera/devether.c:638,644 | ||
| 1993/0904 | ether[0]->arg = ether[0]; | |
| 1993/0903 | } | |
| 1997/0327 | static Chan* | |
| 1993/0903 | etherattach(char *spec) { | |
| 1993/0905 | static int enable; | |
| 1995/0520/sys/src/9/carrera/devether.c:657,687 – 1997/0327/sys/src/9/carrera/devether.c:652,676 | ||
| 1993/0903 | return devattach('l', spec); } | |
| 1997/0327 | static int | |
| 1993/0903 | etherwalk(Chan *c, char *name) { | |
| 1993/0904 | return netifwalk(ether[0], c, name); | |
| 1993/0903 | } | |
| 1997/0327 | static Chan* | |
| 1993/0903 | etheropen(Chan *c, int omode) { | |
| 1993/0904 | return netifopen(ether[0], c, omode); | |
| 1993/0903 | } | |
| 1997/0327 | static void | |
| 1993/0903 | ethercreate(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); } | |
| 1997/0327 | static void | |
| 1993/0903 | etherclose(Chan *c) { | |
| 1993/0904 | netifclose(ether[0], c); | |
| 1995/0520/sys/src/9/carrera/devether.c:693,704 – 1997/0327/sys/src/9/carrera/devether.c:682,687 | ||
| 1993/0904 | return netifread(ether[0], c, buf, n, offset); | |
| 1993/0903 | } | |
| 1995/0108 |
| |
| 1993/0903 | static int | |
| 1993/1202 | etherloop(Etherpkt *p, long n) { | |
| 1995/0520/sys/src/9/carrera/devether.c:731,737 – 1997/0327/sys/src/9/carrera/devether.c:714,720 | ||
| 1993/1202 | return !different; } | |
| 1993/0903 |
| |
| 1997/0327 | static long | |
| 1993/0903 | etherwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1993/0906 | Pbuf *p; | |
| 1995/0520/sys/src/9/carrera/devether.c:792,816 – 1997/0327/sys/src/9/carrera/devether.c:775,793 | ||
| 1993/0903 | return n; | |
| 1995/0108 | } | |
| 1993/0903 |
| |
| 1997/0327 | static void | |
| 1993/0903 | etherremove(Chan *c) { USED(c); } | |
| 1997/0327 | static void | |
| 1993/0903 | etherstat(Chan *c, char *dp) { | |
| 1993/0904 | netifstat(ether[0], c, dp); | |
| 1993/0903 | } | |
| 1997/0327 | static void | |
| 1993/0903 | etherwstat(Chan *c, char *dp) { | |
| 1993/0904 | netifwstat(ether[0], c, dp); | |
| 1995/0520/sys/src/9/carrera/devether.c:818,824 – 1997/0327/sys/src/9/carrera/devether.c:795,801 | ||
| 1993/0906 | #define swiz(s) (s<<24)|((s>>8)&0xff00)|((s<<8)&0xff0000)|(s>>24) | |
| 1997/0327 | static void | |
| 1993/0906 | sonicswap(void *a, int n) { ulong *p, t0, t1; | |
| 1995/0520/sys/src/9/carrera/devether.c:834,836 – 1997/0327/sys/src/9/carrera/devether.c:811,854 | ||
| 1993/0906 | n -= 8; } | |
| 1993/0903 | } | |
| 1997/0327 | int parseether(uchar *to, char *from) { char nip[4]; char *p; int i; p = from; for(i = 0; i < 6; i++){ if(*p == 0) return -1; nip[0] = *p++; if(*p == 0) return -1; nip[1] = *p++; nip[2] = 0; to[i] = strtoul(nip, 0, 16); if(*p == ':') p++; } return 0; } Dev etherdevtab = { etherreset, devinit, etherattach, devclone, etherwalk, etherstat, etheropen, ethercreate, etherclose, etherread, devbread, etherwrite, devbwrite, etherremove, etherwstat, }; | |
| 1997/0327/sys/src/9/carrera/devether.c:836,841 – 1997/0408/sys/src/9/carrera/devether.c:836,844 (short | long) | ||
| 1997/0327 | } Dev etherdevtab = { | |
| 1997/0408 | 'l', "ether", | |
| 1997/0327 | etherreset, devinit, etherattach, | |
| 1997/0408/sys/src/9/carrera/devether.c:1,819 – 1997/1210/sys/src/9/carrera/devether.c:1,372 (short | long) | ||
| 1993/0903 |
| |
| 1997/1210 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" | |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | #include "etherif.h" | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/1210 | static Ether *etherxx[MaxEther]; | |
| 1993/0903 | ||
| 1993/1219 |
| |
| 1993/0906 |
| |
| 1993/0903 | ||
| 1993/0906 |
| |
| 1997/1210 | Chan* etherattach(char* spec) | |
| 1993/0906 | { | |
| 1997/1210 | ulong ctlrno; char *p; Chan *chan; | |
| 1993/0906 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1997/1210 | ctlrno = 0; if(spec && *spec){ ctlrno = strtoul(spec, &p, 0); if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) error(Ebadarg); } if(etherxx[ctlrno] == 0) error(Enodev); | |
| 1993/0903 |
| |
| 1993/1218 |
| |
| 1993/1217 |
| |
| 1993/0904 |
| |
| 1997/1210 | chan = devattach('l', spec); chan->dev = ctlrno; if(etherxx[ctlrno]->dev && etherxx[ctlrno]->dev->attach) etherxx[ctlrno]->dev->attach(etherxx[ctlrno]); return chan; } | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/1210 | static int etherwalk(Chan* chan, char* name) | |
| 1993/0904 | { | |
| 1997/1210 | return netifwalk(etherxx[chan->dev], chan, name); } | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1997/1210 | static void etherstat(Chan* chan, char* dp) | |
| 1993/0904 | { | |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1997/1210 | netifstat(etherxx[chan->dev], chan, dp); } | |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | static Chan* etheropen(Chan* chan, int omode) | |
| 1993/0903 | { | |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1997/1210 | return netifopen(etherxx[chan->dev], chan, omode); } | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/1210 | static void ethercreate(Chan*, char*, int, ulong) | |
| 1993/0904 | { | |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1997/1210 | } | |
| 1993/0904 |
| |
| 1993/0905 |
| |
| 1993/0904 |
| |
| 1993/0905 |
| |
| 1997/1210 | static void etherclose(Chan* chan) | |
| 1993/0905 | { | |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1997/1210 | netifclose(etherxx[chan->dev], chan); } | |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | static long etherread(Chan* chan, void* buf, long n, ulong offset) | |
| 1993/0903 | { | |
| 1993/0904 |
| |
| 1997/1210 | Ether *ether; | |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1997/1210 | ether = etherxx[chan->dev]; if((chan->qid.path & CHDIR) == 0 && ether->dev && ether->dev->ifstat){ /* * With some controllers it is necessary to reach * into the chip to extract statistics. */ if(NETTYPE(chan->qid.path) == Nifstatqid) return ether->dev->ifstat(ether, buf, n, offset); else if(NETTYPE(chan->qid.path) == Nstatqid) ether->dev->ifstat(ether, buf, 0, offset); } | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/1210 | return netifread(ether, chan, buf, n, offset); } | |
| 1993/0904 | ||
| 1993/0906 |
| |
| 1993/0904 | ||
| 1993/0906 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/0327 |
| |
| 1993/0906 | ||
| 1993/0903 |
| |
| 1993/0906 |
| |
| 1997/1210 | static Block* etherbread(Chan* chan, long n, ulong offset) | |
| 1993/0906 | { | |
| 1997/1210 | return netifbread(etherxx[chan->dev], chan, n, offset); | |
| 1993/0906 | } static void | |
| 1993/0904 |
| |
| 1997/1210 | etherremove(Chan*) | |
| 1993/0903 | { | |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0905 |
| |
| 1994/0107 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0905 |
| |
| 1993/0906 |
| |
| 1993/0903 | ||
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0906 |
| |
| 1993/0905 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 | ||
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1993/0903 | } | |
| 1997/0327 | static void | |
| 1993/0906 |
| |
| 1997/1210 | etherwstat(Chan* chan, char* dp) | |
| 1993/0905 | { | |
| 1993/0906 |
| |
| 1997/1210 | netifwstat(etherxx[chan->dev], chan, dp); | |
| 1993/0905 | } | |
| 1993/1212 |
| |
| 1997/1210 | static void etherrtrace(Netfile* f, Etherpkt* pkt, int len) | |
| 1993/1212 | { | |
| 1997/1210 | int i, n; Block *bp; | |
| 1993/1212 |
| |
| 1997/1210 | if(qwindow(f->in) <= 0) return; if(len > 64) n = 64; else n = len; bp = iallocb(n); if(bp == 0) return; memmove(bp->wp, pkt->d, n); i = TK2MS(MACHP(0)->ticks); bp->wp[58] = len>>8; bp->wp[59] = len; bp->wp[60] = i>>24; bp->wp[61] = i>>16; bp->wp[62] = i>>8; bp->wp[63] = i; bp->wp += 64; qpass(f->in, bp); | |
| 1993/1212 | } | |
| 1993/0905 |
| |
| 1993/0903 |
| |
| 1997/1210 | Block* etheriq(Ether* ether, Block* bp, int freebp) | |
| 1993/0903 | { | |
| 1993/0906 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1997/1210 | Etherpkt *pkt; ushort type; int len; Netfile **ep, *f, **fp, *fx; Block *xbp; | |
| 1993/0903 | ||
| 1993/0906 |
| |
| 1997/1210 | ether->inpackets++; | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1997/1210 | pkt = (Etherpkt*)bp->rp; len = BLEN(bp); type = (pkt->type[0]<<8)|pkt->type[1]; fx = 0; ep = ðer->f[Ntypes]; | |
| 1993/0904 | ||
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1993/1219 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1997/1210 | /* check for valid multcast addresses */ if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ if(freebp){ freeb(bp); bp = 0; | |
| 1993/0904 | } | |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1993/1212 |
| |
| 1997/1210 | return bp; | |
| 1993/0903 | } | |
| 1997/1210 | } | |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1997/1210 | /* * Multiplex the packet to all the connections which want it. * If the packet is not to be used subsequently (freebp != 0), * attempt to simply pass it into one of the connections, thereby * saving a copy of the data (usual case hopefully). */ for(fp = ether->f; fp < ep; fp++){ if((f = *fp) && (f->type == type || f->type < 0)){ if(f->type > -2){ if(freebp && fx == 0) fx = f; else if(xbp = iallocb(len)){ memmove(xbp->wp, pkt, len); xbp->wp += len; qpass(f->in, xbp); } else ether->soverflows++; } | |
| 1993/0904 | else | |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0904 | ||
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0906 |
| |
| 1993/0904 | ||
| 1993/0906 |
| |
| 1997/1210 | etherrtrace(f, pkt, len); | |
| 1993/0903 | } | |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1997/1210 | } | |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 | ||
| 1994/0107 |
| |
| 1993/0906 |
| |
| 1994/0107 |
| |
| 1997/1210 | if(fx){ qpass(fx->in, bp); return 0; | |
| 1993/0903 | } | |
| 1997/1210 | if(freebp){ freeb(bp); return 0; } | |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1997/1210 | return bp; | |
| 1993/0903 | } | |
| 1993/0906 |
| |
| 1997/1210 | static int etheroq(Ether* ether, Block* bp) | |
| 1993/0906 | { | |
| 1993/1217 |
| |
| 1997/1210 | int len, loopback, s; Etherpkt *pkt; | |
| 1993/0906 | ||
| 1994/0524 |
| |
| 1993/1217 |
| |
| 1993/0906 |
| |
| 1997/1210 | ether->outpackets++; | |
| 1993/0906 | /* | |
| 1997/1210 | * Check if the packet has to be placed back onto the input queue, * i.e. if it's a loopback or broadcast packet or the interface is * in promiscuous mode. * If it's a loopback packet indicate to etheriq that the data isn't * needed and return, etheriq will pass-on or free the block. | |
| 1993/0906 | */ | |
| 1997/1210 | pkt = (Etherpkt*)bp->rp; len = BLEN(bp); loopback = (memcmp(pkt->d, ether->addr, sizeof(pkt->d)) == 0); if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ s = splhi(); etheriq(ether, bp, loopback); splx(s); | |
| 1993/0906 | } | |
| 1993/1217 |
| |
| 1993/0906 |
| |
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1993/0905 |
| |
| 1997/1210 | if(!loopback){ if(ether->dev && ether->dev->transmit){ qbwrite(ether->oq, bp); ether->dev->transmit(ether); } else{ freeb(bp); return 0; } | |
| 1993/0903 | } | |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/0327 |
| |
| 1993/0904 |
| |
| 1997/1210 | return len; | |
| 1993/0903 | } | |
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1997/1210 | static long etherwrite(Chan* chan, void* buf, long n, ulong) | |
| 1993/0903 | { | |
| 1993/0905 |
| |
| 1997/1210 | Ether *ether; Block *bp; | |
| 1993/0905 |
| |
| 1995/0520 |
| |
| 1993/0903 |
| |
| 1997/1210 | ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid) return netifwrite(ether, chan, buf, n); | |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | if(n > ETHERMAXTU) error(Etoobig); if(n < ETHERMINTU) error(Etoosmall); | |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | bp = allocb(n); if(waserror()){ freeb(bp); nexterror(); } memmove(bp->rp, buf, n); memmove(bp->rp+Eaddrlen, ether->addr, Eaddrlen); poperror(); bp->wp += n; | |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1997/1210 | return etheroq(ether, bp); | |
| 1993/0903 | } | |
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1993/1202 |
| |
| 1995/0114 |
| |
| 1993/1202 | ||
| 1995/0114 |
| |
| 1993/1202 |
| |
| 1995/0114 |
| |
| 1993/1202 |
| |
| 1997/0327 | static long | |
| 1993/0903 |
| |
| 1997/1210 | etherbwrite(Chan* chan, Block* bp, ulong) | |
| 1993/0903 | { | |
| 1993/0906 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1997/1210 | Ether *ether; long n; | |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 | ||
| 1993/1212 |
| |
| 1995/0114 |
| |
| 1993/0903 |
| |
| 1993/1202 |
| |
| 1997/1210 | n = BLEN(bp); ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid){ n = netifwrite(ether, chan, bp->rp, n); freeb(bp); | |
| 1993/1202 | return n; | |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0918 |
| |
| 1993/1212 |
| |
| 1993/0905 | ||
| 1993/1212 |
| |
| 1993/0904 |
| |
| 1993/1212 |
| |
| 1993/0903 |
| |
| 1993/0906 |
| |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1994/0107 |
| |
| 1993/0904 |
| |
| 1997/1210 | if(n > ETHERMAXTU){ freeb(bp); error(Ebadarg); | |
| 1993/0903 | } | |
| 1993/0918 |
| |
| 1993/0904 |
| |
| 1997/1210 | if(n < ETHERMINTU){ freeb(bp); error(Etoosmall); } | |
| 1993/0905 | ||
| 1993/0903 |
| |
| 1997/1210 | return etheroq(ether, bp); | |
| 1995/0108 | } | |
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1997/1210 | void etherreset(void) | |
| 1993/0903 | { | |
| 1997/1210 | Ether *ether; int i, n, ctlrno; char name[NAMELEN], buf[128]; | |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0903 |
| |
| 1997/1210 | for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ether == 0) ether = malloc(sizeof(Ether)); memset(ether, 0, sizeof(Ether)); ether->ctlrno = ctlrno; ether->tbdf = BUSUNKNOWN; ether->mbps = 10; if(isaconfig("ether", ctlrno, ether) == 0) continue; for(n = 0; endev[n]; n++){ if(cistrcmp(endev[n]->name, ether->type)) continue; ether->dev = endev[n]; for(i = 0; i < ether->nopt; i++){ if(strncmp(ether->opt[i], "ea=", 3)) continue; if(parseether(ether->addr, ðer->opt[i][3]) == -1) memset(ether->addr, 0, Eaddrlen); } if(endev[n]->reset(ether)) break; | |
| 1993/0903 | ||
| 1997/0327 |
| |
| 1993/0903 |
| |
| 1993/0904 |
| |
| 1993/0906 |
| |
| 1997/1210 | /* * IRQ2 doesn't really exist, it's used to gang the interrupt * controllers together. A device set to IRQ2 will appear on * the second interrupt controller as IRQ9. */ if(ether->irq == 2) ether->irq = 9; intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf); | |
| 1993/0906 |
| |
| 1997/1210 | i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX", ctlrno, ether->type, ether->mbps, ether->port); if(ether->irq) i += sprint(buf+i, " irq %d", ether->irq); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); if(ether->size) i += sprint(buf+i, " size 0x%luX", ether->size); i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", ether->addr[0], ether->addr[1], ether->addr[2], ether->addr[3], ether->addr[4], ether->addr[5]); sprint(buf+i, "\n"); print(buf); | |
| 1993/0906 | ||
| 1997/0327 |
| |
| 1993/0906 |
| |
| 1997/1210 | snprint(name, sizeof(name), "ether%d", ctlrno); if(ether->mbps == 100){ netifinit(ether, name, Ntypes, 256*1024); if(ether->oq == 0) ether->oq = qopen(256*1024, 1, 0, 0); } else{ netifinit(ether, name, Ntypes, 32*1024); if(ether->oq == 0) ether->oq = qopen(64*1024, 1, 0, 0); } if(ether->oq == 0) panic("etherreset %s", name); | |
| 1993/0906 |
| |
| 1997/1210 | ether->alen = Eaddrlen; memset(ether->bcast, 0xFF, Eaddrlen); ether->arg = ether; ether->promiscuous = ether->dev->promiscuous; ether->multicast = ether->dev->multicast; etherxx[ctlrno] = ether; ether = 0; break; } | |
| 1993/0906 | } | |
| 1997/1210 | if(ether) free(ether); | |
| 1993/0903 | } | |
| 1997/0327 | int | |
| 1997/1210 | parseether(uchar* to, char* from) | |
| 1997/0327 | { char nip[4]; char *p; | |
| 1997/0408/sys/src/9/carrera/devether.c:835,840 – 1997/1210/sys/src/9/carrera/devether.c:388,413 | ||
| 1997/0327 | return 0; } | |
| 1997/1210 | #define POLY 0xedb88320 /* really slow 32 bit crc for ethers */ ulong ethercrc(uchar* p, int len) { int i, j; ulong crc, b; crc = 0xffffffff; for(i = 0; i < len; i++){ b = *p++; for(j = 0; j < 8; j++){ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); b >>= 1; } } return crc; } | |
| 1997/0327 | Dev etherdevtab = { | |
| 1997/0408 | 'l', "ether", | |
| 1997/0408/sys/src/9/carrera/devether.c:849,857 – 1997/1210/sys/src/9/carrera/devether.c:422,430 | ||
| 1997/0327 | ethercreate, etherclose, etherread, | |
| 1997/1210 | etherbread, | |
| 1997/0327 | etherwrite, | |
| 1997/1210 | etherbwrite, | |
| 1997/0327 | etherremove, etherwstat, }; | |
| 1997/1210/sys/src/9/carrera/devether.c:65,73 – 1998/0319/sys/src/9/carrera/devether.c:65,74 (short | long) | ||
|
Change dev read and write to use vlong offset.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/1210 | } | |
| 1993/0904 | ||
| 1997/1210 | static long | |
| 1998/0319 | etherread(Chan* chan, void* buf, long n, vlong off) | |
| 1993/0903 | { | |
| 1997/1210 | Ether *ether; | |
| 1998/0319 | ulong offset = off; | |
| 1993/0903 | ||
| 1997/1210 | ether = etherxx[chan->dev]; if((chan->qid.path & CHDIR) == 0 && ether->dev && ether->dev->ifstat){ | |
| 1997/1210/sys/src/9/carrera/devether.c:231,237 – 1998/0319/sys/src/9/carrera/devether.c:232,238 | ||
| 1993/0903 | } | |
| 1997/1210 | static long | |
| 1998/0319 | etherwrite(Chan* chan, void* buf, long n, vlong) | |
| 1993/0903 | { | |
| 1997/1210 | Ether *ether; Block *bp; | |
| 1998/0319/sys/src/9/carrera/devether.c:326,332 – 1999/0629/sys/src/9/carrera/devether.c:326,332 (short | long) | ||
| 1997/1210 | i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX", ctlrno, ether->type, ether->mbps, ether->port); if(ether->irq) | |
| 1999/0629 | i += sprint(buf+i, " irq %ld", ether->irq); | |
| 1997/1210 | if(ether->mem) i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); if(ether->size) | |
| 1999/0629/sys/src/9/carrera/devether.c:110,121 – 2000/0713/sys/src/9/carrera/devether.c:110,121 (short | long) | ||
| 1993/1212 | ||
| 1997/1210 | if(qwindow(f->in) <= 0) return; | |
| 2000/0713 | if(len > 58) n = 58; | |
| 1997/1210 | else n = len; | |
| 2000/0713 | bp = iallocb(64); if(bp == nil) | |
| 1997/1210 | return; memmove(bp->wp, pkt->d, n); i = TK2MS(MACHP(0)->ticks); | |
| 2000/0713/sys/src/9/carrera/devether.c:1,431 – 2001/0527/sys/src/9/carrera/devether.c:0 (short | long) | ||
|
Deleted.
rsc Mon Mar 7 10:21:06 2005 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0906 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0904 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0904 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0904 |
| |
| 1997/1210 |
| |
| 1993/0904 | ||
| 1997/1210 |
| |
| 1993/0905 |
| |
| 1997/1210 |
| |
| 1993/0904 | ||
| 1997/1210 |
| |
| 1998/0319 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1998/0319 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0904 | ||
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1993/0905 |
| |
| 1997/1210 |
| |
| 1993/0905 |
| |
| 1997/1210 |
| |
| 1993/1212 |
| |
| 1997/1210 |
| |
| 1993/1212 | ||
| 1997/1210 |
| |
| 2000/0713 |
| |
| 1997/1210 |
| |
| 2000/0713 |
| |
| 1997/1210 |
| |
| 1993/1212 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0904 | ||
| 1997/1210 |
| |
| 1993/0904 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0904 | ||
| 1997/1210 |
| |
| 1993/0904 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0906 | ||
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1998/0319 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0905 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/1202 |
| |
| 1993/0918 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0905 | ||
| 1997/1210 |
| |
| 1995/0108 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0903 | ||
| 1997/1210 |
| |
| 1993/0906 | ||
| 1997/1210 |
| |
| 1999/0629 |
| |
| 1997/1210 |
| |
| 1993/0906 | ||
| 1997/1210 |
| |
| 1993/0906 | ||
| 1997/1210 |
| |
| 1993/0906 |
| |
| 1997/1210 |
| |
| 1993/0903 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1997/0327 |
| |
| 1997/0408 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1997/0327 |
| |
| 1997/1210 |
| |
| 1997/0327 |
| |