| plan 9 kernel history: overview | file list | diff list |
1990/0725/gnot/devincon.c (diff list | history)
| 1990/0312/sys/src/9/gnot/devincon.c:13,18 – 1990/0315/sys/src/9/gnot/devincon.c:13,21 (short | long) | ||
| 1990/0312 | #define NOW (MACHP(0)->ticks*MS2HZ) | |
| 1990/0315 | static int SpEcIaL; #define MICROSECOND SpEcIaL = 0 | |
| 1990/0312 | #define DPRINT if(0) enum { | |
| 1990/0312/sys/src/9/gnot/devincon.c:19,25 – 1990/0315/sys/src/9/gnot/devincon.c:22,28 | ||
| 1990/0312 | Minstation= 2, /* lowest station # to poll */ Maxstation= 15, /* highest station # to poll */ Nincon= 1, /* number of incons */ | |
| 1990/0315 | Nin= 32, /* size of raw input buffer */ | |
| 1990/0312 | }; /* | |
| 1990/0312/sys/src/9/gnot/devincon.c:58,71 – 1990/0315/sys/src/9/gnot/devincon.c:61,74 | ||
| 1990/0312 | Rendez kr; /* input kernel process */ ushort chan; /* current input channel */ Queue *rq; /* read queue */ | |
| 1990/0315 | /* input blocks */ | |
| 1990/0312 | ||
| 1990/0315 | Block *inb[Nin]; ushort wi; ushort ri; | |
| 1990/0312 | /* statistics */ ulong overflow; /* overflow errors */ | |
| 1990/0312/sys/src/9/gnot/devincon.c:131,148 – 1990/0315/sys/src/9/gnot/devincon.c:134,155 | ||
| 1990/0312 | * set the incon parameters */ void | |
| 1990/0315 | inconset(Incon *ip, int cnt, int del) | |
| 1990/0312 | { Device *dev; | |
| 1990/0315 | if (cnt<1 || cnt>14 || del<1 || del>15) | |
| 1990/0312 | error(0, Ebadarg); dev = ip->dev; dev->cmd = sel_rcv_cnt | INCON_RUN; | |
| 1990/0315 | MICROSECOND; | |
| 1990/0312 | *(uchar *)&dev->data_cntl = cnt; | |
| 1990/0315 | MICROSECOND; | |
| 1990/0312 | dev->cmd = sel_rcv_tim | INCON_RUN; | |
| 1990/0315 | MICROSECOND; *(uchar *)&dev->data_cntl = del; MICROSECOND; | |
| 1990/0312 | dev->cmd = INCON_RUN | ENABLE_IRQ; } | |
| 1990/0312/sys/src/9/gnot/devincon.c:253,264 – 1990/0315/sys/src/9/gnot/devincon.c:260,272 | ||
| 1990/0312 | incon[0].dev = INCON; incon[0].state = Selected; | |
| 1990/0315 | incon[0].ri = incon[0].wi = 0; inconset(&incon[0], 8, 9); | |
| 1990/0312 | for(i=1; i<Nincon; i++){ incon[i].dev = INCON+i; incon[i].state = Dead; incon[i].dev->cmd = INCON_STOP; | |
| 1990/0315 | incon[i].ri = incon[i].wi = 0; | |
| 1990/0312 | } } | |
| 1990/0312/sys/src/9/gnot/devincon.c:551,556 – 1990/0315/sys/src/9/gnot/devincon.c:559,565 | ||
| 1990/0312 | } DPRINT("CTL|%uo->\n", ctl); dev->cdata = ctl; | |
| 1990/0315 | MICROSECOND; | |
| 1990/0312 | } dev->cdata = 0; | |
| 1990/0312/sys/src/9/gnot/devincon.c:567,598 – 1990/0315/sys/src/9/gnot/devincon.c:576,585 | ||
| 1990/0312 | Incon *ip; ip = (Incon *)arg; | |
| 1990/0315 | return ip->ri!=ip->wi; | |
| 1990/0312 | } /* | |
| 1990/0312/sys/src/9/gnot/devincon.c:599,615 – 1990/0315/sys/src/9/gnot/devincon.c:586,612 | ||
| 1990/0312 | inconkproc(void *arg) { Incon *ip; | |
| 1990/0315 | Block *bp; int i; | |
| 1990/0312 | ip = (Incon *)arg; ip->kstarted = 1; | |
| 1990/0315 | /* * create a number of blocks for input */ for(i = 0; i < Nin; i++){ bp = ip->inb[i] = allocb(128); bp->wptr += 3; } | |
| 1990/0312 | for(;;){ /* | |
| 1990/0315 | * sleep if input fifo empty */ sleep(&ip->kr, notempty, ip); /* | |
| 1990/0312 | * die if the device is closed */ qlock(ip); | |
| 1990/0312/sys/src/9/gnot/devincon.c:621,642 – 1990/0315/sys/src/9/gnot/devincon.c:618,704 | ||
| 1990/0312 | } /* | |
| 1990/0315 | * send blocks upstream and stage new blocks | |
| 1990/0312 | */ | |
| 1990/0315 | while(ip->ri != ip->wi){ PUTNEXT(ip->rq, ip->inb[ip->ri]); bp = ip->inb[ip->ri] = allocb(128); bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; } qunlock(ip); } } | |
| 1990/0312 | ||
| 1990/0315 | /* * drop an input packet on the floor */ static void droppacket(Device *dev) { int i; int c; for(i = 0; i < 17; i++){ c = dev->data_cntl; if(c==0) break; } } /* * advance the queue. if we've run out of staged input blocks, * drop the packet and return 0. otherwise return the next input * block to fill. */ static Block * nextin(Incon *ip, unsigned int c) { Block *bp = ip->inb[ip->wi]; bp->base[0] = ip->chan; bp->base[1] = ip->chan>>8; bp->base[2] = c; ip->wi = (ip->wi + 1) % Nin; if(((ip->wi+1)%Nin) == ip->ri){ droppacket(ip->dev); return 0; } return ip->inb[ip->wi]; } /* * read the packets from the device into the staged input blocks. * we have to do this at interrupt tevel to turn off the interrupts. */ static void rdpackets(Incon *ip) { Block *bp; unsigned int c; Device *dev; dev = ip->dev; while(!(dev->status & RCV_EMPTY)){ bp = ip->inb[ip->wi]; if(((ip->wi+1)%Nin) == ip->ri || bp==0){ c = dev->data_cntl; droppacket(dev); continue; } | |
| 1990/0312 | /* * get channel number */ | |
| 1990/0315 | c = (dev->data_cntl)>>8; | |
| 1990/0312 | DPRINT("<-CH|%uo\n", c); if(ip->chan != c){ | |
| 1990/0315 | if(bp->wptr - bp->rptr > 3){ bp = nextin(ip, 0); if(bp == 0) continue; } | |
| 1990/0312 | ip->chan = c; } | |
| 1990/0312/sys/src/9/gnot/devincon.c:643,716 – 1990/0315/sys/src/9/gnot/devincon.c:705,734 | ||
| 1990/0312 | /* * null byte marks end of packet */ | |
| 1990/0315 | for(;;){ if((c=dev->data_cntl)&1) { | |
| 1990/0312 | /* * data byte, put in local buffer */ | |
| 1990/0315 | c = *bp->wptr++ = c>>8; | |
| 1990/0312 | DPRINT("<-%uo\n", c); | |
| 1990/0315 | if(bp->wptr >= bp->lim){ bp = nextin(ip, 0); if(bp == 0) continue; } | |
| 1990/0312 | } else if (c>>=8) { /* * control byte ends block */ DPRINT("<-CTL|%uo\n", c); | |
| 1990/0315 | bp = nextin(ip, c); if(bp == 0) continue; | |
| 1990/0312 | } else { /* end of packet */ break; } | |
| 1990/0315/sys/src/9/gnot/devincon.c:7,12 – 1990/0320/sys/src/9/gnot/devincon.c:7,13 (short | long) | ||
| 1990/0312 | #include "devtab.h" #include "io.h" | |
| 1990/0320 | #include "ureg.h" | |
| 1990/0312 | typedef struct Incon Incon; typedef struct Device Device; | |
| 1990/0315/sys/src/9/gnot/devincon.c:22,28 – 1990/0320/sys/src/9/gnot/devincon.c:23,30 | ||
| 1990/0312 | Minstation= 2, /* lowest station # to poll */ Maxstation= 15, /* highest station # to poll */ Nincon= 1, /* number of incons */ | |
| 1990/0315 |
| |
| 1990/0320 | Nin= 16, /* Blocks in the input ring */ Bsize= 128, /* size of an input ring block */ | |
| 1990/0312 | }; /* | |
| 1990/0315/sys/src/9/gnot/devincon.c:522,530 – 1990/0320/sys/src/9/gnot/devincon.c:524,530 | ||
| 1990/0312 | n = 16; size = n; dev->cdata = chan; | |
| 1990/0315/sys/src/9/gnot/devincon.c:554,566 – 1990/0320/sys/src/9/gnot/devincon.c:554,566 | ||
| 1990/0312 | if(ctl){ if(size >= 16){ dev->cdata = 0; | |
| 1990/0320 | MICROSECOND; | |
| 1990/0312 | dev->cdata = chan; | |
| 1990/0320 | MICROSECOND; | |
| 1990/0312 | } | |
| 1990/0315 |
| |
| 1990/0312 | } | |
| 1990/0320 | MICROSECOND; | |
| 1990/0312 | dev->cdata = 0; qunlock(&ip->xmit); | |
| 1990/0315/sys/src/9/gnot/devincon.c:596,602 – 1990/0320/sys/src/9/gnot/devincon.c:596,602 | ||
| 1990/0315 | * create a number of blocks for input */ for(i = 0; i < Nin; i++){ | |
| 1990/0320 | bp = ip->inb[i] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; } | |
| 1990/0315/sys/src/9/gnot/devincon.c:622,628 – 1990/0320/sys/src/9/gnot/devincon.c:622,628 | ||
| 1990/0312 | */ | |
| 1990/0315 | while(ip->ri != ip->wi){ PUTNEXT(ip->rq, ip->inb[ip->ri]); | |
| 1990/0320 | bp = ip->inb[ip->ri] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; } | |
| 1990/0315/sys/src/9/gnot/devincon.c:639,648 – 1990/0320/sys/src/9/gnot/devincon.c:639,651 | ||
| 1990/0315 | int i; int c; | |
| 1990/0320 | screenputc('!'); while(!(dev->status & RCV_EMPTY)){ for(i = 0; i < 17; i++){ c = dev->data_cntl; if(c==0) break; } | |
| 1990/0315 | } } | |
| 1990/0315/sys/src/9/gnot/devincon.c:655,670 – 1990/0320/sys/src/9/gnot/devincon.c:658,676 | ||
| 1990/0315 | nextin(Incon *ip, unsigned int c) { Block *bp = ip->inb[ip->wi]; | |
| 1990/0320 | int next; | |
| 1990/0315 | ||
| 1990/0320 | next = (ip->wi+1)%Nin; if(next == ip->ri){ bp->wptr = bp->base+3; droppacket(ip->dev); return 0; } | |
| 1990/0315 | bp->base[0] = ip->chan; bp->base[1] = ip->chan>>8; bp->base[2] = c; | |
| 1990/0320 | ip->wi = next; | |
| 1990/0315 |
| |
| 1990/0315/sys/src/9/gnot/devincon.c:678,703 – 1990/0320/sys/src/9/gnot/devincon.c:684,711 | ||
| 1990/0315 | Block *bp; unsigned int c; Device *dev; | |
| 1990/0320 | uchar *p; int first = ip->wi; | |
| 1990/0315 | dev = ip->dev; | |
| 1990/0320 | bp = ip->inb[ip->wi]; if(bp==0){ droppacket(ip->dev); goto done; } p = bp->wptr; | |
| 1990/0315 | while(!(dev->status & RCV_EMPTY)){ | |
| 1990/0312 | /* * get channel number */ | |
| 1990/0315 | c = (dev->data_cntl)>>8; | |
| 1990/0312 |
| |
| 1990/0315 |
| |
| 1990/0320 | if(p - bp->rptr > 3){ bp->wptr = p; | |
| 1990/0315 | bp = nextin(ip, 0); if(bp == 0) | |
| 1990/0320 | goto done; p = bp->wptr; | |
| 1990/0315 | } | |
| 1990/0312 | ip->chan = c; } | |
| 1990/0315/sys/src/9/gnot/devincon.c:710,737 – 1990/0320/sys/src/9/gnot/devincon.c:718,756 | ||
| 1990/0312 | /* * data byte, put in local buffer */ | |
| 1990/0315 |
| |
| 1990/0312 |
| |
| 1990/0315 |
| |
| 1990/0320 | *p++ = c>>8; | |
| 1990/0312 | } else if (c>>=8) { /* * control byte ends block */ | |
| 1990/0320 | bp->wptr = p; | |
| 1990/0315 | bp = nextin(ip, c); if(bp == 0) | |
| 1990/0320 | goto done; p = bp->wptr; | |
| 1990/0312 | } else { /* end of packet */ break; } } | |
| 1990/0320 | /* * pass a block on if it doesn't have room for one more * packet. this way we don't have to check per byte. */ if(p + 16 > bp->lim){ bp->wptr = p; bp = nextin(ip, 0); if(bp == 0) goto done; p = bp->wptr; } } bp->wptr = p; done: if(first != ip->wi)/**/ wakeup(&ip->kr); | |
| 1990/0312 | } /* | |
| 1990/0315/sys/src/9/gnot/devincon.c:754,764 – 1990/0320/sys/src/9/gnot/devincon.c:773,783 | ||
| 1990/0312 | /* check for exceptional conditions */ if(status&(OVERFLOW|CRC_ERROR)){ if(status&OVERFLOW){ | |
| 1990/0320 | screenputc('^'); | |
| 1990/0312 | ip->overflow++; } if(status&CRC_ERROR){ | |
| 1990/0320 | screenputc('+'); | |
| 1990/0312 | ip->crc++; } } | |
| 1990/0320/sys/src/9/gnot/devincon.c:23,30 – 1990/0321/sys/src/9/gnot/devincon.c:23,31 (short | long) | ||
| 1990/0312 | Minstation= 2, /* lowest station # to poll */ Maxstation= 15, /* highest station # to poll */ Nincon= 1, /* number of incons */ | |
| 1990/0320 |
| |
| 1990/0321 | Nin= 64, /* Blocks in the input ring */ | |
| 1990/0320 | Bsize= 128, /* size of an input ring block */ | |
| 1990/0321 | Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */ | |
| 1990/0312 | }; /* | |
| 1990/0320/sys/src/9/gnot/devincon.c:631,637 – 1990/0321/sys/src/9/gnot/devincon.c:632,638 | ||
| 1990/0315 | } | |
| 1990/0312 | ||
| 1990/0315 | /* | |
| 1990/0321 | * drop a single packet | |
| 1990/0315 | */ static void droppacket(Device *dev) | |
| 1990/0320/sys/src/9/gnot/devincon.c:639,655 – 1990/0321/sys/src/9/gnot/devincon.c:640,663 | ||
| 1990/0315 | int i; int c; | |
| 1990/0320 |
| |
| 1990/0321 | for(i = 0; i < 17; i++){ c = dev->data_cntl; if(c==0) break; | |
| 1990/0315 | } } /* | |
| 1990/0321 | * flush the input fifo */ static void flushfifo(Device *dev) { while(!(dev->status & RCV_EMPTY)) droppacket(dev); } /* | |
| 1990/0315 | * advance the queue. if we've run out of staged input blocks, * drop the packet and return 0. otherwise return the next input * block to fill. | |
| 1990/0320/sys/src/9/gnot/devincon.c:657,676 – 1990/0321/sys/src/9/gnot/devincon.c:665,685 | ||
| 1990/0315 | static Block * nextin(Incon *ip, unsigned int c) { | |
| 1990/0321 | Block *bp; | |
| 1990/0320 | int next; | |
| 1990/0315 | ||
| 1990/0320 |
| |
| 1990/0321 | bp = ip->inb[ip->wi]; | |
| 1990/0315 | bp->base[0] = ip->chan; bp->base[1] = ip->chan>>8; bp->base[2] = c; | |
| 1990/0320 |
| |
| 1990/0315 | ||
| 1990/0321 | next = (ip->wi+3)%Nin; if(next == ip->ri){ bp->wptr = bp->base+3; return bp; } ip->wi = (ip->wi+1)%Nin; | |
| 1990/0315 | return ip->inb[ip->wi]; } | |
| 1990/0320/sys/src/9/gnot/devincon.c:690,697 – 1990/0321/sys/src/9/gnot/devincon.c:699,706 | ||
| 1990/0315 | dev = ip->dev; | |
| 1990/0320 | bp = ip->inb[ip->wi]; if(bp==0){ | |
| 1990/0321 | flushfifo(ip->dev); return; | |
| 1990/0320 | } p = bp->wptr; | |
| 1990/0315 | while(!(dev->status & RCV_EMPTY)){ | |
| 1990/0320/sys/src/9/gnot/devincon.c:699,710 – 1990/0321/sys/src/9/gnot/devincon.c:708,721 | ||
| 1990/0312 | * get channel number */ | |
| 1990/0315 | c = (dev->data_cntl)>>8; | |
| 1990/0321 | if(c == 0){ droppacket(dev); continue; } | |
| 1990/0312 | if(ip->chan != c){ | |
| 1990/0320 | if(p - bp->rptr > 3){ bp->wptr = p; | |
| 1990/0315 | bp = nextin(ip, 0); | |
| 1990/0320 |
| |
| 1990/0315 | } | |
| 1990/0312 | ip->chan = c; | |
| 1990/0320/sys/src/9/gnot/devincon.c:725,732 – 1990/0321/sys/src/9/gnot/devincon.c:736,741 | ||
| 1990/0312 | */ | |
| 1990/0320 | bp->wptr = p; | |
| 1990/0315 | bp = nextin(ip, c); | |
| 1990/0320 |
| |
| 1990/0312 | } else { /* end of packet */ | |
| 1990/0320/sys/src/9/gnot/devincon.c:741,754 – 1990/0321/sys/src/9/gnot/devincon.c:750,760 | ||
| 1990/0320 | if(p + 16 > bp->lim){ bp->wptr = p; bp = nextin(ip, 0); | |
| 1990/0312 | } | |
| 1990/0321/sys/src/9/gnot/devincon.c:23,29 – 1990/0322/sys/src/9/gnot/devincon.c:23,29 (short | long) | ||
| 1990/0312 | Minstation= 2, /* lowest station # to poll */ Maxstation= 15, /* highest station # to poll */ Nincon= 1, /* number of incons */ | |
| 1990/0321 |
| |
| 1990/0322 | Nin= 32, /* Blocks in the input ring */ | |
| 1990/0320 | Bsize= 128, /* size of an input ring block */ | |
| 1990/0321 | Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */ | |
| 1990/0312 | }; | |
| 1990/0321/sys/src/9/gnot/devincon.c:587,594 – 1990/0322/sys/src/9/gnot/devincon.c:587,594 | ||
| 1990/0312 | inconkproc(void *arg) { Incon *ip; | |
| 1990/0315 |
| |
| 1990/0322 | Block *bp, *nbp; int i, n; | |
| 1990/0312 | ip = (Incon *)arg; ip->kstarted = 1; | |
| 1990/0321/sys/src/9/gnot/devincon.c:619,628 – 1990/0322/sys/src/9/gnot/devincon.c:619,639 | ||
| 1990/0312 | } /* | |
| 1990/0315 |
| |
| 1990/0322 | * send blocks upstream and stage new blocks. if the block is small * (< 64 bytes) copy into a smaller buffer. | |
| 1990/0312 | */ | |
| 1990/0315 | while(ip->ri != ip->wi){ | |
| 1990/0322 | bp = ip->inb[ip->ri]; n = BLEN(bp); if(n <= 64){ nbp = allocb(n); memcpy(nbp->wptr, bp->rptr, n); nbp->wptr += n; freeb(bp); PUTNEXT(ip->rq, nbp); } else { PUTNEXT(ip->rq, bp); } | |
| 1990/0320 | bp = ip->inb[ip->ri] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; | |
| 1990/0322/sys/src/9/gnot/devincon.c:264,270 – 1990/0330/sys/src/9/gnot/devincon.c:264,270 (short | long) | ||
| 1990/0312 | incon[0].dev = INCON; incon[0].state = Selected; | |
| 1990/0315 | incon[0].ri = incon[0].wi = 0; | |
| 1990/0330 | /* inconset(&incon[0], 8, 9); /**/ | |
| 1990/0312 | for(i=1; i<Nincon; i++){ incon[i].dev = INCON+i; incon[i].state = Dead; | |
| 1990/0330/sys/src/9/gnot/devincon.c:243,249 – 1990/0331/sys/src/9/gnot/devincon.c:243,249 (short | long) | ||
| 1990/0312 | break; case Selected: print("incon[%d] station %d\n", ip-incon, ip->station); | |
| 1990/0331 | inconset(ip, 3, 15); | |
| 1990/0312 | break; default: print("incon[%d] bollixed\n", ip-incon); | |
| 1990/0330/sys/src/9/gnot/devincon.c:264,270 – 1990/0331/sys/src/9/gnot/devincon.c:264,270 | ||
| 1990/0312 | incon[0].dev = INCON; incon[0].state = Selected; | |
| 1990/0315 | incon[0].ri = incon[0].wi = 0; | |
| 1990/0330 |
| |
| 1990/0331 | /* inconset(&incon[0], 3, 15); /**/ | |
| 1990/0312 | for(i=1; i<Nincon; i++){ incon[i].dev = INCON+i; incon[i].state = Dead; | |
| 1990/0330/sys/src/9/gnot/devincon.c:625,639 – 1990/0331/sys/src/9/gnot/devincon.c:625,631 | ||
| 1990/0315 | while(ip->ri != ip->wi){ | |
| 1990/0322 | bp = ip->inb[ip->ri]; n = BLEN(bp); | |
| 1990/0331 | PUTNEXT(ip->rq, bp); | |
| 1990/0320 | bp = ip->inb[ip->ri] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; | |
| 1990/0331/sys/src/9/gnot/devincon.c:757,762 – 1990/05312/sys/src/9/gnot/devincon.c:757,764 (short | long) | ||
| 1990/0320 | } } bp->wptr = p; | |
| 1990/05312 | if(bp->wptr != bp->base+3) nextin(ip, 0); | |
| 1990/0320 | if(first != ip->wi)/**/ wakeup(&ip->kr); | |
| 1990/05312/sys/src/9/gnot/devincon.c:783,796 – 1990/0619/sys/src/9/gnot/devincon.c:783,792 (short | long) | ||
| 1990/0312 | /* check for exceptional conditions */ if(status&(OVERFLOW|CRC_ERROR)){ | |
| 1990/0320 |
| |
| 1990/0619 | if(status&OVERFLOW) | |
| 1990/0312 | ip->overflow++; | |
| 1990/0320 |
| |
| 1990/0619 | if(status&CRC_ERROR) | |
| 1990/0312 | ip->crc++; | |
| 1990/0619/sys/src/9/gnot/devincon.c:229,234 – 1990/0623/sys/src/9/gnot/devincon.c:229,236 (short | long) | ||
| 1990/0312 | if(!canqlock(&ip->reslock)) return; | |
| 1990/0623 | print("inconrestart\n"); | |
| 1990/0312 | /* * poll for incon station numbers */ | |
| 1990/0623/sys/src/9/gnot/devincon.c:133,138 – 1990/0629/sys/src/9/gnot/devincon.c:133,140 (short | long) | ||
| 1990/0312 | static void inconstclose(Queue*); Qinfo inconinfo = { nullput, inconoput, inconstopen, inconstclose, "incon" }; | |
| 1990/0629 | int incondebug; | |
| 1990/0312 | /* * set the incon parameters */ | |
| 1990/0623/sys/src/9/gnot/devincon.c:492,497 – 1990/0629/sys/src/9/gnot/devincon.c:494,502 | ||
| 1990/0312 | ctl = bp->rptr[2]; bp->rptr += 3; | |
| 1990/0629 | if(incondebug) print("->(%d)%uo %d\n", chan, ctl, bp->wptr - bp->rptr); | |
| 1990/0312 | /* * make sure there's an incon out there */ | |
| 1990/0623/sys/src/9/gnot/devincon.c:677,682 – 1990/0629/sys/src/9/gnot/devincon.c:682,689 | ||
| 1990/0315 | bp->base[0] = ip->chan; bp->base[1] = ip->chan>>8; bp->base[2] = c; | |
| 1990/0629 | if(incondebug) print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr)-3; | |
| 1990/0315 | ||
| 1990/0321 | next = (ip->wi+3)%Nin; if(next == ip->ri){ | |
| 1990/0623/sys/src/9/gnot/devincon.c:807,810 – 1990/0629/sys/src/9/gnot/devincon.c:814,822 | ||
| 1990/0312 | } ip->state = Dead; } | |
| 1990/0629 | } incontoggle() { incondebug ^= 1; | |
| 1990/0312 | } | |
| 1990/0629/sys/src/9/gnot/devincon.c:89,95 – 1990/0725/sys/src/9/gnot/devincon.c:89,95 (short | long) | ||
| 1990/0312 | enum { Selecting, Selected, | |
| 1990/0725 | Notliving, | |
| 1990/0312 | }; /* | |
| 1990/0629/sys/src/9/gnot/devincon.c:177,183 – 1990/0725/sys/src/9/gnot/devincon.c:177,183 | ||
| 1990/0312 | /* * get us to a known state */ | |
| 1990/0725 | ip->state = Notliving; | |
| 1990/0312 | dev->cmd = INCON_STOP; /* | |
| 1990/0629/sys/src/9/gnot/devincon.c:271,277 – 1990/0725/sys/src/9/gnot/devincon.c:271,277 | ||
| 1990/0331 | /* inconset(&incon[0], 3, 15); /**/ | |
| 1990/0312 | for(i=1; i<Nincon; i++){ incon[i].dev = INCON+i; | |
| 1990/0725 | incon[i].state = Notliving; | |
| 1990/0312 | incon[i].dev->cmd = INCON_STOP; | |
| 1990/0315 | incon[i].ri = incon[i].wi = 0; | |
| 1990/0312 | } | |
| 1990/0629/sys/src/9/gnot/devincon.c:400,406 – 1990/0725/sys/src/9/gnot/devincon.c:400,406 | ||
| 1990/0312 | char name[32]; ip = &incon[s->dev]; | |
| 1990/0725 | sprint(name, "incon%d", s->dev); | |
| 1990/0312 | q->ptr = q->other->ptr = ip; ip->rq = q; kproc(name, inconkproc, ip); | |
| 1990/0629/sys/src/9/gnot/devincon.c:410,416 – 1990/0725/sys/src/9/gnot/devincon.c:410,416 | ||
| 1990/0312 | * kill off the kernel process */ static int | |
| 1990/0725 | kNotliving(void *arg) | |
| 1990/0312 | { Incon *ip; | |
| 1990/0629/sys/src/9/gnot/devincon.c:427,433 – 1990/0725/sys/src/9/gnot/devincon.c:427,433 | ||
| 1990/0312 | ip->rq = 0; qunlock(ip); wakeup(&ip->kr); | |
| 1990/0725 | sleep(&ip->r, kNotliving, ip); | |
| 1990/0312 | } /* | |
| 1990/0629/sys/src/9/gnot/devincon.c:500,506 – 1990/0725/sys/src/9/gnot/devincon.c:500,506 | ||
| 1990/0312 | /* * make sure there's an incon out there */ | |
| 1990/0725 | if(!(dev->status&INCON_ALIVE) || ip->state==Notliving){ | |
| 1990/0312 | inconrestart(ip); freemsg(q, bp); qunlock(&ip->xmit); | |
| 1990/0629/sys/src/9/gnot/devincon.c:812,818 – 1990/0725/sys/src/9/gnot/devincon.c:812,818 | ||
| 1990/0312 | ip->dev->cmd = INCON_STOP; break; } | |
| 1990/0725 | ip->state = Notliving; | |
| 1990/0312 | } | |
| 1990/0629 | } | |
| 1990/0725/sys/src/9/gnot/devincon.c:683,696 – 1990/0731/sys/src/9/gnot/devincon.c:683,696 (short | long) | ||
| 1990/0315 | bp->base[1] = ip->chan>>8; bp->base[2] = c; | |
| 1990/0629 | if(incondebug) | |
| 1990/0731 | print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr); | |
| 1990/0315 | ||
| 1990/0321 |
| |
| 1990/0731 | next = (ip->wi+1)%Nin; | |
| 1990/0321 | if(next == ip->ri){ bp->wptr = bp->base+3; return bp; } | |
| 1990/0731 | ip->wi = next; | |
| 1990/0321 | ||
| 1990/0315 | return ip->inb[ip->wi]; } | |
| 1990/0731/sys/src/9/gnot/devincon.c:493,498 – 1990/0802/sys/src/9/gnot/devincon.c:493,500 (short | long) | ||
| 1990/0312 | chan = bp->rptr[0] | (bp->rptr[1]<<8); ctl = bp->rptr[2]; bp->rptr += 3; | |
| 1990/0802 | if(chan<=0) print("bad channel %d\n", chan); | |
| 1990/0312 | ||
| 1990/0629 | if(incondebug) print("->(%d)%uo %d\n", chan, ctl, bp->wptr - bp->rptr); | |
| 1990/0802/sys/src/9/gnot/devincon.c:610,615 – 1990/1024/sys/src/9/gnot/devincon.c:610,621 (short | long) | ||
| 1990/0315 | bp->wptr += 3; } | |
| 1990/1024 | /* * ignore errors */ if(waserror()) ; | |
| 1990/0312 | for(;;){ /* | |
| 1990/0315 | * sleep if input fifo empty | |
| 1990/1024/sys/src/9/gnot/devincon.c:158,163 – 1990/1101/sys/src/9/gnot/devincon.c:158,198 (short | long) | ||
| 1990/0312 | dev->cmd = INCON_RUN | ENABLE_IRQ; } | |
| 1990/1101 | /* * parse a set request */ void inconsetctl(Incon *ip, Block *bp) { char *field[3]; int n; int del; int cnt; del = 15; n = getfields((char *)bp->rptr, field, 3, ' '); switch(n){ default: freeb(bp); error(0, Ebadarg); case 2: del = strtol(field[1], 0, 0); if(del<0 || del>15){ freeb(bp); error(0, Ebadarg); } /* fall through */ case 1: cnt = strtol(field[0], 0, 0); if(cnt<0 || cnt>15){ freeb(bp); error(0, Ebadarg); } } inconset(ip, cnt, del); freeb(bp); } | |
| 1990/0312 | static void nop(void) { | |
| 1990/1024/sys/src/9/gnot/devincon.c:463,470 – 1990/1101/sys/src/9/gnot/devincon.c:498,510 | ||
| 1990/0312 | int ctl; int n, size; | |
| 1990/1101 | ip = (Incon *)q->ptr; | |
| 1990/0312 | if(bp->type != M_DATA){ | |
| 1990/1101 | if(streamparse("inconset", bp)) inconsetctl(ip, bp); else freeb(bp); | |
| 1990/0312 | return; } | |
| 1990/1024/sys/src/9/gnot/devincon.c:477,483 – 1990/1101/sys/src/9/gnot/devincon.c:517,522 | ||
| 1990/0312 | /* * one transmitter at a time */ | |
| 1990/1024/sys/src/9/gnot/devincon.c:598,603 – 1990/1101/sys/src/9/gnot/devincon.c:637,643 | ||
| 1990/0312 | Incon *ip; | |
| 1990/0322 | Block *bp, *nbp; int i, n; | |
| 1990/1101 | int locked; | |
| 1990/0312 | ip = (Incon *)arg; ip->kstarted = 1; | |
| 1990/1024/sys/src/9/gnot/devincon.c:610,620 – 1990/1101/sys/src/9/gnot/devincon.c:650,663 | ||
| 1990/0315 | bp->wptr += 3; } | |
| 1990/1024 |
| |
| 1990/1101 | locked = 0; if(waserror()){ if(locked) qunlock(ip); ip->kstarted = 0; wakeup(&ip->r); return; } | |
| 1990/1024 | ||
| 1990/0312 | for(;;){ /* | |
| 1990/1024/sys/src/9/gnot/devincon.c:625,630 – 1990/1101/sys/src/9/gnot/devincon.c:668,674 | ||
| 1990/0315 | /* | |
| 1990/0312 | * die if the device is closed */ | |
| 1990/1101 | locked = 1; | |
| 1990/0312 | qlock(ip); if(ip->rq == 0){ qunlock(ip); | |
| 1990/1024/sys/src/9/gnot/devincon.c:646,651 – 1990/1101/sys/src/9/gnot/devincon.c:690,696 | ||
| 1990/0315 | ip->ri = (ip->ri+1)%Nin; } qunlock(ip); | |
| 1990/1101 | locked = 0; | |
| 1990/0315 | } } | |
| 1990/0312 | ||
| 1990/1101/sys/src/9/gnot/devincon.c:131,137 – 1990/11151/sys/src/9/gnot/devincon.c:131,144 (short | long) | ||
| 1990/0312 | static void inconoput(Queue*, Block*); static void inconstopen(Queue*, Stream*); static void inconstclose(Queue*); | |
| 1990/11151 | Qinfo inconinfo = { nullput, inconoput, inconstopen, inconstclose, "incon" }; | |
| 1990/0312 | ||
| 1990/0629 | int incondebug; | |
| 1990/11151/sys/src/9/gnot/devincon.c:151,157 – 1990/11211/sys/src/9/gnot/devincon.c:151,157 (short | long) | ||
| 1990/0312 | Device *dev; | |
| 1990/0315 | if (cnt<1 || cnt>14 || del<1 || del>15) | |
| 1990/0312 |
| |
| 1990/11211 | error(Ebadarg); | |
| 1990/0312 | dev = ip->dev; dev->cmd = sel_rcv_cnt | INCON_RUN; | |
| 1990/11151/sys/src/9/gnot/devincon.c:181,192 – 1990/11211/sys/src/9/gnot/devincon.c:181,192 | ||
| 1990/1101 | switch(n){ default: freeb(bp); | |
| 1990/11211 | error(Ebadarg); | |
| 1990/1101 | case 2: del = strtol(field[1], 0, 0); if(del<0 || del>15){ freeb(bp); | |
| 1990/11211 | error(Ebadarg); | |
| 1990/1101 | } /* fall through */ case 1: | |
| 1990/11151/sys/src/9/gnot/devincon.c:193,199 – 1990/11211/sys/src/9/gnot/devincon.c:193,199 | ||
| 1990/1101 | cnt = strtol(field[0], 0, 0); if(cnt<0 || cnt>15){ freeb(bp); | |
| 1990/11211 | error(Ebadarg); | |
| 1990/1101 | } } inconset(ip, cnt, del); | |
| 1990/11151/sys/src/9/gnot/devincon.c:336,342 – 1990/11211/sys/src/9/gnot/devincon.c:336,342 | ||
| 1990/0312 | i = strtoul(spec, 0, 0); if(i >= Nincon) | |
| 1990/11211 | error(Ebadarg); | |
| 1990/0312 | ip = &incon[i]; if(ip->state != Selected) inconrestart(ip); | |
| 1990/11151/sys/src/9/gnot/devincon.c:343,349 – 1990/11211/sys/src/9/gnot/devincon.c:343,350 | ||
| 1990/0312 | c = devattach('i', spec); c->dev = i; | |
| 1990/11211 | c->qid.path = CHDIR; c->qid.vers = 0; | |
| 1990/0312 | return c; } | |
| 1990/11151/sys/src/9/gnot/devincon.c:368,376 – 1990/11211/sys/src/9/gnot/devincon.c:369,377 | ||
| 1990/0312 | Chan* inconopen(Chan *c, int omode) { | |
| 1990/11211 | if(c->qid.path == CHDIR){ | |
| 1990/0312 | if(omode != OREAD) | |
| 1990/11211 | error(Eperm); | |
| 1990/0312 | }else streamopen(c, &inconinfo); c->mode = openmode(omode); | |
| 1990/11151/sys/src/9/gnot/devincon.c:382,394 – 1990/11211/sys/src/9/gnot/devincon.c:383,395 | ||
| 1990/0312 | void inconcreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1990/11211 | error(Eperm); | |
| 1990/0312 | } void inconclose(Chan *c) { | |
| 1990/11211 | if(c->qid.path != CHDIR) | |
| 1990/0312 | streamclose(c); } | |
| 1990/11151/sys/src/9/gnot/devincon.c:407,431 – 1990/11211/sys/src/9/gnot/devincon.c:408,420 | ||
| 1990/0312 | void inconremove(Chan *c) { | |
| 1990/11211 | error(Eperm); | |
| 1990/0312 | } void inconwstat(Chan *c, char *dp) { | |
| 1990/11211 | error(Eperm); | |
| 1990/0312 | } /* | |
| 1990/11211/sys/src/9/gnot/devincon.c:600,608 – 1990/1212/sys/src/9/gnot/devincon.c:600,619 (short | long) | ||
| 1990/0312 | if(size >= 16){ dev->cdata = 0; | |
| 1990/0320 | MICROSECOND; | |
| 1990/1212 | for(end = NOW+1000; dev->status & TX_FULL;){ nop(); /* make sure we don't optimize too much */ if(NOW > end){ print("incon output stuck\n"); freemsg(q, bp); qunlock(&ip->xmit); return; } } | |
| 1990/0312 | dev->cdata = chan; | |
| 1990/0320 | MICROSECOND; | |
| 1990/0312 | } | |
| 1990/1212 | if(dev->status & TX_FULL) print("inconfull\n"); | |
| 1990/0312 | dev->cdata = ctl; } | |
| 1990/0320 | MICROSECOND; | |
| 1990/1212/sys/src/9/gnot/devincon.c:14,21 – 1990/1214/sys/src/9/gnot/devincon.c:14,20 (short | long) | ||
| 1990/0312 | #define NOW (MACHP(0)->ticks*MS2HZ) | |
| 1990/0315 |
| |
| 1990/1214 | #define MICROSECOND USED(NOW) | |
| 1990/0315 | ||
| 1990/0312 | #define DPRINT if(0) | |
| 1990/1212/sys/src/9/gnot/devincon.c:643,649 – 1990/1214/sys/src/9/gnot/devincon.c:642,648 | ||
| 1990/0312 | { Incon *ip; | |
| 1990/0322 | Block *bp, *nbp; | |
| 1990/1214 | int i; | |
| 1990/1101 | int locked; | |
| 1990/0312 | ip = (Incon *)arg; | |
| 1990/1212/sys/src/9/gnot/devincon.c:675,686 – 1990/1214/sys/src/9/gnot/devincon.c:674,687 | ||
| 1990/0315 | /* | |
| 1990/0312 | * die if the device is closed */ | |
| 1990/1101 |
| |
| 1990/1214 | USED(locked); | |
| 1990/0312 | qlock(ip); | |
| 1990/1214 | locked = 1; | |
| 1990/0312 | if(ip->rq == 0){ qunlock(ip); ip->kstarted = 0; wakeup(&ip->r); | |
| 1990/1214 | poperror(); | |
| 1990/0312 | return; } | |
| 1990/1212/sys/src/9/gnot/devincon.c:690,701 – 1990/1214/sys/src/9/gnot/devincon.c:691,702 | ||
| 1990/0312 | */ | |
| 1990/0315 | while(ip->ri != ip->wi){ | |
| 1990/0322 | bp = ip->inb[ip->ri]; | |
| 1990/0331 | PUTNEXT(ip->rq, bp); | |
| 1990/0320 | bp = ip->inb[ip->ri] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; } | |
| 1990/1214 | USED(locked); | |
| 1990/0315 | qunlock(ip); | |
| 1990/1101 | locked = 0; | |
| 1990/0315 | } | |
| 1990/1214/sys/src/9/gnot/devincon.c:877,883 – 1991/0115/sys/src/9/gnot/devincon.c:877,884 (short | long) | ||
| 1990/0312 | } | |
| 1990/0629 | } | |
| 1991/0115 | void incontoggle(void) | |
| 1990/0629 | { incondebug ^= 1; | |
| 1990/0312 | } | |
| 1991/0115/sys/src/9/gnot/devincon.c:393,405 – 1991/0411/sys/src/9/gnot/devincon.c:393,405 (short | long) | ||
| 1990/0312 | } long | |
| 1991/0411 | inconread(Chan *c, void *buf, long n, ulong offset) | |
| 1990/0312 | { return streamread(c, buf, n); } long | |
| 1991/0411 | inconwrite(Chan *c, void *buf, long n, ulong offset) | |
| 1990/0312 | { return streamwrite(c, buf, n, 0); } | |
| 1991/0411/sys/src/9/gnot/devincon.c:359,364 – 1991/0419/sys/src/9/gnot/devincon.c:359,370 (short | long) | ||
| 1990/0312 | return devwalk(c, name, 0, 0, streamgen); } | |
| 1991/0419 | Chan* inconclwalk(Chan *c, char *name) { return devclwalk(c, name); } | |
| 1990/0312 | void inconstat(Chan *c, char *dp) { | |
| 1991/0419/sys/src/9/gnot/devincon.c:359,370 – 1991/0427/sys/src/9/gnot/devincon.c:359,364 (short | long) | ||
| 1990/0312 | return devwalk(c, name, 0, 0, streamgen); } | |
| 1991/0419 |
| |
| 1990/0312 | void inconstat(Chan *c, char *dp) { | |
| 1991/0427/sys/src/9/gnot/devincon.c:272,279 – 1991/0906/sys/src/9/gnot/devincon.c:272,277 (short | long) | ||
| 1990/0312 | if(!canqlock(&ip->reslock)) return; | |
| 1990/0623 |
| |
| 1990/0312 | /* * poll for incon station numbers */ | |
| 1991/0906/sys/src/9/gnot/devincon.c:24,30 – 1991/1122/sys/src/9/gnot/devincon.c:24,32 (short | long) | ||
| 1990/0312 | Nincon= 1, /* number of incons */ | |
| 1990/0322 | Nin= 32, /* Blocks in the input ring */ | |
| 1990/0320 | Bsize= 128, /* size of an input ring block */ | |
| 1990/0321 |
| |
| 1991/1122 | Mfifo= 0xff, /* a mask, must be 2^n-1, must be > Nin */ Qstats= 1, /* qid of the statistics file */ | |
| 1990/0312 | }; /* | |
| 1991/0906/sys/src/9/gnot/devincon.c:78,83 – 1991/1122/sys/src/9/gnot/devincon.c:80,86 | ||
| 1990/0312 | ulong crc; /* crc errors */ ulong in; /* bytes in */ ulong out; /* bytes out */ | |
| 1991/1122 | ulong wait; /* wait time in milliseconds */ | |
| 1990/0312 | }; Incon incon[Nincon]; | |
| 1991/0906/sys/src/9/gnot/devincon.c:141,146 – 1991/1122/sys/src/9/gnot/devincon.c:144,153 | ||
| 1990/0312 | ||
| 1990/0629 | int incondebug; | |
| 1991/1122 | Dirtab incondir[]={ "stats", {Qstats}, 0, 0444, }; | |
| 1990/0312 | /* * set the incon parameters */ | |
| 1991/0906/sys/src/9/gnot/devincon.c:354,372 – 1991/1122/sys/src/9/gnot/devincon.c:361,379 | ||
| 1990/0312 | int inconwalk(Chan *c, char *name) { | |
| 1991/1122 | return devwalk(c, name, incondir, 1, streamgen); | |
| 1990/0312 | } void inconstat(Chan *c, char *dp) { | |
| 1991/1122 | devstat(c, dp, incondir, 1, streamgen); | |
| 1990/0312 | } Chan* inconopen(Chan *c, int omode) { | |
| 1990/11211 |
| |
| 1991/1122 | if(c->qid.path == CHDIR || c->qid.path == Qstats){ | |
| 1990/0312 | if(omode != OREAD) | |
| 1990/11211 | error(Eperm); | |
| 1990/0312 | }else | |
| 1991/0906/sys/src/9/gnot/devincon.c:393,399 – 1991/1122/sys/src/9/gnot/devincon.c:400,417 | ||
| 1990/0312 | long | |
| 1991/0411 | inconread(Chan *c, void *buf, long n, ulong offset) | |
| 1990/0312 | { | |
| 1991/1122 | char b[256]; Incon *i; if(c->qid.path == CHDIR) return devdirread(c, buf, n, incondir, 1, streamgen); else if(c->qid.path == Qstats){ i = &incon[c->dev]; sprint(b, "in: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n", i->in, i->out, i->overflow, i->crc, i->wait); return stringread(buf, n, b, offset); } else return streamread(c, buf, n); | |
| 1990/0312 | } long | |
| 1991/0906/sys/src/9/gnot/devincon.c:486,492 – 1991/1122/sys/src/9/gnot/devincon.c:504,510 | ||
| 1990/0312 | { Device *dev; Incon *ip; | |
| 1991/1122 | ulong start, end; | |
| 1990/0312 | int chan; int ctl; int n, size; | |
| 1991/0906/sys/src/9/gnot/devincon.c:548,554 – 1991/1122/sys/src/9/gnot/devincon.c:566,573 | ||
| 1990/0312 | /* * spin till there is room */ | |
| 1991/1122 | start = NOW; for(n = 0, end = start+1000; dev->status & TX_FULL; n++){ | |
| 1990/0312 | nop(); /* make sure we don't optimize too much */ if(NOW > end){ print("incon output stuck\n"); | |
| 1991/0906/sys/src/9/gnot/devincon.c:557,562 – 1991/1122/sys/src/9/gnot/devincon.c:576,582 | ||
| 1990/0312 | return; } } | |
| 1991/1122 | ip->wait = (n + ip->wait)>>1; | |
| 1990/0312 | /* * put in next packet | |
| 1991/0906/sys/src/9/gnot/devincon.c:566,571 – 1991/1122/sys/src/9/gnot/devincon.c:586,592 | ||
| 1990/0312 | n = 16; size = n; dev->cdata = chan; | |
| 1991/1122 | ip->out += n; | |
| 1990/0312 | while(n--){ *(uchar *)&dev->data_cntl = *bp->rptr++; } | |
| 1991/0906/sys/src/9/gnot/devincon.c:689,694 – 1991/1122/sys/src/9/gnot/devincon.c:710,716 | ||
| 1990/0312 | */ | |
| 1990/0315 | while(ip->ri != ip->wi){ | |
| 1990/0322 | bp = ip->inb[ip->ri]; | |
| 1991/1122 | ip->in += BLEN(bp); | |
| 1990/0331 | PUTNEXT(ip->rq, bp); | |
| 1990/0320 | bp = ip->inb[ip->ri] = allocb(Bsize); | |
| 1990/0315 | bp->wptr += 3; | |
| Too many diffs (26 > 25). Stopping. | ||