📄 devastar.c
字号:
} else if(strncmp(cmsg, "run", 3) == 0){ /* start up downloaded program */ startcp(a); } else error(Ebadarg); qunlock(a); poperror();}/* * Send a command to a channel * (must be called with ac qlocked) */static intchancmddone(void *arg){ Astarchan *ac = arg; int x; LOCKPAGE(ac->a, 0); x = ac->ccb->cmd; UNLOCKPAGE(ac->a); return !x;}static voidchancmd(Astarchan *ac, int cmd){ CCB *ccb; int status; ccb = ac->ccb; LOCKPAGE(ac->a, 0); ccb->cmd = cmd; UNLOCKPAGE(ac->a); /* wait outside of lock */ tsleep(&ac->r, chancmddone, ac, 1000); LOCKPAGE(ac->a, 0); status = ccb->status; cmd = ccb->cmd; UNLOCKPAGE(ac->a); if(cmd){ print("#G%d: cmd didn't terminate\n", ac->a->id); error(Eio); } if(status){ print("#G%d: cmd status %ux\n", ac->a->id, status); error(Eio); }}/* * enable a channel for IO, set standard params. * (must be called with ac qlocked) */static voidenable(Astarchan *ac){ Astar *a = ac->a; int n; /* make sure we control RTS, DTR and break */ LOCKPAGE(a, 0); n = LEUS(ac->ccb->proto) | Cmctl; ac->ccb->proto = LEUS(n); ac->ccb->outlow = 64; UNLOCKPAGE(a); chancmd(ac, Cconfall); astarctl(ac, "l8"); astarctl(ac, "p0"); astarctl(ac, "d1"); astarctl(ac, "r1"); chancmd(ac, Crcvena|Cxmtena|Cconfall);}/* * disable a channel for IO * (must be called with ac qlocked) */static voiddisable(Astarchan *ac){ int n; astarctl(ac, "d0"); astarctl(ac, "r0"); LOCKPAGE(ac->a, 0); n = LEUS(ac->ccb->proto) | Cmctl; ac->ccb->proto = LEUS(n); UNLOCKPAGE(ac->a); chancmd(ac, Crcvdis|Cxmtdis|Cflushin|Cflushout|Cconfall); ac->dsr = ac->dcd = 0;}/* * change channel parameters * (must be called with ac qlocked) */static voidastarctl(Astarchan *ac, char *cmd){ int i, n; int command; CCB *ccb; Astar *a; /* let output drain for a while */ for(i = 0; i < 16 && qlen(ac->oq); i++) tsleep(&ac->r, (int (*)(void*))qlen, ac->oq, 125); if(strncmp(cmd, "break", 5) == 0) cmd = "k"; ccb = ac->ccb; command = 0; i = atoi(cmd+1); a = ac->a; LOCKPAGE(a, 0); switch(*cmd){ case 'B': case 'b': /* set baud rate (high rates are special - only 16 bits) */ switch(i){ case 76800: ccb->baud = LEUS(Cb76800); break; case 115200: ccb->baud = LEUS(Cb115200); break; default: ccb->baud = LEUS(i); break; } ac->baud = i; /* set trigger level to about 50 per second */ n = i/500; i = (LEUS(ccb->inlim) - LEUS(ccb->inbase))/2; if(n > i) n = i; ccb->intrigger = LEUS(n); command = Cconfall; break; case 'D': case 'd': n = LEUS(ccb->mctl); if(i) n |= Cdtrctl; else n &= ~Cdtrctl; ac->dtr = i; ccb->mctl = LEUS(n); break; case 'f': case 'F': qflush(ac->oq); break; case 'H': case 'h': qhangup(ac->iq, nil); qhangup(ac->oq, nil); break; case 'L': case 'l': n = i - 5; if(n < 0 || n > 3) error(Ebadarg); n |= LEUS(ccb->format) & ~Clenmask; ccb->format = LEUS(n); command = Cconfall; break; case 'm': case 'M': /* turn on cts */ n = LEUS(ccb->proto); if(i){ n |= Cobeycts|Cgenrts; n &= ~Cmctl; } else { n &= ~(Cobeycts|Cgenrts); n |= Cmctl; } ccb->proto = LEUS(n); command = Cconfall; break; case 'n': case 'N': qnoblock(ac->oq, i); break; case 'P': case 'p': switch(*(cmd+1)){ case 'e': n = Cevenpar; break; case 'o': n = Coddpar; break; default: n = Cnopar; break; } n |= LEUS(ccb->format) & ~Cparmask; ccb->format = LEUS(n); command = Cconfall; break; case 'K': case 'k': if(i <= 0) i = 250; n = LEUS(ccb->mctl) | Cbreakctl; ccb->mctl = LEUS(n); UNLOCKPAGE(a); tsleep(&ac->r, return0, 0, i); LOCKPAGE(a, 0); n &= ~Cbreakctl; ccb->mctl = LEUS(n); break; case 'R': case 'r': n = LEUS(ccb->mctl); if(i) n |= Crtsctl; else n &= ~Crtsctl; ccb->mctl = LEUS(n); ac->rts = i; break; case 'Q': case 'q': qsetlimit(ac->iq, i); qsetlimit(ac->oq, i); break; case 'X': case 'x': n = LEUS(ccb->proto); if(i) n |= Cobeyxon; else n &= ~Cobeyxon; ccb->proto = LEUS(n); command = Cconfall; break; } UNLOCKPAGE(a); if(command) chancmd(ac, command);}static longastarwrite(Chan *c, void *buf, long n, vlong off){ Astar *a; Astarchan *ac; char cmsg[32]; ulong offset = off; if(c->qid.path & CHDIR) error(Eperm); a = astar[BOARD(c->qid.path)]; switch(TYPE(c->qid.path)){ case Qmem: if(a->pci) return pcimemwrite(a, buf, n, offset); return isamemwrite(a, buf, n, offset); case Qbctl: if(n > sizeof cmsg) n = sizeof(cmsg) - 1; memmove(cmsg, buf, n); cmsg[n] = 0; bctlwrite(a, cmsg); return n; case Qdata: ac = a->c + CHAN(c->qid.path); return qwrite(ac->oq, buf, n); case Qctl: ac = a->c + CHAN(c->qid.path); if(n > sizeof cmsg) n = sizeof(cmsg) - 1; memmove(cmsg, buf, n); cmsg[n] = 0; if(waserror()){ qunlock(ac); nexterror(); } qlock(ac); astarctl(ac, cmsg); qunlock(ac); poperror(); } return 0;}static voidastarwstat(Chan *c, char *dp){ Dir d; Astarchan *ac; if(!iseve()) error(Eperm); if(CHDIR & c->qid.path) error(Eperm); if(TYPE(c->qid.path) != Qdata && TYPE(c->qid.path) != Qctl) error(Eperm); ac = astar[BOARD(c->qid.path)]->c + CHAN(c->qid.path); convM2D(dp, &d); d.mode &= 0666; ac->perm = d.mode;}Dev astardevtab = { 'G', "astar", astarreset, devinit, astarattach, devclone, astarwalk, astarstat, astaropen, devcreate, astarclose, astarread, devbread, astarwrite, devbwrite, devremove, astarwstat,};/* * get output going */static voidastaroutput(Astarchan *ac){ Astar *a = ac->a; CCB *ccb = ac->ccb; uchar buf[256]; uchar *rp, *wp, *bp, *ep, *p, *e; int n; if(a->needpage) setpage(a, 0); ep = a->addr; rp = ep + LEUS(ccb->outrp); wp = ep + LEUS(ccb->outwp); bp = ep + LEUS(ccb->outbase); ep = ep + LEUS(ccb->outlim); for(;;){ n = rp - wp - 1; if(n < 0) n += ep - bp + 1; if(n == 0) break; if(n > sizeof(buf)) n = sizeof(buf); n = qconsume(ac->oq, buf, n); if(n <= 0) break; if(a->needpage) setpage(a, bp - a->addr); e = buf + n; for(p = buf; p < e;){ *wp++ = *p++; if(wp > ep) wp = bp; } if(a->needpage) setpage(a, 0); ccb->outwp = LEUS(wp - a->addr); }}static voidastarkick(void *v){ Astarchan *ac; ac = v; ilock(&ac->a->pagelock); astaroutput(ac); iunlock(&ac->a->pagelock);}/* * process input */static voidastarinput(Astarchan *ac){ Astar *a = ac->a; CCB *ccb = ac->ccb; uchar buf[256]; uchar *rp, *wp, *bp, *ep, *p, *e; int n; if(a->needpage) setpage(a, 0); ep = a->addr; rp = ep + LEUS(ccb->inrp); wp = ep + LEUS(ccb->inwp); bp = ep + LEUS(ccb->inbase); ep = ep + LEUS(ccb->inlim); for(;;){ n = wp - rp; if(n == 0) break; if(n < 0) n += ep - bp + 1; if(n > sizeof(buf)) n = sizeof(buf); if(a->needpage) setpage(a, bp - a->addr); e = buf + n; for(p = buf; p < e;){ *p++ = *rp++; if(rp > ep) rp = bp; } if(ac->opens == 0 || qproduce(ac->iq, buf, n) < 0) break; /* flow controlled or not open */ if(a->needpage) setpage(a, 0); ccb->inrp = LEUS(rp - a->addr); } if(a->needpage) setpage(a, 0);}/* * get flow controlled input going again */static voidastarkickin(void *v){ Astarchan *ac; ac = v; ilock(&ac->a->pagelock); astarinput(ac); iunlock(&ac->a->pagelock);}static voidastarmodemchange(Astarchan *ac){ Astar *a = ac->a; int mstat; if(a->needpage) setpage(a, 0); mstat = LEUS(ac->ccb->mstat); if(ac->hup_dsr && ac->dsr == 1 && (mstat & Cdsrstat) == 0 || ac->hup_dcd && ac->dcd == 1 && (mstat & Cdcdstat) == 0){ qhangup(ac->iq, nil); qhangup(ac->oq, nil); } ac->dsr = mstat & Cdsrstat; ac->dcd = mstat & Cdcdstat;}/* * handle an interrupt */static voidastarintr(Ureg *ur, void *arg){ Astar *a = arg; Astarchan *ac; ulong globvec, vec, invec, outvec, errvec, mvec, cmdvec; int c, status; USED(ur); if(a->running == 0) panic("#G%d: interrupt but cp not running\n", a->id); lock(&a->pagelock); if(a->needpage) setpage(a, 0); /* get causes */ globvec = LEUS(xchgw(&a->gcb->serv, 0)); USED(globvec); invec = LEUS(xchgw(&a->gcb->inserv, 0)); outvec = LEUS(xchgw(&a->gcb->outserv, 0)); errvec = LEUS(xchgw(&a->gcb->errserv, 0)); mvec = LEUS(xchgw(&a->gcb->modemserv, 0)); cmdvec = LEUS(xchgw(&a->gcb->cmdserv, 0)); /* reenable interrupts */ if(a->pci){ /* * Only the PCI doorbell interrupt is expected. */ status = inl(a->port+PCIstatus); if((status & 0x0810E000) != 0x00002000) print("#G%d: unexpected interrupt %uX\n", a->id, status); if(status & 0x00002000) outl(a->port+PCIdoorbell1, 1); } a->gcb->cmd2 = LEUS(Gintack); /* service interrupts */ ac = a->c; for(vec = invec; vec; vec >>= 1){ if(vec&1) astarinput(ac); ac++; } ac = a->c; for(vec = outvec; vec; vec >>= 1){ if(vec&1) astaroutput(ac); ac++; } ac = a->c; for(vec = cmdvec; vec; vec >>= 1){ if(vec&1) wakeup(&ac->r); ac++; } ac = a->c; for(vec = mvec; vec; vec >>= 1){ if(vec&1) astarmodemchange(ac); ac++; } ac = a->c; for(vec = errvec; vec; vec >>= 1){ c = LEUS(ac->ccb->errstat); if(c & Cframing) ac->framing++; if(c & Coverrun) ac->overrun++; ac++; } unlock(&a->pagelock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -