| plan 9 kernel history: overview | file list | diff list |
1990/0315/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 | prev | next) | ||
| 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; } | |