📄 devastar.c
字号:
if(ioalloc(a->port, 6, 0, name) < 0){ print("#G%d: port 0x%lux in use\n", a->id, a->port); return -1; } found = astarprobe(a->port); } if(!found){ print("#G%d: not found\n", a->id); iofree(a->port); return -1; } /* check interrupt level */ if(isairqcode[a->irq] == -1){ print("#G%d: bad irq %lud\n", a->id, a->irq); iofree(a->port); return -1; } /* set ISA memory address */ outb(a->port+ISAmaddr, (a->mem>>12) & 0xfc); a->gcb = KADDR(a->mem); a->addr = KADDR(a->mem); /* disable ISA memory response */ outb(a->port+ISActl2, 0); a->memsize = 0; a->page = -1; /* reset processor */ outb(a->port+ISActl1, 0); return 0;}static Chan*astarattach(char *spec){ ulong ctlrno; char *p; ctlrno = 0; if(spec && *spec){ ctlrno = strtoul(spec, &p, 0); if((ctlrno == 0 && p == spec) || *p || (ctlrno >= Maxcard)) error(Ebadarg); } if(astar[ctlrno] == nil) error(Enodev); return devattach('G', spec);}static intastarwalk(Chan *c, char *name){ return devwalk(c, name, 0, 0, astargen);}static voidastarstat(Chan *c, char *dp){ devstat(c, dp, 0, 0, astargen);}static Chan*astaropen(Chan *c, int omode){ Astar *a; Astarchan *ac; c = devopen(c, omode, 0, 0, astargen); a = astar[BOARD(c->qid.path)]; switch(TYPE(c->qid.path)){ case Qmem: case Qbctl: if(!iseve()) error(Eperm); break; case Qdata: case Qctl: ac = a->c + CHAN(c->qid.path); qlock(ac); if(waserror()){ qunlock(ac); ac->opens--; nexterror(); } if(ac->opens++ == 0){ enable(ac); qreopen(ac->iq); qreopen(ac->oq); } qunlock(ac); poperror(); break; } return c;}static voidastarclose(Chan *c){ Astar *a; Astarchan *ac; if((c->flag & COPEN) == 0) return; a = astar[BOARD(c->qid.path)]; switch(TYPE(c->qid.path)){ case Qdata: case Qctl: ac = a->c + CHAN(c->qid.path); qlock(ac); if(waserror()){ qunlock(ac); nexterror(); } if(--(ac->opens) == 0){ disable(ac); qclose(ac->iq); qclose(ac->oq); } qunlock(ac); poperror(); break; }}/* * read PCI mapped memory */static longpcimemread(Astar *a, uchar *to, long n, ulong offset){ uchar *from; int rem; if(offset+n > a->memsize){ if(offset >= a->memsize) return 0; n = a->memsize - offset; } from = a->addr+offset; for(rem = n; rem > 0; rem--) *to++ = *from++; return n;}/* * read ISA mapped memory */static longisamemread(Astar *a, uchar *to, long n, ulong offset){ uchar *from, *e, *tp; int i, rem; uchar tmp[256]; if(offset+n > a->memsize){ if(offset >= a->memsize) return 0; n = a->memsize - offset; } for(rem = n; rem > 0; rem -= i){ /* map in right piece of memory */ i = offset&Pagemask; from = a->addr + i; i = Pagesize - i; if(i > rem) i = rem; if(i > sizeof(tmp)) i = sizeof(tmp); /* * byte at a time so endian doesn't matter, * go via tmp to avoid pagefaults while ilock'd */ tp = tmp; LOCKPAGE(a, offset); for(e = tp + i; tp < e;) *tp++ = *from++; UNLOCKPAGE(a); memmove(to, tmp, i); to += i; offset += i; } return n;}/* * read ISA status */static longbctlread(Astar *a, void *buf, long n, ulong offset){ char s[128]; if(a->pci) sprint(s, "range %luX remap %luX region %luX mailbox %luX doorbell0 %luX doorbell1 %luX control %luX command %luX", inl(a->port+PCIrange), inl(a->port+PCIremap), inl(a->port+PCIregion), inl(a->port+PCImailbox), inl(a->port+PCIdoorbell0), inl(a->port+PCIdoorbell1), inl(a->port+PCIcontrol), inl(a->port+PCIcommand)); else sprint(s, "id %4.4ux ctl1 %2.2ux ctl2 %2.2ux maddr %2.2ux stat %4.4ux", (inb(a->port+ISAid)<<8)|inb(a->port+ISAid), inb(a->port+ISActl1), inb(a->port+ISActl2), inb(a->port+ISAmaddr), (inb(a->port+ISAstat2)<<8)|inb(a->port+ISAstat1)); return readstr(offset, buf, n, s);}static longstatread(Astarchan *ac, void *buf, long n, ulong offset){ char s[256]; int mstat, bstat, fstat; LOCKPAGE(ac->a, 0); mstat = LEUS(ac->ccb->mstat); bstat = LEUS(ac->ccb->bstat); fstat = LEUS(ac->ccb->format); UNLOCKPAGE(ac->a); snprint(s, sizeof s, "b%d c%d d%d e%d l%d m%d p%c r%d s%d\n" "%ld %d %d%s%s%s%s\n", ac->baud, ac->hup_dcd, ac->dtr, ac->hup_dsr, (fstat & Clenmask), 0, /* change in modem status? */ (fstat & Cparmask) ? ((fstat & Cevenpar) == Cevenpar ? 'e' : 'o') : 'n', (bstat & Crbrts) ? 1 : 0, (fstat & C2stop) ? 2 : 1, ac - ac->a->c, ac->framing, ac->overrun, (mstat & Cctsstat) ? " cts" : "", (mstat & Cdsrstat) ? " dsr" : "", (mstat & Cdcdstat) ? " dcd" : "", (mstat & Cristat) ? " ring" : "" ); return readstr(offset, buf, n, s);}static longastarread(Chan *c, void *buf, long n, vlong off){ Astar *a; Astarchan *ac; ulong offset = off; if(c->qid.path & CHDIR) return devdirread(c, buf, n, 0, 0, astargen); switch(TYPE(c->qid.path)){ case Qstat: a = astar[BOARD(c->qid.path)]; return statread(a->c + CHAN(c->qid.path), buf, n, offset); case Qmem: a = astar[BOARD(c->qid.path)]; if(a->pci) return pcimemread(a, buf, n, offset); return isamemread(a, buf, n, offset); case Qbctl: return bctlread(astar[BOARD(c->qid.path)], buf, n, offset); case Qdata: a = astar[BOARD(c->qid.path)]; ac = a->c + CHAN(c->qid.path); return qread(ac->iq, buf, n); } return 0;}/* * write PCI mapped memory */static longpcimemwrite(Astar *a, uchar *from, long n, ulong offset){ uchar *to; int rem; ulong limit; /* * Disallow writes above 0xD000 where the i960 * data structures live if writing in the lower bank. */ if(a->addr == (uchar*)a->mem) limit = 0xD000; else limit = a->memsize; if(offset+n > limit){ if(offset >= limit) return 0; n = limit - offset; } to = a->addr+offset; for(rem = n; rem > 0; rem--) *to++ = *from++; return n;}/* * write ISA mapped memory */static longisamemwrite(Astar *a, uchar *from, long n, ulong offset){ uchar *to, *e, *tp; int i, rem; uchar tmp[256]; if(offset+n > a->memsize){ if(offset >= a->memsize) return 0; n = a->memsize - offset; } for(rem = n; rem > 0; rem -= i){ /* map in right piece of memory */ i = offset&Pagemask; to = a->addr + i; i = Pagesize - i; if(i > rem) i = rem; if(i > sizeof(tmp)) i = sizeof(tmp); /* * byte at a time so endian doesn't matter, * go via tmp to avoid pagefaults while ilock'd */ memmove(tmp, from, i); tp = tmp; LOCKPAGE(a, offset); for(e = tp + i; tp < e;) *to++ = *tp++; UNLOCKPAGE(a); from += i; offset += i; } return n;}/* * put board into download mode */static voiddownloadmode(Astar *a){ int c, i; /* put board in download mode */ if(a->pci){ /* * Don't let the download write over the * i960 data structures. */ a->memsize = 0xD000; a->addr = (uchar*)a->mem; } else{ a->memsize = Pramsize; a->needpage = 1; c = inb(a->port+ISActl1); outb(a->port+ISActl1, c & ~ISAnotdl); /* give it up to 5 seconds to reset */ for(i = 0; i < 21; i++){ if(!(inb(a->port+ISActl1) & ISAnotdl)) break; tsleep(&a->r, return0, 0, 500); } if(inb(a->port+ISActl1) & ISAnotdl){ print("#G%d: did not reset\n", a->id); error(Eio); } /* enable ISA access to first 16k */ a->page = -1; setpage(a, 0); }}/* * start control program */static voidstartcp(Astar *a){ int c, n, i, sz; uchar *x; CCB *ccb; Astarchan *ac; char name[10]; if(a->running) error(Eio); /* take board out of download mode and enable IRQ */ if(a->pci){ outl(a->port+PCImailbox, 1); /* wait for control program to signal life */ delay(100); for(i = 0; i < 10; i++){ if(inl(a->port+PCImailbox) & 0x80000000) break; tsleep(&a->r, return0, 0, 100); } if(!(inl(a->port+PCImailbox) & 0x80000000)){ print("#G%d: program not ready\n", a->id); //error(Eio); } a->addr = (uchar*)(a->mem+0x10000); } else{ c = inb(a->port+ISActl1); outb(a->port+ISActl1, c|ISAien|ISAnotdl); /* wait for control program to signal life */ for(i = 0; i < 21; i++){ if(inb(a->port+ISActl1) & ISApr) break; tsleep(&a->r, return0, 0, 500); } if((inb(a->port+ISActl1) & ISApr) == 0){ print("#G%d: program not ready\n", a->id); error(Eio); } } a->memsize = a->ramsize; if(a->pci || a->memsize <= Pagesize) a->needpage = 0; else{ a->page = -1; setpage(a, 0); a->needpage = 1; } if(waserror()){ UNLOCKPAGE(a); poperror(); } LOCKPAGE(a, 0); i = LEUS(a->gcb->type); switch(i){ default: print("#G%d: wrong board type %uX\n", a->id, i); error(Eio); case 0x0C: case 0x12: /* AvanstarXp */ break; } /* check assumptions */ n = LEUS(a->gcb->ccbn); if(n != 8 && n != 16){ print("#G%d: has %d channels?\n", a->id, i); error(Eio); } x = a->addr + LEUS(a->gcb->ccboff); sz = LEUS(a->gcb->ccbsz); if(x+n*sz > a->addr+Pagesize){ print("#G%d: ccb's not in 1st page\n", a->id); error(Eio); } for(i = 0; i < n; i++){ ccb = (CCB*)(x + i*sz); if(APAGE(LEUS(ccb->inbase)) != APAGE(LEUS(ccb->inlim)) || APAGE(LEUS(ccb->outbase)) != APAGE(LEUS(ccb->outlim))){ print("#G%d: chan buffer spans pages\n", a->id); error(Eio); } } UNLOCKPAGE(a); poperror(); /* setup the channels */ a->running = 1; a->nchan = i; a->c = smalloc(a->nchan * sizeof(Astarchan)); for(i = 0; i < a->nchan; i++){ ac = &a->c[i]; ac->a = a; ac->ccb = (CCB*)x; ac->baud = 9600; /* a100i default */ ac->perm = 0660; ac->iq = qopen(4*1024, 0, astarkickin, ac); ac->oq = qopen(4*1024, 0, astarkick, ac); x += sz; } snprint(name, sizeof name, "astar%d", a->id); /* set up interrupt level, enable interrupts */ if(a->pci){ /* * Which bits in the interrupt control register should be set? */ outl(a->port+PCIcontrol, 0x00031F00); intrenable(a->irq, astarintr, a, a->pci->tbdf, name); } else{ c = inb(a->port+ISActl1); c &= ~ISAirq; c |= ISAien|isairqcode[a->irq]; outb(a->port+ISActl1, c); intrenable(a->irq, astarintr, a, BUSUNKNOWN, name); } /* enable control program interrupt generation */ LOCKPAGE(a, 0); a->gcb->cmd2 = LEUS(Gintack); UNLOCKPAGE(a);}static voidbctlwrite(Astar *a, char *cmsg){ if(waserror()){ qunlock(a); nexterror(); } qlock(a); if(a->running) error(Eio); if(strncmp(cmsg, "download", 8) == 0){ /* put board in download mode */ downloadmode(a);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -