| plan 9 kernel history: overview | file list | diff list |
1994/1113/pc/devastar.c (diff list | history)
| 1994/1112/sys/src/9/pc/devastar.c:11,17 – 1994/1113/sys/src/9/pc/devastar.c:11,30 (short | long | prev | next) | ||
| 1994/1106 | /* | |
| 1994/1107 | * Stargate's Avanstar serial board. There are ISA, EISA, microchannel * versions. We only handle the ISA one. | |
| 1994/1113 | * * At the expense of performance, I've tried to be careful about * endian-ness to make this convertable to other ISA bus machines. * However, xchngus() is in assembler and will have to be translated. | |
| 1994/1106 | */ | |
| 1994/1113 | #define LENDIAN 1 /* unsigned short little endian representation */ #ifdef LENDIAN #define LEUS(x) (x) #else #define LEUS(x) ( (((x)<<8)&0xff00) | (((x)>>8)&0xff) ) #endif LENDIAN | |
| 1994/1106 | typedef struct Astar Astar; | |
| 1994/1107 | typedef struct Astarchan Astarchan; | |
| 1994/1106 | ||
| 1994/1112/sys/src/9/pc/devastar.c:37,46 – 1994/1113/sys/src/9/pc/devastar.c:50,62 | ||
| 1994/1107 | ||
| 1994/1112 | Maxcard= 8, Pramsize= 64*1024, /* size of program ram */ | |
| 1994/1113 | Pageshift= 14, /* footprint of card mem in ISA space */ Pagesize= 1<<Pageshift, Pagemask= Pagesize-1, | |
| 1994/1106 | }; | |
| 1994/1113 | #define APAGE(x) ((x)>>Pageshift) | |
| 1994/1107 | /* IRQ codes */ static int isairqcode[16] = { | |
| 1994/1112/sys/src/9/pc/devastar.c:60,68 – 1994/1113/sys/src/9/pc/devastar.c:76,84 | ||
| 1994/1106 | ushort avail; /* available buffer space */ ushort type; /* board type */ ushort cpvers; /* control program version */ | |
| 1994/1113 | ushort ccbn; /* control channel block count */ ushort ccboff; /* control channel block offset */ ushort ccbsz; /* control channel block size */ | |
| 1994/1106 | ushort cmd2; /* command word 2 */ ushort status2; /* status word 2 */ ushort errserv; /* comm error service request 'X' */ | |
| 1994/1112/sys/src/9/pc/devastar.c:146,155 – 1994/1113/sys/src/9/pc/devastar.c:162,168 | ||
| 1994/1107 | Cb115200= 0xff01, /* CCB.format fields */ | |
| 1994/1113 | Clenmask= 3<<0, /* data bits */ | |
| 1994/1107 | C1stop= 0<<2, /* stop bits */ C2stop= 1<<2, Cnopar= 0<<3, /* parity */ | |
| 1994/1112/sys/src/9/pc/devastar.c:157,162 – 1994/1113/sys/src/9/pc/devastar.c:170,176 | ||
| 1994/1107 | Cevenpar= 3<<3, Cmarkpar= 5<<3, Cspacepar= 7<<3, | |
| 1994/1113 | Cparmask= 7<<3, | |
| 1994/1107 | Cnormal= 0<<6, /* normal mode */ Cecho= 1<<6, /* echo mode */ Clloop= 2<<6, /* local loopback */ | |
| 1994/1112/sys/src/9/pc/devastar.c:220,230 – 1994/1113/sys/src/9/pc/devastar.c:234,248 | ||
| 1994/1107 | ISAConf; int id; /* from plan9.ini */ | |
| 1994/1111 | int nchan; /* number of channels */ | |
| 1994/1112 |
| |
| 1994/1111 | Astarchan *c; /* channels */ | |
| 1994/1107 | int ramsize; /* 16k or 256k */ | |
| 1994/1106 |
| |
| 1994/1112 |
| |
| 1994/1113 | int memsize; /* size of memory currently mapped */ int page; /* page currently mapped */ GCB *gbc; /* global board comm area */ uchar *addr; /* base of memory area */ int running; Rendez r; /* when waiting for board */ | |
| 1994/1106 | }; /* host per channel info */ | |
| 1994/1112/sys/src/9/pc/devastar.c:233,239 – 1994/1113/sys/src/9/pc/devastar.c:251,257 | ||
| 1994/1106 | QLock; | |
| 1994/1109 | Astar *a; /* controller */ | |
| 1994/1107 |
| |
| 1994/1113 | CCB *ccb; /* channel control block */ | |
| 1994/1111 | int perm; | |
| 1994/1112 | int opens; | |
| 1994/1107 | ||
| 1994/1112/sys/src/9/pc/devastar.c:240,245 – 1994/1113/sys/src/9/pc/devastar.c:258,264 | ||
| 1994/1106 | /* buffers */ Queue *iq; Queue *oq; | |
| 1994/1113 | Rendez r; | |
| 1994/1106 | }; | |
| 1994/1109 | Astar *astar[Maxcard]; | |
| 1994/1112/sys/src/9/pc/devastar.c:260,265 – 1994/1113/sys/src/9/pc/devastar.c:279,302 | ||
| 1994/1111 | ||
| 1994/1109 | static int astarsetup(Astar*); | |
| 1994/1107 | ||
| 1994/1113 | /* * Only 16k maps into ISA space */ void setpage(Astar *a, ulong offset) { int i; i = APAGE(offset); if(i == a->page) return; outb(a->port+ISActl2, ISAmen|i); a->page = i; } /* * generate the astar directory entries */ | |
| 1994/1111 | int | |
| 1994/1112 | astargen(Chan *c, Dirtab *tab, int ntab, int i, Dir *db) | |
| 1994/1111 | { | |
| 1994/1112/sys/src/9/pc/devastar.c:355,360 – 1994/1113/sys/src/9/pc/devastar.c:392,398 | ||
| 1994/1107 | if(a->irq == 0) a->irq = 15; a->id = i; | |
| 1994/1113 | a->page = -1; | |
| 1994/1107 | if(astarsetup(a) < 0){ xfree(a); | |
| 1994/1112/sys/src/9/pc/devastar.c:377,384 – 1994/1113/sys/src/9/pc/devastar.c:415,422 | ||
| 1994/1107 | if(port < 0) return 0; | |
| 1994/1113 | c = inb(port+ISAid); c1 = inb(port+ISAid); | |
| 1994/1107 | return (c == ISAid0 && c1 == ISAid1) | |
| 1994/1112 | || (c == ISAid1 && c1 == ISAid0); | |
| 1994/1107 | } | |
| 1994/1112/sys/src/9/pc/devastar.c:407,413 – 1994/1113/sys/src/9/pc/devastar.c:445,451 | ||
| 1994/1107 | } /* set memory address */ | |
| 1994/1113 | outb(a->port+ISAmaddr, (a->mem>>12) & 0xfc); | |
| 1994/1112 | a->gbc = (GCB*)(KZERO | a->mem); a->addr = (char*)(KZERO | a->mem); | |
| 1994/1107 | ||
| 1994/1112/sys/src/9/pc/devastar.c:479,496 – 1994/1113/sys/src/9/pc/devastar.c:517,534 | ||
| 1994/1112 | qlock(a); if(--a->opens == 0){ /* take board out of download mode and enable IRQ */ | |
| 1994/1113 | outb(a->port+ISActl1, ISAien|isairqcode[a->irq]); | |
| 1994/1112 | /* enable ISA access to first 16k */ | |
| 1994/1113 | outb(a->port+ISActl2, ISAmen|0); | |
| 1994/1112 | /* wait for program ready */ for(i = 0; i < 21; i++){ | |
| 1994/1113 | if(inb(a->port+ISActl1) & ISApr) | |
| 1994/1112 | break; tsleep(&r, return0, 0, 500); } | |
| 1994/1113 | if((inb(a->port+ISActl1) & ISApr) == 0) | |
| 1994/1112 | print("astar%d program not ready\n", a->id); } qunlock(a); | |
| 1994/1112/sys/src/9/pc/devastar.c:498,510 – 1994/1113/sys/src/9/pc/devastar.c:536,595 | ||
| 1994/1112 | } | |
| 1994/1111 | } | |
| 1994/1113 | static long memread(Astar *a, uchar *to, long n, ulong offset) { uchar *from, *e; int i, rem; if(offset+n > a->memsize){ if(offset >= a->memsize) return 0; n = a->memsize - offset; } if(waserror()){ qunlock(a); nexterror(); } qlock(a); for(rem = n; rem > 0; rem -= i){ /* map in right piece of memory */ setpage(a, offset); i = offset&Pagemask; to = a->addr + i; i = Pagesize - i; if(i > rem) i = rem; /* byte at a time so endian doesn't matter */ for(e = from + i; from < e;) *to++ = *from++; } qunlock(a); poperror(); return n; } static long bctlread(Chan *c, void *buf, long n, ulong offset) { char s[128]; 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); } | |
| 1994/1111 | long astarread(Chan *c, void *buf, long n, ulong offset) { | |
| 1994/1112 |
| |
| 1994/1111 |
| |
| 1994/1112 |
| |
| 1994/1111 | if(c->qid.path & CHDIR) return devdirread(c, buf, n, 0, 0, astargen); | |
| 1994/1112/sys/src/9/pc/devastar.c:511,644 – 1994/1113/sys/src/9/pc/devastar.c:596,897 | ||
| 1994/1111 | switch(TYPE(c->qid.path)){ case Qmem: | |
| 1994/1112 |
| |
| 1994/1113 | return memread(astar[BOARD(c->qid.path)], buf, n, offset); case Qbctl: return bctlread(astar[BOARD(c->qid.path)], buf, n, offset); } | |
| 1994/1112 |
| |
| 1994/1113 | return 0; } | |
| 1994/1112 |
| |
| 1994/1113 | static long memwrite(Astar *a, uchar *from, long n, ulong offset) { uchar *to, *e; int i, rem; if(offset+n > a->memsize){ if(offset >= a->memsize) return 0; n = a->memsize - offset; } if(waserror()){ qunlock(a); nexterror(); } qlock(a); for(rem = n; rem > 0; rem -= i){ /* map in right piece of memory */ setpage(a, offset); i = offset&Pagemask; from = a->addr + i; i = Pagesize - i; if(i > rem) i = rem; /* byte at a time so endian doesn't matter */ for(e = from + i; from < e;) *to++ = *from++; } qunlock(a); poperror(); return n; } /* * setup a channel */ static void chansetup(Astar *a, Astarchan *ac, void *ccb) { ac->a = a; ac->ccb = ccb; ac->iq = qopen(4*1024, 0, 0, 0); ac->oq = qopen(4*1024, 0, astarkick, p); } /* * start control progarm */ static void startcp(Astar *a) { int n, i, sz; uchar *x; CCB *ccb; if(a->running) error(Eio); /* take board out of download mode and enable IRQ */ outb(a->port+ISActl1, ISAien|isairqcode[a->irq]|ISAnotdl); a->memsize = a->ramsize; /* 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("astar%d program not ready\n", a->id); error(Eio); } setpage(a, 0); i = LEUS(a->gcb->type); switch(i){ default: print("astar%d wrong board type %ux\n", a->id, i); error(Eio); case 0xc: break; } /* check assumptions */ n = LEUS(a->gcb->ccbn); if(n != 8 && n != 16){ print("astar%d had %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("astar%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("astar%d chan buffer spans pages\n", a->id); error(Eio); | |
| 1994/1112 | } | |
| 1994/1113 | } /* setup the channels */ a->running = 1; a->nchan = i; a->c = xalloc(a->nchan * sizeof(Astarchan)); for(i = 0; i < a->nchan; i++){ chansetup(a, &a->c[i], (CCB*)x); x += sz; } } static long bctlwrite(Astar *a, char *msg) { int i; uchar c; if(waserror()){ | |
| 1994/1112 | qunlock(a); | |
| 1994/1113 | nexterror(); } qlock(a); if(strncmp(cmsg, "download", 8) == 0){ if(a->running) error(Eio); /* put board in download mode */ c = inb(a->port+ISActl1); outb(a->port+ISActl1, c & ~ISAnotdl); a->memsize = Pramsize; /* enable ISA access to first 16k */ outb(a->port+ISActl2, ISAmen); } else if(strncmp(cmsg, "run", 3) == 0){ if(a->running) error(Eio); startcp(a); } else error(Ebadarg); qunlock(a); poperror(); return n; } /* * change channel parameters */ void astarctl(Astarchan *ac, char *cmd) { int i, n; int command; /* let output drain for a while */ for(i = 0; i < 16 && qlen(ac->oq); i++) tsleep(&ac->r, qlen, ac->oq, 125); if(strncmp(cmd, "break", 5) == 0) cmd = "k"; command = 0; n = atoi(cmd+1); switch(*cmd){ case 'B': case 'b': switch(n){ case 76800: ac->ccb->baud = LEUS(Cb76800); break; case 115200: ac->ccb->baud = LEUS(Cb115200); break; default: ac->ccb->baud = LEUS(n); break; } command = Cconfall; | |
| 1994/1112 | break; | |
| 1994/1113 | case 'D': case 'd': | |
| 1994/1112 | break; | |
| 1994/1113 | case 'f': case 'F': qflush(ac->oq); break; case 'H': case 'h': qhangup(ac->iq); qhangup(ac->oq); break; case 'L': case 'l': n -= 5; if(n < 0 || n > 3) error(Ebadarg); n |= LEUS(ac->ccb->format) & ~Clenmask; ac->ccb->format = LEUS(n); command = Cconfall; break; case 'm': case 'M': n = LEUS(ac->ccb->format) | Cobeycts; ac->ccb->proto = LEUS(n); command = Cconfall; break; case 'n': case 'N': qnoblock(p->oq, n); break; case 'P': case 'p': switch(*(cmd+1)){ case 'e': n = Cevenpar; break; case 'o': n = Coddpar; break; default: n = Cnopar; break; } n |= LEUS(ac->ccb->format) & ~Cparmask; ac->ccb->format = LEUS(n); command = Cconfall; break; case 'K': case 'k': break; case 'R': case 'r': break; case 'Q': case 'q': qsetlimit(ac->iq, n); qsetlimit(ac->oq, n); break; case 'X': case 'x': n = LEUS(ac->ccb->format) | Cobeyxon; ac->ccb->proto = LEUS(n); command = Cconfall; break; | |
| 1994/1111 | } | |
| 1994/1113 | ||
| 1994/1111 | long astarwrite(Chan *c, void *buf, long n, ulong offset) { | |
| 1994/1112 | Astar *a; | |
| 1994/1113 | Astarchan *ac; | |
| 1994/1112 | char cmsg[32]; | |
| 1994/1111 | if(c->qid.path & CHDIR) error(Eperm); | |
| 1994/1113 | a = astar[BOARD(c->qid.path)]; | |
| 1994/1111 | switch(TYPE(c->qid.path)){ case Qmem: | |
| 1994/1112 |
| |
| 1994/1113 | return memwrite(a, buf, n, offset); | |
| 1994/1112 | case Qbctl: if(n > sizeof cmsg) n = sizeof(cmsg) - 1; memmove(cmsg, buf, n); cmsg[n] = 0; | |
| 1994/1113 | return bctlwrite(a, cmsg); case Qdata: ac = a->c + CHAN(c->qid.path); return qwrite(ac->oq, buf, n); case Qctl: if(n > sizeof cmsg) n = sizeof(cmsg) - 1; memmove(cmsg, buf, n); cmsg[n] = 0; return astarctl(a, msg); | |
| 1994/1111 | } | |
| 1994/1109 | return 0; | |
| 1994/1112/sys/src/9/pc/devastar.c:664,666 – 1994/1113/sys/src/9/pc/devastar.c:917,920 | ||
| 1994/1112 | USED(c, dp); error(Eperm); | |
| 1994/1106 | } | |
| 1994/1113 | ||