| plan 9 kernel history: overview | file list | diff list |
1998/0109/pc/devastar.c (diff list | history)
| 1997/0919/sys/src/9/pc/devastar.c:13,19 – 1998/0109/sys/src/9/pc/devastar.c:13,19 (short | long | prev | next) | ||
| 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. | |
| 1998/0109 | * However, xchgw() is in assembler and will have to be translated. | |
| 1994/1106 | */ | |
| 1994/1113 | #define LENDIAN 1 | |
| 1997/0919/sys/src/9/pc/devastar.c:49,59 – 1998/0109/sys/src/9/pc/devastar.c:49,70 | ||
| 1994/1106 | ISAstat1= 4, /* board status (1 bit per channel) */ ISAstat2= 5, /* board status (1 bit per channel) */ | |
| 1994/1107 | ||
| 1994/1112 |
| |
| 1994/1113 | Pageshift= 14, /* footprint of card mem in ISA space */ Pagesize= 1<<Pageshift, Pagemask= Pagesize-1, | |
| 1998/0109 | PCIrange= 0x00, PCIremap= 0x04, PCIregion= 0x18, PCImailbox= 0x40, PCIdoorbell0= 0x60, PCIdoorbell1= 0x64, PCIcontrol= 0x68, /* write */ PCIstatus= 0x68, /* read */ PCIcommand= 0x6C, Maxcard= 8, Pramsize= 64*1024, /* size of program ram */ | |
| 1994/1106 | }; | |
| 1994/1113 | #define APAGE(x) ((x)>>Pageshift) | |
| 1997/0919/sys/src/9/pc/devastar.c:239,244 – 1998/0109/sys/src/9/pc/devastar.c:250,256 | ||
| 1994/1114 | Rendez r; /* waiting for command completion */ | |
| 1994/1112 | ||
| 1994/1107 | ISAConf; | |
| 1998/0109 | Pcidev* pci; | |
| 1994/1114 | Lock pagelock; /* lock for setting page */ int page; /* page currently mapped */ | |
| 1994/1107 | int id; /* from plan9.ini */ | |
| 1997/0919/sys/src/9/pc/devastar.c:247,252 – 1998/0109/sys/src/9/pc/devastar.c:259,265 | ||
| 1994/1107 | int ramsize; /* 16k or 256k */ | |
| 1994/1113 | int memsize; /* size of memory currently mapped */ | |
| 1994/1116 | int needpage; | |
| 1998/0109 | int pagebase; /* pci */ | |
| 1994/1115 | GCB *gcb; /* global board comm area */ | |
| 1994/1113 | uchar *addr; /* base of memory area */ int running; | |
| 1997/0919/sys/src/9/pc/devastar.c:304,309 – 1998/0109/sys/src/9/pc/devastar.c:317,327 | ||
| 1994/1113 | { | |
| 1994/1121 | int i; | |
| 1994/1113 | ||
| 1998/0109 | if(a->pci){ print("#G%d: setpage caller pc %uX\n", a->id, getcallerpc(a)); return; } | |
| 1994/1113 | i = APAGE(offset); if(i == a->page) return; | |
| 1997/0919/sys/src/9/pc/devastar.c:389,397 – 1998/0109/sys/src/9/pc/devastar.c:407,417 | ||
| 1997/0327 | static void | |
| 1994/1107 | astarreset(void) | |
| 1994/1106 | { | |
| 1994/1121 |
| |
| 1998/0109 | int i, x; | |
| 1994/1107 | Astar *a; | |
| 1998/0109 | Pcidev *p; | |
| 1994/1106 | ||
| 1998/0109 | p = nil; | |
| 1994/1106 | for(i = 0; i < Maxcard; i++){ | |
| 1994/1109 | a = astar[nastar] = xalloc(sizeof(Astar)); | |
| 1994/1112 | if(isaconfig("serial", i, a) == 0){ | |
| 1997/0919/sys/src/9/pc/devastar.c:400,438 – 1998/0109/sys/src/9/pc/devastar.c:420,503 | ||
| 1994/1118 | continue; | |
| 1994/1106 | } | |
| 1998/0109 | a->ramsize = 0; | |
| 1994/1120 | /* check all possible names */ | |
| 1994/1107 |
| |
| 1998/0109 | if(cistrcmp(a->type, "a100i") == 0 || cistrcmp(a->type,"A100I") == 0) | |
| 1994/1107 | a->ramsize = 16*1024; | |
| 1997/0917 |
| |
| 1998/0109 | else if(cistrcmp(a->type, "a200i") == 0 || cistrcmp(a->type,"A200I") == 0 || cistrcmp(a->type, "a16i") == 0) | |
| 1994/1107 | a->ramsize = 256*1024; | |
| 1994/1118 |
| |
| 1998/0109 | else if(cistrcmp(a->type, "AvanstarXp") == 0){ if(p = pcimatch(p, 0x114F, 0x6001)){ a->pci = p; /* * It's really 128KB, but split into * two 64KB chunks. */ a->ramsize = 64*1024; } } if(a->ramsize == 0){ | |
| 1994/1118 | xfree(a); astar[nastar] = 0; | |
| 1994/1107 | continue; | |
| 1994/1118 | } | |
| 1994/1108 | ||
| 1994/1120 |
| |
| 1994/1107 |
| |
| 1998/0109 | if(a->pci){ a->irq = p->intl; a->port = p->mem[1].bar & ~0x03; a->mem = upamalloc(p->mem[2].bar & ~0x0F, p->mem[2].size, 0); a->addr = (uchar*)a->mem; a->gcb = (GCB*)(a->mem+0x10000); | |
| 1994/1107 | ||
| 1997/0327 |
| |
| 1995/0106 |
| |
| 1994/1210 |
| |
| 1995/0115 |
| |
| 1998/0109 | /* * Toggle the software reset and wait for * the adapter local init status to indicate done. */ outl(a->port+PCIremap, 0xA0000001); x = inl(a->port+PCIcommand); outl(a->port+PCIcommand, 0x40000000|x); microdelay(1); outl(a->port+PCIcommand, x); delay(100); for(x = 0; x < 10000; x++){ if(inl(a->port+PCIcommand) & 0x80000000) break; } if(!(inl(a->port+PCIcommand) & 0x80000000)) print("#G: didn't reset\n", a->id); | |
| 1994/1210 | ||
| 1994/1107 |
| |
| 1994/1109 |
| |
| 1994/1107 |
| |
| 1998/0109 | /* * So the memory can be read before any other * initialisation takes place. */ a->memsize = a->ramsize; | |
| 1994/1107 | } | |
| 1994/1120 |
| |
| 1994/1115 |
| |
| 1994/1121 |
| |
| 1998/0109 | else{ /* defaults */ if(a->irq == 0) a->irq = 15; a->mem = umbmalloc(a->mem, Pagesize, Pagesize); if(a->mem == 0) panic("astarreset: %lux", a->mem); a->mem = PADDR(a->mem); if(astarsetup(a) < 0){ xfree(a); astar[nastar] = 0; continue; } print("\tctl1 %ux ctl2 %ux maddr %ux stat1 %ux stat2 %ux\n", inb(a->port+ISActl1), inb(a->port+ISActl2), inb(a->port+ISAmaddr), inb(a->port+ISAstat1), inb(a->port+ISAstat2)); } print("#G%d: %s port 0x%luX addr 0x%luX irq %d\n", a->id, a->type, a->port, a->addr, a->irq); | |
| 1994/1109 | nastar++; | |
| 1994/1107 | } } | |
| 1997/0919/sys/src/9/pc/devastar.c:475,494 – 1998/0109/sys/src/9/pc/devastar.c:540,559 | ||
| 1994/1107 | else | |
| 1994/1112 | found = astarprobe(a->port); | |
| 1994/1107 | if(!found){ | |
| 1998/0109 | print("#G%d: not found\n", a->id); | |
| 1994/1107 | return -1; } | |
| 1994/1120 | /* check interrupt level */ | |
| 1994/1112 | if(isairqcode[a->irq] == -1){ | |
| 1994/1107 |
| |
| 1998/0109 | print("#G%d: bad irq %d\n", a->id, a->irq); | |
| 1994/1107 | return -1; } | |
| 1994/1111 | ||
| 1994/1120 | /* set ISA memory address */ outb(a->port+ISAmaddr, (a->mem>>12) & 0xfc); | |
| 1998/0109 | a->gcb = KADDR(a->mem); a->addr = KADDR(a->mem); | |
| 1994/1120 | /* disable ISA memory response */ | |
| 1994/1121 | outb(a->port+ISActl2, 0); | |
| 1997/0919/sys/src/9/pc/devastar.c:588,597 – 1998/0109/sys/src/9/pc/devastar.c:653,684 | ||
| 1994/1111 | } | |
| 1994/1114 | /* | |
| 1998/0109 | * read PCI mapped memory */ static long pcimemread(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; } /* | |
| 1994/1114 | * read ISA mapped memory */ | |
| 1994/1113 | static long | |
| 1998/0109 | isamemread(Astar *a, uchar *to, long n, ulong offset) | |
| 1994/1113 | { | |
| 1994/1114 | uchar *from, *e, *tp; | |
| 1994/1113 | int i, rem; | |
| 1997/0919/sys/src/9/pc/devastar.c:640,650 – 1998/0109/sys/src/9/pc/devastar.c:727,749 | ||
| 1994/1113 | { char s[128]; | |
| 1998/0109 | if(a->pci) sprint(s, "range %uX remap %uX region %uX mailbox %uX doorbell0 %uX doorbell1 %uX control %uX command %uX", 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)); | |
| 1994/1113 | return readstr(offset, buf, n, s); } | |
| 1997/0919/sys/src/9/pc/devastar.c:693,699 – 1998/0109/sys/src/9/pc/devastar.c:792,801 | ||
| 1994/1121 | a = astar[BOARD(c->qid.path)]; return statread(a->c + CHAN(c->qid.path), buf, n, offset); | |
| 1994/1111 | case Qmem: | |
| 1994/1113 |
| |
| 1998/0109 | a = astar[BOARD(c->qid.path)]; if(a->pci) return pcimemread(a, buf, n, offset); return isamemread(a, buf, n, offset); | |
| 1994/1113 | case Qbctl: return bctlread(astar[BOARD(c->qid.path)], buf, n, offset); | |
| 1994/1115 | case Qdata: | |
| 1997/0919/sys/src/9/pc/devastar.c:706,715 – 1998/0109/sys/src/9/pc/devastar.c:808,848 | ||
| 1994/1113 | } | |
| 1994/1112 | ||
| 1994/1114 | /* | |
| 1998/0109 | * write PCI mapped memory */ static long pcimemwrite(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; } /* | |
| 1994/1114 | * write ISA mapped memory */ | |
| 1994/1113 | static long | |
| 1998/0109 | isamemwrite(Astar *a, uchar *from, long n, ulong offset) | |
| 1994/1113 | { | |
| 1994/1114 | uchar *to, *e, *tp; | |
| 1994/1113 | int i, rem; | |
| 1997/0919/sys/src/9/pc/devastar.c:759,783 – 1998/0109/sys/src/9/pc/devastar.c:892,926 | ||
| 1996/0808 | int c, i; /* put board in download mode */ | |
| 1998/0109 | if(a->pci){ /* * Don't let the download write over the * i960 data structures. */ a->memsize = 0xD000; a->addr = (uchar*)a->mem; | |
| 1996/0808 | } | |
| 1998/0109 | else{ a->memsize = Pramsize; a->needpage = 1; c = inb(a->port+ISActl1); outb(a->port+ISActl1, c & ~ISAnotdl); | |
| 1996/0808 |
| |
| 1998/0109 | /* 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); } | |
| 1996/0808 | } /* | |
| 1997/0919/sys/src/9/pc/devastar.c:795,820 – 1998/0109/sys/src/9/pc/devastar.c:938,984 | ||
| 1994/1113 | error(Eio); /* take board out of download mode and enable IRQ */ | |
| 1994/1120 |
| |
| 1998/0109 | 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); } } | |
| 1994/1113 | a->memsize = a->ramsize; | |
| 1994/1116 |
| |
| 1998/0109 | if(a->pci || a->memsize <= Pagesize) | |
| 1994/1116 | a->needpage = 0; | |
| 1998/0109 | else{ a->page = -1; setpage(a, 0); | |
| 1994/1116 | a->needpage = 1; | |
| 1994/1121 |
| |
| 1994/1113 |
| |
| 1994/1114 | if(waserror()){ | |
| 1994/1116 | UNLOCKPAGE(a); | |
| 1997/0919/sys/src/9/pc/devastar.c:825,833 – 1998/0109/sys/src/9/pc/devastar.c:989,998 | ||
| 1994/1113 | i = LEUS(a->gcb->type); switch(i){ default: | |
| 1998/0109 | print("#G%d: wrong board type %uX\n", a->id, i); | |
| 1994/1113 | error(Eio); | |
| 1998/0109 | case 0x0C: case 0x12: /* AvanstarXp */ | |
| 1994/1113 | break; } | |
| 1997/0919/sys/src/9/pc/devastar.c:834,846 – 1998/0109/sys/src/9/pc/devastar.c:999,1011 | ||
| 1994/1113 | /* check assumptions */ n = LEUS(a->gcb->ccbn); if(n != 8 && n != 16){ | |
| 1998/0109 | print("#G%d: has %d channels?\n", a->id, i); | |
| 1994/1113 | error(Eio); } x = a->addr + LEUS(a->gcb->ccboff); sz = LEUS(a->gcb->ccbsz); if(x+n*sz > a->addr+Pagesize){ | |
| 1998/0109 | print("#G%d: ccb's not in 1st page\n", a->id); | |
| 1994/1113 | error(Eio); } for(i = 0; i < n; i++){ | |
| 1997/0919/sys/src/9/pc/devastar.c:847,853 – 1998/0109/sys/src/9/pc/devastar.c:1012,1018 | ||
| 1994/1113 | ccb = (CCB*)(x + i*sz); if(APAGE(LEUS(ccb->inbase)) != APAGE(LEUS(ccb->inlim)) || APAGE(LEUS(ccb->outbase)) != APAGE(LEUS(ccb->outlim))){ | |
| 1998/0109 | print("#G%d: chan buffer spans pages\n", a->id); | |
| 1994/1113 | error(Eio); | |
| 1994/1112 | } | |
| 1994/1113 | } | |
| 1997/0919/sys/src/9/pc/devastar.c:871,883 – 1998/0109/sys/src/9/pc/devastar.c:1036,1056 | ||
| 1994/1113 | } | |
| 1994/1121 | /* set up interrupt level, enable interrupts */ | |
| 1998/0109 | if(a->pci){ /* * Which bits in the interrupt control register should be set? */ outl(a->port+PCIcontrol, 0x00031F00); intrenable(VectorPIC + a->irq, astarintr, a, a->pci->tbdf); } else{ c = inb(a->port+ISActl1); c &= ~ISAirq; c |= ISAien|isairqcode[a->irq]; outb(a->port+ISActl1, c); intrenable(VectorPIC + a->irq, astarintr, a, BUSUNKNOWN); } | |
| 1994/1121 | ||
| 1997/0327 |
| |
| 1994/1121 |
| |
| 1997/0919/sys/src/9/pc/devastar.c:887,894 – 1998/0109/sys/src/9/pc/devastar.c:1060,1065 | ||
| 1994/1115 | static void bctlwrite(Astar *a, char *cmsg) | |
| 1994/1113 | { | |
| 1994/1112 | qunlock(a); | |
| 1994/1113 | nexterror(); | |
| 1997/0919/sys/src/9/pc/devastar.c:902,921 – 1998/0109/sys/src/9/pc/devastar.c:1073,1127 | ||
| 1994/1113 | /* put board in download mode */ | |
| 1996/0808 | downloadmode(a); | |
| 1994/1113 | ||
| 1994/1115 |
| |
| 1994/1120 |
| |
| 1994/1115 | ||
| 1994/1113 | } else if(strncmp(cmsg, "run", 3) == 0){ | |
| 1994/1115 | /* start up downloaded program */ | |
| 1994/1113 | startcp(a); | |
| 1998/0109 | } else if(strncmp(cmsg, "test", 4) == 0){ uchar *p; #ifdef notdef p = a->addr; a->page = -1; setpage(a, 16*1024); *p = 'X'; p = a->addr; print("page0: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); setpage(a, 2*16*1024); print("page1: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr; *p = 'Y'; p = a->addr; print("page1: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); setpage(a, 16*1024); p = a->addr; print("page0: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); #else p = a->addr; *p = 'A'; print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr+(16*1024); *p = 'B'; print("16K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr; print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); *p = 'C'; print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr+(64*1024); *p = 'D'; print("64K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr; print(" 0K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); p = a->addr+(16*1024); print("16K: %8.8uX %2.2uX\n", inl(a->port+PCIremap), *p); #endif /* notdef */ | |
| 1994/1113 | } else error(Ebadarg); | |
| 1997/0919/sys/src/9/pc/devastar.c:959,969 – 1998/0109/sys/src/9/pc/devastar.c:1165,1175 | ||
| 1994/1115 | cmd = ccb->cmd; | |
| 1994/1116 | UNLOCKPAGE(ac->a); | |
| 1994/1115 | if(cmd){ | |
| 1994/1114 |
| |
| 1998/0109 | print("#G%d: cmd didn't terminate\n", ac->a->id); | |
| 1994/1114 | error(Eio); } | |
| 1994/1115 | if(status){ | |
| 1998/0109 | print("#G%d: cmd status %ux\n", ac->a->id, status); | |
| 1994/1114 | error(Eio); } } | |
| 1997/0919/sys/src/9/pc/devastar.c:1188,1194 – 1998/0109/sys/src/9/pc/devastar.c:1394,1402 | ||
| 1994/1113 | a = astar[BOARD(c->qid.path)]; | |
| 1994/1111 | switch(TYPE(c->qid.path)){ case Qmem: | |
| 1994/1113 |
| |
| 1998/0109 | if(a->pci) return pcimemwrite(a, buf, n, offset); return isamemwrite(a, buf, n, offset); | |
| 1994/1112 | case Qbctl: if(n > sizeof cmsg) n = sizeof(cmsg) - 1; | |
| 1997/0919/sys/src/9/pc/devastar.c:1376,1386 – 1998/0109/sys/src/9/pc/devastar.c:1584,1595 | ||
| 1994/1114 | Astar *a = arg; Astarchan *ac; | |
| 1997/0917 | ulong globvec, vec, invec, outvec, errvec, mvec, cmdvec; | |
| 1994/1121 |
| |
| 1998/0109 | int c, status; | |
| 1994/1114 | ||
| 1998/0109 | ||
| 1994/1114 | USED(ur); | |
| 1994/1121 | if(a->running == 0) | |
| 1998/0109 | panic("#G%d: interrupt but cp not running\n", a->id); | |
| 1994/1121 | ||
| 1994/1114 | lock(&a->pagelock); | |
| 1994/1116 | if(a->needpage) | |
| 1997/0919/sys/src/9/pc/devastar.c:1397,1402 – 1998/0109/sys/src/9/pc/devastar.c:1606,1621 | ||
| 1994/1115 | USED(mvec); | |
| 1994/1114 | /* reenable interrupts */ | |
| 1998/0109 | 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); } | |
| 1994/1115 | a->gcb->cmd2 = LEUS(Gintack); | |
| 1994/1114 | /* service interrupts */ | |