123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- #include "all.h"
- #include "io.h"
- #include "mem.h"
- #include "../ip/ip.h"
- #include "etherif.h"
- extern int etherga620reset(Ether*);
- extern int ether21140reset(Ether*);
- extern int etherelnk3reset(Ether*);
- extern int etheri82557reset(Ether*);
- extern int dp83815reset(Ether*);
- extern int dp83820pnp(Ether*);
- extern int rtl8139pnp(Ether*);
- static struct
- {
- char* type;
- int (*reset)(Ether*);
- } etherctlr[] =
- {
- { "ga620", etherga620reset, },
- { "21140", ether21140reset, },
- { "2114x", ether21140reset, },
- { "3C509", etherelnk3reset, },
- { "83815", dp83815reset, },
- { "dp83820", dp83820pnp, },
- { "elnk3", etherelnk3reset, },
- { "i82557", etheri82557reset, },
- { "rtl8139", rtl8139pnp, },
- { 0, },
- };
- static Ether etherif[MaxEther];
- void
- etheriq(Ether* ether, Msgbuf* mb)
- {
- ilock(ðer->rqlock);
- if(ether->rqhead)
- ether->rqtail->next = mb;
- else
- ether->rqhead = mb;
- ether->rqtail = mb;
- mb->next = 0;
- iunlock(ðer->rqlock);
- wakeup(ðer->rqr);
- }
- static int
- isinput(void* arg)
- {
- return ((Ether*)arg)->rqhead != 0;
- }
- #include "compat.h"
- static void
- etheri(void)
- {
- Ether *ether;
- Ifc *ifc;
- Msgbuf *mb;
- Enpkt *p;
- ether = getarg();
- ifc = ðer->ifc;
- print("ether%di: %E %I\n", ether->ctlrno, ether->ifc.ea, ether->ifc.ipa);
- (*ether->attach)(ether);
- for(;;) {
- while(!isinput(ether))
- sleep(ðer->rqr, isinput, ether);
- ilock(ðer->rqlock);
- if(ether->rqhead == 0) {
- iunlock(ðer->rqlock);
- continue;
- }
- mb = ether->rqhead;
- ether->rqhead = mb->next;
- iunlock(ðer->rqlock);
- p = (Enpkt*)mb->data;
- switch(nhgets(p->type)){
- case Arptype:
- arpreceive(p, mb->count, ifc);
- break;
- case Iptype:
- ipreceive(p, mb->count, ifc);
- ifc->rxpkt++;
- ifc->work[0].count++;
- ifc->work[1].count++;
- ifc->work[2].count++;
- ifc->rate[0].count += mb->count;
- ifc->rate[1].count += mb->count;
- ifc->rate[2].count += mb->count;
- break;
- }
- mbfree(mb);
- }
- }
- static void
- ethero(void)
- {
- Ether *ether;
- Ifc *ifc;
- Msgbuf *mb;
- int len;
- ether = getarg();
- ifc = ðer->ifc;
- print("ether%do: %E %I\n", ether->ctlrno, ifc->ea, ifc->ipa);
- for(;;) {
- for(;;) {
- mb = recv(ifc->reply, 0);
- if(mb != nil)
- break;
- }
- if(mb->data == 0) {
- print("ether%do: pkt nil cat=%d free=%d\n",
- ether->ctlrno, mb->category, mb->flags&FREE);
- if(!(mb->flags & FREE))
- mbfree(mb);
- continue;
- }
- len = mb->count;
- if(len > ETHERMAXTU) {
- print("ether%do: pkt too big - %d\n", ether->ctlrno, len);
- mbfree(mb);
- continue;
- }
- if(len < ETHERMINTU) {
- memset(mb->data+len, 0, ETHERMINTU-len);
- mb->count = len = ETHERMINTU;
- }
- memmove(((Enpkt*)(mb->data))->s, ifc->ea, sizeof(ifc->ea));
- ilock(ðer->tqlock);
- if(ether->tqhead)
- ether->tqtail->next = mb;
- else
- ether->tqhead = mb;
- ether->tqtail = mb;
- mb->next = 0;
- iunlock(ðer->tqlock);
- (*ether->transmit)(ether);
- ifc->work[0].count++;
- ifc->work[1].count++;
- ifc->work[2].count++;
- ifc->rate[0].count += len;
- ifc->rate[1].count += len;
- ifc->rate[2].count += len;
- ifc->txpkt++;
- }
- }
- Msgbuf*
- etheroq(Ether* ether)
- {
- Msgbuf *mb;
- mb = nil;
- ilock(ðer->tqlock);
- if(ether->tqhead){
- mb = ether->tqhead;
- ether->tqhead = mb->next;
- }
- iunlock(ðer->tqlock);
- return mb;
- }
- static void
- cmd_state(int, char*[])
- {
- Ether *ether;
- Ifc *ifc;
- for(ether = ðerif[0]; ether < ðerif[MaxEther]; ether++){
- if(ether->mbps == 0)
- continue;
- ifc = ðer->ifc;
- if(!isvalidip(ifc->ipa))
- continue;
- print("ether stats %d\n", ether->ctlrno);
- print(" work =%7W%7W%7W pkts\n", ifc->work+0, ifc->work+1, ifc->work+2);
- print(" rate =%7W%7W%7W tBps\n", ifc->rate+0, ifc->rate+1, ifc->rate+2);
- print(" err = %3ld rc %3ld sum\n", ifc->rcverr, ifc->sumerr);
- }
- }
- void
- etherstart(void)
- {
- Ether *ether;
- Ifc *ifc;
- int anystarted;
- char buf[100], *p;
- anystarted = 0;
- for(ether = ðerif[0]; ether < ðerif[MaxEther]; ether++){
- if(ether->mbps == 0)
- continue;
- ifc = ðer->ifc;
- lock(ifc);
- getipa(ifc, ether->ctlrno);
- if(!isvalidip(ifc->ipa)){
- unlock(ifc);
- ether->mbps = 0;
- continue;
- }
- if(ifc->reply == 0){
- dofilter(ifc->work+0, C0a, C0b, 1);
- dofilter(ifc->work+1, C1a, C1b, 1);
- dofilter(ifc->work+2, C2a, C2b, 1);
- dofilter(ifc->rate+0, C0a, C0b, 1000);
- dofilter(ifc->rate+1, C1a, C1b, 1000);
- dofilter(ifc->rate+2, C2a, C2b, 1000);
- ifc->reply = newqueue(Nqueue);
- }
- unlock(ifc);
- sprint(ether->oname, "ether%do", ether->ctlrno);
- userinit(ethero, ether, ether->oname);
- sprint(ether->iname, "ether%di", ether->ctlrno);
- userinit(etheri, ether, ether->iname);
- ifc->next = enets;
- enets = ifc;
- anystarted++;
- }
- if(anystarted){
- cmd_install("state", "-- ether stats", cmd_state);
- arpstart();
- if((p = getconf("route")) && strlen(p) < sizeof(buf)-7){
- sprint(buf, "route %s", p);
- cmd_exec(buf);
- }
- }
- }
- static int
- parseether(uchar *to, char *from)
- {
- char nip[4];
- char *p;
- int i;
- p = from;
- while(*p == ' ')
- ++p;
- 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;
- }
- void
- etherinit(void)
- {
- Ether *ether;
- int i, n, ctlrno;
- for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- ether = ðerif[ctlrno];
- memset(ether, 0, sizeof(Ether));
- if(!isaconfig("ether", ctlrno, ether))
- continue;
- for(n = 0; etherctlr[n].type; n++){
- if(cistrcmp(etherctlr[n].type, ether->type))
- continue;
- ether->ctlrno = ctlrno;
- ether->tbdf = BUSUNKNOWN;
- for(i = 0; i < ether->nopt; i++){
- if(strncmp(ether->opt[i], "ea=", 3))
- continue;
- if(parseether(ether->ea, ðer->opt[i][3]) == -1)
- memset(ether->ea, 0, Easize);
- }
- if((*etherctlr[n].reset)(ether))
- break;
- if(ether->irq == 2)
- ether->irq = 9;
- setvec(Int0vec + ether->irq, ether->interrupt, ether);
- memmove(ether->ifc.ea, ether->ea, sizeof(ether->ea));
- print("ether%d: %s: %dMbps port 0x%lux irq %ld",
- ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
- if(ether->mem)
- print(" addr 0x%lux", ether->mem & ~KZERO);
- if(ether->size)
- print(" size 0x%lux", ether->size);
- print(": ");
- for(i = 0; i < sizeof(ether->ea); i++)
- print("%2.2ux", ether->ea[i]);
- print("\n");
-
- break;
- }
- }
- }
|