#!/bin/rc # # command: /bin/boddle /n/juke/plan_9/sys/src/9/pc /sys/lib/pcdist/src/9/pc # srcdir: /n/juke/plan_9/sys/src/9/pc # version: 816407398 # date: Tue Nov 14 22:49:58 EST 1995 # myname=$0 doextract=no fn usage{ echo $myname: usage: $myname '[-X] [src-directory]' >[1=2] exit usage } fn sigint{ rm -rf 816407398 exit interrupt } while(~ $1 -*){ switch($1){ case -X doextract=yes case -* usage } shift } switch($#*){ case 0 srcdir=/sys/src/9/pc case 1 srcdir=$1 case * usage } if(! ~ $doextract yes){ echo This shell file contains a bundle of diffs representing changes echo to original source files in the Plan 9 distribution. It will run echo against the files in echo ' ' $srcdir echo '(unless overridden by the optional source directory argument)' echo and create a directory 816407398 containing the updated files. echo It will NOT automatically update the original files. echo echo Invoke with argument -X to perform the actual extraction. exit 0 } rm -rf 816407398 mkdir 816407398 target=816407398/adaptec.c echo -n '816407398/adaptec.c: ' if(! test -f $srcdir/adaptec.c || ! test -r $srcdir/adaptec.c){ echo $srcdir/adaptec.c unreadable exit unreadable } sum=`{sum < $srcdir/adaptec.c} if(! ~ 83c1b40114270 $sum(1)^$sum(2)){ echo $srcdir/adaptec.c is not the original distribution file exit original } cp $srcdir/adaptec.c 816407398/adaptec.c ed 816407398/adaptec.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM adaptec.c' 521,527c if(issuepollcmd(ctlr) == 0){ . 510a * If the BIOS is enabled on the 1542C/CF and BIOS options for support of drives * > 1Gb, dynamic scanning of the SCSI bus or more than 2 drives under DOS 5.0 are * enabled, the BIOS disables accepting Cmbinit to protect against running with * drivers which don't support those options. In order to unlock the interface * it is necessary to read a lock-code using Cextbios and write it back using * Cmbienable; the lock-code is non-zero. */ ctlr->cmd[0] = Cinquiry; ctlr->cmdlen = 1; ctlr->datalen = 4; issuepollcmd(ctlr); if(ctlr->data[0] > 0x43){ ctlr->cmd[0] = Cextbios; ctlr->cmdlen = 1; ctlr->datalen = 2; issuepollcmd(ctlr); /* * Lock-code returned in data[1]. If it's non-zero write it back * along with bit 0 of byte 0 cleared to enable mailbox initialisation. */ if(ctlr->data[1]){ ctlr->cmd[0] = Cmbienable; ctlr->cmd[1] = 0; ctlr->cmd[2] = ctlr->data[1]; ctlr->cmdlen = 3; ctlr->datalen = 0; issuepollcmd(ctlr); } } /* . 484d 477a static int issuepollcmd(Ctlr *ctlr) { ulong s; uchar rif, rs; s = splhi(); issue(ctlr); while(((rif = inb(ctlr->port+Rif)) & Hacc) == 0) ; rs = inb(ctlr->port+Rs); outb(ctlr->port+Rc, Irst); if((rif & Hacc) && (rs & Invdcmd)){ splx(s); print("adaptec%d: invdcmd #%2.2ux, len %d\n", 0, ctlr->cmd[0], ctlr->cmdlen); return 0; } splx(s); return 1; } . 76a Cextbios = 0x28, /* return extended BIOS information */ Cmbienable = 0x29, /* set mailbox interface enable */ . wq //GO.SYSIN DD VADIM adaptec.c sum=`{sum < 816407398/adaptec.c} if(~ 0c17c09015603 $sum(1)^$sum(2)) echo if not{ echo 816407398/adaptec.c checksum error creating updated file exit checksum } target=816407398/bbmalloc.c echo -n '816407398/bbmalloc.c: ' if(! test -f $srcdir/bbmalloc.c || ! test -r $srcdir/bbmalloc.c){ echo $srcdir/bbmalloc.c unreadable exit unreadable } sum=`{sum < $srcdir/bbmalloc.c} if(! ~ 738636e41366 $sum(1)^$sum(2)){ echo $srcdir/bbmalloc.c is not the original distribution file exit original } cp $srcdir/bbmalloc.c 816407398/bbmalloc.c ed 816407398/bbmalloc.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM bbmalloc.c' 89a if(!onstack) bbfree(memstart, len); . 88d 82c return u!=0; . wq //GO.SYSIN DD VADIM bbmalloc.c sum=`{sum < 816407398/bbmalloc.c} if(~ 6d7538971387 $sum(1)^$sum(2)) echo if not{ echo 816407398/bbmalloc.c checksum error creating updated file exit checksum } target=816407398/dat.h echo -n '816407398/dat.h: ' if(! test -f $srcdir/dat.h || ! test -r $srcdir/dat.h){ echo $srcdir/dat.h unreadable exit unreadable } sum=`{sum < $srcdir/dat.h} if(! ~ 7e2e1d678666 $sum(1)^$sum(2)){ echo $srcdir/dat.h is not the original distribution file exit original } cp $srcdir/dat.h 816407398/dat.h ed 816407398/dat.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM dat.h' 391a Cmdexec= 1<<6, /* status 1 byte */ Overrun= 0x10, . 266a int nopt; char opt[NISAOPT][ISAOPTLEN]; . 257a /* * a parsed plan9.ini line */ #define ISAOPTLEN 16 #define NISAOPT 8 . 11a typedef struct PCIcfg PCIcfg; . wq //GO.SYSIN DD VADIM dat.h sum=`{sum < 816407398/dat.h} if(~ adde50898869 $sum(1)^$sum(2)) echo if not{ echo 816407398/dat.h checksum error creating updated file exit checksum } target=816407398/devata.c echo -n '816407398/devata.c: ' if(! test -f $srcdir/devata.c || ! test -r $srcdir/devata.c){ echo $srcdir/devata.c unreadable exit unreadable } sum=`{sum < $srcdir/devata.c} if(! ~ 8ac981f022873 $sum(1)^$sum(2)){ echo $srcdir/devata.c is not the original distribution file exit original } cp $srcdir/devata.c 816407398/devata.c ed 816407398/devata.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devata.c' 1185a } } static int isatapi(Drive *dp) { Controller *cp; cp = dp->cp; outb(cp->pbase+Pdh, dp->dh); DPRINT("%s: isatapi %d\n", dp->vol, dp->atapi); if(dp->atapi){ outb(cp->pbase+Pcmd, 0x08); delay(20); } dp->atapi = 0; dp->bytes = 512; microdelay(1); if(inb(cp->pbase+Pstatus)){ DPRINT("%s: isatapi status %ux\n", dp->vol, inb(cp->pbase+Pstatus)); return 0; } if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14){ DPRINT("%s: isatapi cyl %ux %ux\n", dp->vol, inb(cp->pbase+Pcylmsb), inb(cp->pbase+Pcyllsb)); return 0; } dp->atapi = 1; sprint(dp->vol, "atapi%d", dp->driveno); dp->spindown = 0; spindownmask &= ~(1<driveno); return 1; } static void atapiexec(Drive *dp) { Controller *cp; int loop; cp = dp->cp; if(cmdreadywait(dp)){ error(Eio); } ILOCK(&cp->reglock); cp->nsecs = 1; cp->sofar = 0; cp->error = 0; cp->cmd = Cpktcmd; outb(cp->pbase+Pcount, 0); outb(cp->pbase+Psector, 0); outb(cp->pbase+Pfeature, 0); outb(cp->pbase+Pcyllsb, cp->len); outb(cp->pbase+Pcylmsb, cp->len>>8); outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, cp->cmd); if(dp->drqintr == 0){ microdelay(1); for(loop = 0; (inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0; loop++){ if(loop < 10000) continue; panic("%s: cmddrqwait: cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); } outss(cp->pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); } IUNLOCK(&cp->reglock); loop = 0; while(waserror()){ DPRINT("%s: interrupted atapiexec\n", dp->vol); if(loop++ > 10){ print("%s: disk error\n", dp->vol); nexterror(); } } atasleep(cp); poperror(); if(loop) nexterror(); if(cp->status & Serr){ DPRINT("%s: Bad packet command %ux\n", dp->vol, cp->error); error(Eio); } } static long atapiio(Drive *dp, char *a, ulong len, ulong offset) { ulong bn, n, o, m; Controller *cp; uchar *buf; int retrycount; cp = dp->cp; buf = smalloc(Maxxfer); qlock(cp->ctlrlock); retrycount = 1; retry: if(waserror()){ dp->partok = 0; if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ dp->vers++; if(retrycount){ retrycount--; goto retry; } } cp->dp = 0; free(buf); qunlock(cp->ctlrlock); nexterror(); } cp->buf = buf; cp->dp = dp; cp->len = dp->bytes; n = len; while(n > 0){ bn = offset / dp->bytes; if(offset > dp->cap-dp->bytes) break; o = offset % dp->bytes; m = dp->bytes - o; if(m > n) m = n; memset(cp->cmdblk, 0, 12); cp->cmdblk[0] = Cread2; cp->cmdblk[2] = bn >> 24; cp->cmdblk[3] = bn >> 16; cp->cmdblk[4] = bn >> 8; cp->cmdblk[5] = bn; cp->cmdblk[7] = 0; cp->cmdblk[8] = 1; atapiexec(dp); if(cp->count != dp->bytes){ print("short read\n"); break; } memmove(a, cp->buf + o, m); n -= m; offset += m; a += m; } poperror(); free(buf); cp->dp = 0; qunlock(cp->ctlrlock); return len-n; } static long atapirwio(Chan *c, char *a, ulong len, ulong offset) { Drive *dp; ulong vers; long rv; dp = atadrive[DRIVE(c->qid.path)]; qlock(dp); if(waserror()){ qunlock(dp); nexterror(); } vers = c->qid.vers; c->qid.vers = dp->vers; if(vers && vers != dp->vers) error(Eio); rv = atapiio(dp, a, len, offset); poperror(); qunlock(dp); return rv; } static void atapipart(Drive *dp) { Controller *cp; uchar *buf, err; Partition *pp; int retrycount; cp = dp->cp; pp = &dp->p[0]; strcpy(pp->name, "disk"); pp->start = 0; pp->end = 0; dp->npart = 1; buf = smalloc(Maxxfer); qlock(cp->ctlrlock); retrycount = 1; retry: if(waserror()){ if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ dp->vers++; if(retrycount){ retrycount--; goto retry; } } cp->dp = 0; free(buf); if((cp->status & Serr) && (cp->error & 0xF0) == 0x20) err = cp->error; else err = 0; qunlock(cp->ctlrlock); if(err == 0x20) return; nexterror(); } cp->buf = buf; cp->dp = dp; cp->len = 8; cp->count = 0; memset(cp->cmdblk, 0, sizeof(cp->cmdblk)); cp->cmdblk[0] = Ccapacity; atapiexec(dp); if(cp->count != 8){ print("cmd=%2.2uX, lastcmd=%2.2uX ", cp->cmd, cp->lastcmd); print("cdsize count %d, status 0x%2.2uX, error 0x%2.2uX\n", cp->count, cp->status, cp->error); error(Eio); } dp->lbasecs = (cp->buf[0]<<24)|(cp->buf[1]<<16)|(cp->buf[2]<<8)|cp->buf[3]; dp->cap = dp->lbasecs*dp->bytes; cp->dp = 0; free(cp->buf); poperror(); qunlock(cp->ctlrlock); pp->end = dp->cap / dp->bytes; dp->partok = 1; } static void atapiintr(Controller *cp) { uchar cause; int count, loop, pbase; uchar *addr; pbase = cp->pbase; cause = inb(pbase+Pcount) & 0x03; DPRINT("%s: atapiintr %uX\n", cp->dp->vol, cause); switch(cause){ case 0: /* data out */ cp->status |= Serr; /*FALLTHROUGH*/ case 1: /* command */ if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(pbase+Perror); wakeup(&cp->r); break; } outss(pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); break; case 2: /* data in */ addr = cp->buf; if(addr == 0){ cp->lastcmd = cp->cmd; cp->cmd = 0; if(cp->status & Serr) cp->error = inb(pbase+Perror); wakeup(&cp->r); break; } loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ if(++loop > Maxloop){ cp->status |= Serr; break; } cp->status = inb(pbase+Pstatus); } if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(pbase+Perror); print("%s: Cpktcmd status=%uX, error=%uX\n", cp->dp->vol, cp->status, cp->error); wakeup(&cp->r); break; } count = inb(pbase+Pcyllsb)|(inb(pbase+Pcylmsb)<<8); if (count > Maxxfer) count = Maxxfer; inss(pbase+Pdata, addr, count/2); cp->count = count; cp->lastcmd = cp->cmd; break; case 3: /* status */ cp->lastcmd = cp->cmd; cp->cmd = 0; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; . 1183c IUNLOCK(&cp->reglock); . 1181c outb(cp->pbase+Pdh, dp->dh); . 1177,1178c if((dp->state == Sspinning) && (diff >= dp->spindown)){ DPRINT("%s: spindown\n", dp->vol); ILOCK(&cp->reglock); . 1172,1173c for(driveno = 0; driveno < NDrive && mask; driveno++){ mask &= ~(1<reglock); . 1153,1154c if(cp->cmd == 0 && cp->lastcmd == Cpktcmd && cp->cmdblk[0] == Ccapacity) break; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); print("%s: weird interrupt, cmd=%.2ux, lastcmd=%.2ux, ", dp->vol, cp->cmd, cp->lastcmd); print("status=%.2ux, error=%.2ux, count=%.2ux\n", cp->ctlrno, cp->error, inb(cp->pbase+Pcount)); . 1151a case Cpktcmd: atapiintr(cp); break; . 1143d 1139,1141c case Cfeature: . 1135a else if(cp->cmd == Cident && (cp->status & Sready) == 0) cp->cmd = Cident2; else cp->cmd = 0; inb(cp->pbase+Pstatus); DPRINT("status %uX, alt %uX\n", inb(cp->pbase+Pstatus), inb(cp->pbase+0x206)); . 1132,1134c if(cp->cmd == Cidentd) . 1129c print("%s: intr %d %d\n", dp->vol, cp->sofar, cp->nsecs); . 1108,1111c if(++loop > Maxloop){ print("%s: read/ident cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); cp->status |= Serr; break; . 1105a case Cidentd: . 1088,1092c if(++loop > Maxloop) panic("%s: write cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); . 1068,1071c if(++loop > Maxloop){ print("ata%d: cmd=%lux, lastcmd=%lux status=%lux\n", cp->ctlrno, cp->cmd, cp->lastcmd, inb(cp->pbase+Pstatus)); panic("%s: wait busy\n", dp->vol); . 1064,1065d 1057,1062c ILOCK(&cp->reglock); . 1055c cp = arg; if((dp = cp->dp) == 0) return; . 1052,1053c int loop; uchar *addr; . 1048c ataintr(Ureg*, void* arg) . 1041c Maxloop= 1000000, . 1034a dp->partok = 1; . 1031a dp->npart = pp - dp->p; . 1015,1029d 1013a if(getfields(line[i], field, 3, " ") != 3) break; if(pp >= &dp->p[Npart]) break; strncpy(pp->name, field[0], NAMELEN); if(strncmp(pp->name, "repl", NAMELEN) == 0) dp->repl.p = pp; pp->start = strtoul(field[1], 0, 0); pp->end = strtoul(field[2], 0, 0); if(pp->start > pp->end || pp->start >= dp->p[0].end) break; . 1012c if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ . 1007a else{ strcpy((char*)buf, p); n = getfields((char*)buf, line, Npart+1, "\n"); } . 1006c n = getfields((char*)buf, line, Npart+1, "\n"); if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)){ dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); } . 997,1004c sprint(namebuf, "%spartition", dp->vol); if((p = getconf(namebuf)) == 0){ /* * read last sector from disk, null terminate. This used * to be the sector we used for the partition tables. * However, this sector is special on some PC's so we've * started to use the second last sector as the partition * table instead. To avoid reconfiguring all our old systems * we first look to see if there is a valid partition * table in the last sector. If so, we use it. Otherwise * we switch to the second last. */ ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); . 988,995c * Check if the partitions are described in plan9.ini. * If not, read the disc. . 986a . 982a DPRINT("%s: atapart error\n", dp->vol); . 973a pp++; . 961a if(dp->partok) return; . 960c DPRINT("%s: partok %d\n", dp->vol, dp->partok); . 958c uchar *buf; . 955c char *field[3], namebuf[NAMELEN], *p; . 931c n = getfields((char*)buf, line, Nrepl+1, "\n"); . 906c uchar *buf; . 892a DPRINT("%s: probed: %d/%d/%d CHS %d bytes\n", dp->vol, dp->cyl, dp->heads, dp->sectors, dp->cap); if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0) error(Eio); . 875c for(i = 0; i < 64; i++) . 871c for(i = 0; i < 16; i++) . 858c i = dp->lbasecs - 1; . 856a if(dp->atapi) return; . 839c qunlock(cp->ctlrlock); . 835a cp->dp = 0; . 832a } . 831c if(cp->status & Serr){ DPRINT("%s: probe err: status %lux, err %lux\n", dp->vol, cp->status, cp->error); . 827c IUNLOCK(&cp->reglock); . 823c outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head); . 819a cp->buf = buf; . 814c ILOCK(&cp->reglock); . 812c if(cmdreadywait(dp)){ error(Eio); } . 808c qunlock(cp->ctlrlock); . 806a cp->dp = 0; . 805c qlock(cp->ctlrlock); . 800c uchar *buf; . 790c qunlock(cp->ctlrlock); . 785,786c if(cp->cmd){ cp->lastcmd = cp->cmd; cp->cmd = 0; } cp->dp = 0; . 768,782c dp->lbasecs = 0; . 763,765c dp->lbasecs = lbasecs; dp->cap = dp->bytes * dp->lbasecs; DPRINT("%s: LBA: %s %d sectors %d bytes\n", dp->vol, id, dp->lbasecs, dp->cap); . 761c DPRINT("%s: config 0x%uX capabilities 0x%uX\n", dp->vol, ip->config, ip->capabilities); if(dp->atapi){ dp->bytes = 2048; if((ip->config & 0x0060) == 0x0020) dp->drqintr = 1; } if(dp->spindown && (ip->capabilities & (1<<13))) dp->spindown /= 5; /* use default (unformatted) settings */ dp->cyl = ip->cyls; dp->heads = ip->heads; dp->sectors = ip->s2t; DPRINT("%s: %s %d/%d/%d CHS %d bytes\n", dp->vol, id, dp->cyl, dp->heads, dp->sectors, dp->cap); if(ip->cvalid&(1<<0)){ /* use current settings */ dp->cyl = ip->ccyls; dp->heads = ip->cheads; dp->sectors = ip->cs2t; DPRINT("%s: changed to %d cyl %d head %d sec\n", dp->vol, dp->cyl, dp->heads, dp->sectors); } lbasecs = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){ . 743c DPRINT("%s: bad disk ident status\n", dp->vol); if(dp->atapi == 0 && (cp->error & Eabort)){ dp->atapi = 1; if(isatapi(dp)){ cmd = Cidentd; goto retryatapi; } } . 736,738c outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, cmd); IUNLOCK(&cp->reglock); . 733c cp->cmd = cmd; . 730c retryatapi: ILOCK(&cp->reglock); . 728c if(dp->atapi || isatapi(dp)) cmd = Cidentd; else{ cmd = Cident; if(cmdreadywait(dp)){ dp->atapi = 1; if(isatapi(dp) == 0) error(Eio); cmd = Cidentd; } } . 724c cp->dp = 0; free(buf); qunlock(cp->ctlrlock); . 722c qlock(cp->ctlrlock); . 718a ulong lbasecs; uchar cmd; . 716c uchar *buf; . 663c qunlock(cp->ctlrlock); . 661a cp->dp = 0; . 658,660c if(cp->status & Serr) DPRINT("%s: setbuf err: status %lux, err %lux\n", dp->vol, cp->status, cp->error); . 649,654c ILOCK(&cp->reglock); cp->cmd = Cfeature; cp->dp = dp; outb(cp->pbase+Pfeature, arg); outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, Cfeature); IUNLOCK(&cp->reglock); . 647c if(cmdreadywait(dp)){ error(Eio); } . 643c cp->dp = 0; qunlock(cp->ctlrlock); . 641c if(dp->atapi) return; qlock(cp->ctlrlock); . 637c atafeature(Drive *dp, uchar arg) . 627c qunlock(cp->ctlrlock); . 624a cp->dp = 0; . 618,619c DPRINT("%s err: lblk %ld status %lux, err %lux\n", dp->vol, lblk, cp->status, cp->error); . 612a dp->state = Sspinning; . 611d 606c print("%s: disk error\n", dp->vol); . 604c DPRINT("%s: interrupted ataxfer\n", dp->vol); . 592c IUNLOCK(&cp->reglock); . 588c panic("%s: ataxfer", dp->vol); . 585a microdelay(1); . 579c outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head); . 569c ILOCK(&cp->reglock); . 562,567c if(cmdreadywait(dp)){ error(Eio); } . 558c qunlock(cp->ctlrlock); . 556a cp->dp = 0; . 555c qlock(cp->ctlrlock); . 553a DPRINT("%s: ataxfer cyl %d sec %d head %d len %d\n", dp->vol, cyl, sec, head, len); . 516c ataxfer(Drive *dp, Partition *pp, int cmd, long start, long len, uchar *buf) . 505c DPRINT("ata%d: cmd 0x%uX timeout\n", cp->ctlrno, cp->cmd); . 496c DPRINT("%s: found bblk %ld at offset %ld\n", dp->vol, bblk, i); . 484a if(dp->atapi) return 0; if(status & Sready) return 0; } USED(status); DPRINT("%s: cmdreadywait failed %uX\n", dp->vol, status); outb(cp->pbase+Pdh, DHmagic); return 1; . 479,483c /* * Is the current drive the one we wish to use? */ dh = (inb(cp->pbase+Pdh) & DHslave)^(dp->dh & DHslave); status = 0; while(m->ticks < end){ status = inb(cp->pbase+Pstatus); if(status & Sbusy) continue; if(dh){ outb(cp->pbase+Pdh, dp->dh); /* BOTCH - lock */ dh = 0; continue; . 477c end += MS2TK(2000); . 475c end += MS2TK(10); . 473a dp->usetime = m->ticks; end = m->ticks+1; . 469,470c ulong end; uchar dh, status; . 466c static int . 463,464d 393a . 392c dp = atadrive[DRIVE(c->qid.path)]; if(dp->atapi) error(Eperm); . 387c uchar *buf; . 359,361d 352a dp = atadrive[DRIVE(c->qid.path)]; if(dp->atapi){ if(dp->online == 0) error(Eio); if(waserror()){ qunlock(dp); nexterror(); } qlock(dp); if(dp->partok == 0) atapipart(dp); qunlock(dp); poperror(); return atapirwio(c, a, n, offset); } pp = &dp->p[PART(c->qid.path)]; . 348c uchar *buf; . 336d 334c atawstat(Chan*, char*) . 329d 327c ataremove(Chan*) . 320,322c qlock(dp); dp->partok = 0; atapart(dp); qunlock(dp); . 317c qunlock(dp); . 311,312c dp = atadrive[DRIVE(c->qid.path)]; p = &dp->p[PART(c->qid.path)]; . 305c Drive *dp; . 298d 296c atacreate(Chan*, char*, int, ulong) . 264c if(dp->partok == 0){ if(dp->atapi) atapipart(dp); else atapart(dp); } . 258c atafeature(dp, 0xAA); /* read look ahead */ . 251,255d 243c DPRINT("ataattach\n"); for(driveno = 0; driveno < NDrive; driveno++){ if((dp = atadrive[driveno]) == 0) continue; . 240a int driveno; . 225,226c for(i = 0; i < isa.nopt; i++){ if(strncmp(isa.opt[i], "spindown", 8) == 0){ if(isa.opt[i][9] != '=') continue; if(isa.opt[i][8] == '0') slave = 0; else if(isa.opt[i][8] == '1') slave = 1; else continue; driveno = ctlrno*2+slave; if(atadrive[driveno] == 0) continue; if((spindown = strtol(&isa.opt[i][10], 0, 0)) == 0) continue; if(spindown < (Hardtimeout+2000)/1000) spindown = (Hardtimeout+2000)/1000; atadrive[driveno]->spindown = spindown; spindownmask |= (1<atapi = 1; } } } . 223c ctlr = atactlr[ctlrno]; if(have640b >= 0 && (ctlrno & 0x01)) ctlr->ctlrlock = &atactlrlock[ctlrno-1]; else ctlr->ctlrlock = &atactlrlock[ctlrno]; ctlr->pbase = port; ctlr->ctlrno = ctlrno; ctlr->lastcmd = 0xFF; setvec(irq, ataintr, ctlr); driveno = ctlrno*2; if((atadrive[driveno] = xalloc(sizeof(Drive))) == 0){ DPRINT("ata%d: can't xalloc drive0\n", ctlrno); return; } drive = atadrive[driveno]; drive->cp = ctlr; drive->driveno = driveno; sprint(drive->vol, "hd%d", drive->driveno); drive->dh = DHmagic; drive->vers = 1; driveno++; if((atadrive[driveno] = xalloc(sizeof(Drive))) == 0){ DPRINT("ata%d: can't xalloc drive1\n", ctlrno); return; } drive = atadrive[driveno]; drive->cp = ctlr; drive->driveno = driveno; sprint(drive->vol, "hd%d", drive->driveno); drive->dh = DHmagic|DHslave; drive->vers = 1; } void atareset(void) { int ctlrno, driveno, i, slave, spindown; ISAConf isa; lock(&ataresetlock); if(ataresetdone){ unlock(&ataresetlock); return; } ataresetdone = 1; unlock(&ataresetlock); cmd640b(); rz1000(); atactlrprobe(0, ATAvec0); for(ctlrno = 0; ctlrno < NCtlr; ctlrno++){ memset(&isa, 0, sizeof(ISAConf)); if(isaconfig("ata", ctlrno, &isa) == 0) continue; if(ctlrno && isa.irq) atactlrprobe(ctlrno, Int0vec+isa.irq); DPRINT("ata%d: ctlr %sfound\n", ctlrno, atactlr[ctlrno] ? "": "not "); if(atactlr[ctlrno] == 0) continue; . 217,221c DPRINT("ata%d: DHmagic ok\n", ctlrno); if((atactlr[ctlrno] = xalloc(sizeof(Controller))) == 0){ DPRINT("ata%d: can't xalloc ctlr\n", ctlrno); return; . 210,215c static void atactlrprobe(int ctlrno, int irq) { Controller *ctlr; Drive *drive; int driveno, port; if(atactlr[ctlrno]) return; port = pbase[ctlrno]; outb(port+Pdh, DHmagic); delay(1); if((inb(port+Pdh) & 0xFF) != DHmagic){ DPRINT("ata%d: DHmagic not ok\n", ctlrno); return; . 203,208c /* * Look for PC-Tech RZ1000 controllers and turn off prefetch. * This is overkill, but cheap. */ pcicfg = malloc(sizeof(PCIcfg)); pcicfg->vid = 0x1042; pcicfg->did = 0; devno = 0; while((devno = pcimatch(0, devno, pcicfg)) != -1){ if(pcicfg->did != 0x1000 && pcicfg->did != 0x1001) continue; pcicfgr(0, devno-1, 0, 0x40, &r40, sizeof(r40)); r40 &= ~0x2000; pcicfgw(0, devno-1, 0, 0x40, &r40, sizeof(r40)); } free(pcicfg); } . 200,201c static void rz1000(void) { PCIcfg* pcicfg; ulong r40; int devno; . 196,198c /* * Look for CMD640B dual PCI controllers. Amongst other * bugs only one of the controllers can be active at a time. * Unfortunately there's no way to tell which pair of * controllers this is, so if one is found then all controller * pairs are synchronised. */ pcicfg = malloc(sizeof(PCIcfg)); pcicfg->vid = 0x1095; pcicfg->did = 0x0640; devno = 0; while((devno = pcimatch(0, devno, pcicfg)) != -1){ have640b = devno-1; /* * If one is found, make sure read-ahead is disabled on all * drives and that the 2nd controller is enabled: * reg 0x51: bit 7 - drive 1 read ahead disable * bit 6 - drive 0 read ahead disable * bit 3 - 2nd controller enable * reg 0x57: bit 3 - drive 1 read ahead disable * bit 2 - drive 0 read ahead disable * Doing byte-writes to PCI configuration space is not in the * spec... */ pcicfgr(0, have640b, 0, 0x50, r50, sizeof(r50)); r50[0x01] |= 0xC8; pcicfgw8(0, have640b, 0, 0x51, &r50[0x01], sizeof(r50[0x01])); r50[0x07] |= 0x0C; pcicfgw8(0, have640b, 0, 0x57, &r50[0x07], sizeof(r50[0x07])); } free(pcicfg); } . 191,194c PCIcfg* pcicfg; uchar r50[12]; int devno; . 188,189c static void cmd640b(void) . 174c if(atadrive[drive] == 0) return 0; dp = atadrive[drive]; . 172c if(drive >= NDrive) . 168d 159c atagen(Chan *c, Dirtab*, long, long s, Dir *dirp) . 157a static int isatapi(Drive*); static long atapirwio(Chan*, char*, ulong, ulong); static void atapipart(Drive*); static void atapiintr(Controller*); . 153c static void atafeature(Drive*, uchar); . 151c static long ataxfer(Drive*, Partition*, int, long, long, uchar*); . 146,148c static Lock ataresetlock; static int ataresetdone; static Controller *atactlr[NCtlr]; static QLock atactlrlock[NCtlr]; static Drive *atadrive[NDrive]; static int spindownmask; static int have640b = -1; static int pbase[NCtlr] = { Pbase0, Pbase1, Pbase2, Pbase3, }; . 141,143c Drive* dp; /* drive being accessed */ . 138c uchar cmd; /* current command */ uchar cmdblk[12]; /* ATAPI */ int len; /* ATAPI */ int count; /* ATAPI */ uchar lastcmd; /* debugging info */ uchar status; uchar error; uchar* buf; /* xfer buffer */ . 135,136d 130a uchar ctlrno; . 129d 125c QLock* ctlrlock; /* exclusive access to the controller */ . 116,117c uchar lba; /* true if drive has logical block addressing */ uchar multi; /* true if drive can do multiple block xfers (unused) */ uchar drqintr; /* ATAPI */ ulong vers; /* ATAPI */ int spindown; . 114a ulong lbasecs; . 103a int partok; . 100,102c uchar driveno; uchar dh; /* DHmagic|Am-I-A-Slave */ uchar atapi; uchar online; . 70a . 69c Hardtimeout= 5000, /* disk access timeout (ms) */ NCtlr= 4, NDrive= NCtlr*2, . 66c Npart= 20+2, /* 8 sub partitions, disk, and partition */ . 59,61d 56,57d 52a Cpktcmd= 0xA0, Cidentd= 0xA1, Ccapacity= 0x25, Cread2= 0x28, . 50,51d 48d 44,46c Cident2= 0xFE, /* pseudo command for post Cident interrupt */ Cfeature= 0xEF, . 40c Cfirst= 0xFF, /* pseudo command for initialisation */ . 34a Sdf= (1<<5), . 31a DHmagic= 0xA0, DHslave= 0x10, . 26c Eabort= (1<<2), Pfeature= 1, /* buffer mode port (write) */ . 22,23c Pbase0= 0x1F0, /* primary */ Pbase1= 0x170, /* secondary */ Pbase2= 0x1E8, /* tertiary */ Pbase3= 0x168, /* quaternary */ . 11a #define ILOCK(x) #define IUNLOCK(x) . 0a /* * This has gotten a bit messy with the addition of multiple controller, * and ATAPI support; needs a rewrite before adding any 'ctl' functions. */ . wq //GO.SYSIN DD VADIM devata.c sum=`{sum < 816407398/devata.c} if(~ b87eb7a336203 $sum(1)^$sum(2)) echo if not{ echo 816407398/devata.c checksum error creating updated file exit checksum } target=816407398/devi82365.c echo -n '816407398/devi82365.c: ' if(! test -f $srcdir/devi82365.c || ! test -r $srcdir/devi82365.c){ echo $srcdir/devi82365.c unreadable exit unreadable } sum=`{sum < $srcdir/devi82365.c} if(! ~ ee2c456424234 $sum(1)^$sum(2)){ echo $srcdir/devi82365.c is not the original distribution file exit original } cp $srcdir/devi82365.c 816407398/devi82365.c ed 816407398/devi82365.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devi82365.c' 914c if(ct == et || ct->nioregs == 0) . 912a } } if(ct->nioregs == 0 || ((1<irqs) == 0){ for(t = pp->ctab; t < et; t++) if(t->nioregs && ((1<irqs)){ ct = t; break; } } if(ct->nioregs == 0){ for(t = pp->ctab; t < et; t++) if(t->nioregs){ ct = t; break; } } . 908,911c /* assume default is right */ if(pp->def) ct = pp->def; else ct = pp->ctab; /* try for best match */ if(ct->nioregs == 0 || ct->port != isa->port || ((1<irqs) == 0){ for(t = pp->ctab; t < et; t++) if(t->nioregs && t->port == isa->port && ((1<irqs)){ ct = t; . 902,906c et = &pp->ctab[pp->nctab]; . 887c Conftab *ct, *et, *t; . 541,546c if((c & 0xc0) != 0xc0) break; c = inb(d); if((c & 0xc0) != 0x00) break; if(c & 0x20){ . 251a . 248a . wq //GO.SYSIN DD VADIM devi82365.c sum=`{sum < 816407398/devi82365.c} if(~ cd5d464c24481 $sum(1)^$sum(2)) echo if not{ echo 816407398/devi82365.c checksum error creating updated file exit checksum } target=816407398/devsbcd.c echo -n '816407398/devsbcd.c: ' if(! test -f $srcdir/devsbcd.c || ! test -r $srcdir/devsbcd.c){ echo $srcdir/devsbcd.c unreadable exit unreadable } sum=`{sum < $srcdir/devsbcd.c} if(! ~ 2eb08c3212806 $sum(1)^$sum(2)){ echo $srcdir/devsbcd.c is not the original distribution file exit original } cp $srcdir/devsbcd.c 816407398/devsbcd.c ed 816407398/devsbcd.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devsbcd.c' 723a port = drive->port; . 721c int i, e, port; . 719c mitsbcdio(Drive* drive, ulong adr) . 679a port = drive->port; . 677c int i, e, port; . 675c mitinitdrive(Drive* drive) . 587,588c i = status(drive); errno = reqsense(drive); . 581c errno = reqsense(drive); . 579c sr = status(drive); . 576,577c outb(sport, 0); while((inb(sport)&(DTEN|STEN)) != DTEN) . 574c *p++ = inb(dport); . 572c if(inb(sport) != 0xfd) . 569c outb(sport, 1); . 561c sr = inb(sport) & (STEN|DTEN); . 558c issue(drive, cmd); . 548a dport = drive->dport; sport = drive->port+STATUS; . 546c int dport, sport, sr, i, try, errno; . 544c pansbcdio(Drive* drive, ulong adr) . 525c i = reqsense(drive); . 520c sr = status(drive); . 515,516c issue(drive, cmd); i = poll(10, DTEN, drive, 1); . 502c paninitdrive(Drive* drive) . 450c sbcd.sbcdio(&sbcd, bn); . 377c sbcd.initdrive(&sbcd); . 353,354c insb(drive->port+INFO, data, 6); sr = status(drive); . 350c print("devsbcd: cmd error, sr=%2.2ux\n", status(drive)); . 347,348c issue(drive, cmd); i = poll(10, DTEN, drive, 1); . 342,343d 339c int i, sr, retry; . 337c getcap(Drive* drive) . 330,331c insb(drive->port+INFO, data, 8); status(drive); . 324,325c issue(drive, cmd); i = poll(2000, DTEN, drive, 0); . 317c reqsense(Drive* drive) . 307c sr = inb(sport) & (STEN|DTEN); . 304a sport = drive->port+STATUS; . 303c int i, sr, sport; . 301c poll(int timeo, int state, Drive* drive, int delay) . 277c error("no sb cd-rom configured"); . 270c sbcd.port = sbconf.port; sbcd.dport = sbcd.port; for(i = 0; i < sbconf.nopt; i++){ if(strcmp(sbconf.opt[i], "laser")) continue; sbcd.dport = sbcd.port+2; break; } . 254a else if(strcmp(sbconf.type, "atapi") == 0) return; . 236a int i; . 206,207c drain(drive); i = status(drive); . 202a port = drive->port; . 201c int i, len, port; . 197c issue(Drive* drive, uchar *cmd) . 193c return info; . 190c info = inb(iport); . 186,187c if((info & DTEN|STEN) == STEN) drain(drive); . 184c if(inb(sport) == 0xff) . 182a info = inb(iport); . 181c iport = drive->port+INFO; sport = drive->port+STATUS; . 179c int info, iport, sport; . 177c status(Drive* drive) . 170,173c int sport, dport; sport = drive->port+STATUS; dport = drive->dport; outb(sport, 1); while((inb(sport) & (DTEN|STEN)) == STEN) inb(dport); outb(sport, 0); . 168c drain(Drive* drive) . 162,165c static void pansbcdio(Drive*, ulong); static void mitsbcdio(Drive*, ulong); static void paninitdrive(Drive*); static void mitinitdrive(Drive*); . 147,148c void (*sbcdio)(Drive*, ulong); void (*initdrive)(Drive*); . 144a int dport; . 34c INFO = 0, DATA = 0, /* 0 for real SB, 2 for SB-like cards */ . wq //GO.SYSIN DD VADIM devsbcd.c sum=`{sum < 816407398/devsbcd.c} if(~ c107431113428 $sum(1)^$sum(2)) echo if not{ echo 816407398/devsbcd.c checksum error creating updated file exit checksum } target=816407398/devvga.c echo -n '816407398/devvga.c: ' if(! test -f $srcdir/devvga.c || ! test -r $srcdir/devvga.c){ echo $srcdir/devvga.c unreadable exit unreadable } sum=`{sum < $srcdir/devvga.c} if(! ~ ea7d916f23360 $sum(1)^$sum(2)){ echo $srcdir/devvga.c is not the original distribution file exit original } cp $srcdir/devvga.c 816407398/devvga.c ed 816407398/devvga.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devvga.c' 794a CGASCREEN[pos+1] = 2; . 755c hp += inch - footprint; . 735c edisp = ((uchar*)vgascreen.base) + footprint; . 728,729c page = off>>footshift; off &= (1< (footprint)/(vgascreen.width*BY2WD)) vgamaxy = (footprint)/(vgascreen.width*BY2WD); . 316a /* see if it fits in the usual place */ if(x <= Footprint){ screenmem = SCREENMEM; if(x == 0){ footprint = Footprint; footshift = Footshift; } else { footprint = x; for(n = 0; n < 31; n++) if((1<= footprint) break; footshift = n; } vgascreen.base = (void*)screenmem; vgascreen.r.max.y = (footprint)/(vgascreen.width*BY2WD); return; } /* grab new space */ if(y == 0){ if(footprint >= x) return; } else { int s, e; s = screenmem & ~KZERO; e = s + footprint; s = ROUND(s, y); if(e >= s + x) return; } y = getspace(x, y); if(y == 0) error("not enough free address space"); screenmem = y; vgascreen.base = (void*)y; footprint = x; vgascreen.r.max.y = (footprint)/(vgascreen.width*BY2WD); for(n = 0; n < 31; n++) if((1<= footprint) break; footshift = n; return; } . 315a else if(strcmp(field[0], "linear") == 0){ if(n < 2) error(Ebadarg); x = strtoul(field[1], 0, 0); if(n < 3) y = 0; else y = strtoul(field[2], 0, 0); . 246c n = getfields(arg, field, 3, " \t\n"); if(n < 2) . 241c int n; ulong x, y, z; . 206c port += sprint(cbuf+port, "off\n"); sprint(cbuf+port, "addr: 0x%lux\n", screenmem&~KZERO); . 204c port += sprint(cbuf+port, "%s\n", hwgc->name); . 51,56d 45,49d 13a enum { /* default footprint is 64k */ Footshift= 16, Footprint= 1</dev/null >[2=1] <<'//GO.SYSIN DD VADIM dos' 35a vgact65540 . 34a vgaark2000pv . 31c ether509 pci . wq //GO.SYSIN DD VADIM dos sum=`{sum < 816407398/dos} if(~ e99009c3590 $sum(1)^$sum(2)) echo if not{ echo 816407398/dos checksum error creating updated file exit checksum } target=816407398/ether.h echo -n '816407398/ether.h: ' if(! test -f $srcdir/ether.h || ! test -r $srcdir/ether.h){ echo $srcdir/ether.h unreadable exit unreadable } sum=`{sum < $srcdir/ether.h} if(! ~ 484a37164461 $sum(1)^$sum(2)){ echo $srcdir/ether.h is not the original distribution file exit original } cp $srcdir/ether.h 816407398/ether.h ed 816407398/ether.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether.h' 37a uchar dummyrr; /* do dummy remote read */ . wq //GO.SYSIN DD VADIM ether.h sum=`{sum < 816407398/ether.h} if(~ afcd2b694506 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether.h checksum error creating updated file exit checksum } target=816407398/ether2000.c echo -n '816407398/ether2000.c: ' if(! test -f $srcdir/ether2000.c || ! test -r $srcdir/ether2000.c){ echo $srcdir/ether2000.c unreadable exit unreadable } sum=`{sum < $srcdir/ether2000.c} if(! ~ 8da35f812864 $sum(1)^$sum(2)){ echo $srcdir/ether2000.c is not the original distribution file exit original } cp $srcdir/ether2000.c 816407398/ether2000.c ed 816407398/ether2000.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether2000.c' 73a delay(2); . 66a ctlr->card.dummyrr = 1; for(i = 0; i < ctlr->card.nopt; i++){ if(strcmp(ctlr->card.opt[i], "nodummyrr")) continue; ctlr->card.dummyrr = 0; break; } . 25c Reset = 0x1F, /* offset from I/O base of reset port */ . wq //GO.SYSIN DD VADIM ether2000.c sum=`{sum < 816407398/ether2000.c} if(~ ccd8327d3036 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether2000.c checksum error creating updated file exit checksum } target=816407398/ether509.c echo -n '816407398/ether509.c: ' if(! test -f $srcdir/ether509.c || ! test -r $srcdir/ether509.c){ echo $srcdir/ether509.c unreadable exit unreadable } sum=`{sum < $srcdir/ether509.c} if(! ~ f15af29014924 $sum(1)^$sum(2)){ echo $srcdir/ether509.c is not the original distribution file exit original } cp $srcdir/ether509.c 816407398/ether509.c ed 816407398/ether509.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether509.c' 606c * Commands have the format 'CCCCCAAAAAAAAAAA' where C . 602a case 0x000000: acr = Xcvr10BaseT; break; case 0x300000: acr = XcvrBNC; break; } free(pcicfg); } else acr = ins(port+AddressConfig); . 601c if(pcicfg){ ctlr->card.irq = pcicfg->irq; COMMAND(port, SelectWindow, 3); acr = XcvrAUI; l = inl(port+InternalCgf); switch(l & 0x700000){ . 589c if(strcmp(ctlr->card.type, "3C589") != 0 && pcicfg == 0) . 576a port = tcm589(&ctlr->card); if(port == 0) . 574,575c if(port == 0 && (pcicfg = tcm590(&ctlr->card))) port = pcicfg->baseaddr[0] & ~0x01; . 570c free(ap); . 568a pcicfg = ap->pcicfg; . 565a pcicfg = 0; . 555a PCIcfg *pcicfg; . 554c ulong l, port; . 541,542c if(strcmp(isa->type, "3C589") != 0) return 0; /* * The 3com manual register description says that this a noop for * PCMCIA but the flow chart at the end shows it. */ COMMAND(isa->port, SelectWindow, 0); outs(isa->port+ConfigControl, Ena); return isa->port; . 537a static PCIcfg* tcm590(ISAConf *isa) { PCIcfg* pcicfg; static int devno = 0; int port; Adapter *ap; pcicfg = malloc(sizeof(PCIcfg)); for(;;){ pcicfg->vid = 0x10B7; pcicfg->did = 0; if((devno = pcimatch(0, devno, pcicfg)) == -1) break; port = pcicfg->baseaddr[0] & ~0x01; COMMAND(port, GlobalReset, 0); while(ins(port+Status) & CmdInProgress) ; if(isa->port == 0 || isa->port == port) return pcicfg; ap = malloc(sizeof(Adapter)); ap->pcicfg = pcicfg; ap->port = port; ap->next = adapter; adapter = ap; pcicfg = malloc(sizeof(PCIcfg)); } free(pcicfg); return 0; } . 345,346c Adapter* next; ulong port; PCIcfg* pcicfg; . 320,340d 308,318c if(status & AllIntr) panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ctlr)); . 303,306c * Panic if there are any interrupt bits on we haven't * dealt with. . 291,301c wakeup(&ctlr->tr); status &= ~(TxAvailable|TxComplete); } . 288,289c if(status & TxComplete){ /* * Pop the TX Status stack, accumulating errors. * If there was a Jabber or Underrun error, reset * the transmitter. For all conditions enable * the transmitter. */ txstatus = 0; do{ if(x = inb(port+TxStatus)) outb(port+TxStatus, 0); txstatus |= x; }while(ins(port+Status) & TxComplete); if(txstatus & (TxJabber|TxUnderrun)) COMMAND(port, TxReset, 0); COMMAND(port, TxEnable, 0); ctlr->oerrs++; } if(status & (TxAvailable|TxComplete)){ /* * Reset the Tx FIFO threshold. */ if(status & TxAvailable) COMMAND(port, AckIntr, TxAvailable); . 283,286c if(status & RxComplete){ receive(ctlr); wakeup(&ctlr->rr); status &= ~RxComplete; . 276,281c COMMAND(port, AckIntr, Latch); status = ins(port+Status); if((status & AllIntr) == 0) break; if(status & Failure){ /* * Adapter failure, try to find out why. * Reset if necessary. * What happens if Tx is active and we reset, * need to retransmit? * This probably isn't right. */ diag = getdiag(ctlr); print("ether509: status #%ux, diag #%ux\n", status, diag); if(diag & TxOverrun){ COMMAND(port, TxReset, 0); COMMAND(port, TxEnable, 0); } if(diag & RxUnderrun){ COMMAND(port, RxReset, 0); attach(ctlr); } if(diag & TxOverrun) transmit(ctlr); return; . 270,274c * Clear the interrupt latch. * It's possible to receive a packet and for another * to become complete before we exit the interrupt * handler so this must be done first to ensure another * interrupt will occur. . 268c for(;;){ . 266d 239c outsl(port+Fifo, tb->pkt, (len/4)); . 91a InternalCgf = 0x00, /* window 3 */ . 15a GlobalReset = 0x00, /* Global Reset */ . wq //GO.SYSIN DD VADIM ether509.c sum=`{sum < 816407398/ether509.c} if(~ fdde614816590 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether509.c checksum error creating updated file exit checksum } target=816407398/ether589.c echo -n '816407398/ether589.c: ' if(! test -f $srcdir/ether589.c || ! test -r $srcdir/ether589.c){ echo $srcdir/ether589.c unreadable exit unreadable } sum=`{sum < $srcdir/ether589.c} if(! ~ 6b3cc8191548 $sum(1)^$sum(2)){ echo $srcdir/ether589.c is not the original distribution file exit original } cp $srcdir/ether589.c 816407398/ether589.c ed 816407398/ether589.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether589.c' 58c outs(port + ResourceConfig, 0x3f00 | (x&0xff)); . 54c /* outs(port + AddressConfig, x & 0x20); */ outs(port + AddressConfig, x & 0xf0); . wq //GO.SYSIN DD VADIM ether589.c sum=`{sum < 816407398/ether589.c} if(~ a7490f5e1591 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether589.c checksum error creating updated file exit checksum } target=816407398/ether8003.c echo -n '816407398/ether8003.c: ' if(! test -f $srcdir/ether8003.c || ! test -r $srcdir/ether8003.c){ echo $srcdir/ether8003.c unreadable exit unreadable } sum=`{sum < $srcdir/ether8003.c} if(! ~ 3dc3a5056399 $sum(1)^$sum(2)){ echo $srcdir/ether8003.c is not the original distribution file exit original } cp $srcdir/ether8003.c 816407398/ether8003.c ed 816407398/ether8003.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether8003.c' 222,223c /* if(ctlr->card.bit16) ctlr->card.size <<= 2;*/ } static void reset8216(Ctlr *ctlr, uchar[8]) { uchar hcr, irq, x; ulong addr, wd8003; wd8003 = ctlr->card.port; ctlr->card.bit16 = 1; /* * Switch to the alternate register set and retrieve the memory * and irq information. */ hcr = inb(wd8003+Hcr); outb(wd8003+Hcr, 0x80|hcr); addr = inb(wd8003+0x0B) & 0xFF; irq = inb(wd8003+0x0D); outb(wd8003+Hcr, hcr); ctlr->card.mem = KZERO|(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13)); ctlr->card.size = 8192*(1<<((addr>>4) & 0x03)); ctlr->card.irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)]; /* * Enable interface RAM, set interface width, * and enable interrupts. */ x = inb(wd8003+Msr) & ~Rst; outb(wd8003+Msr, Menb|x); x = inb(wd8003+Laar); outb(wd8003+Laar, M16en|x); outb(wd8003+Ijr, Ienable); } /* * Get configuration parameters, enable memory. * There are opportunities here for buckets of code. * We'll try to resist. */ int wd8003reset(Ctlr *ctlr) { int i; uchar ea[Eaddrlen], ic[8], id, sum; ulong wd8003; /* * Set up the software configuration. * Use defaults for port, irq, mem and size if not specified. * Defaults are set for the dumb 8003E which can't be * autoconfigured. */ if(ctlr->card.port == 0) ctlr->card.port = 0x280; if(ctlr->card.irq == 0) ctlr->card.irq = 3; if(ctlr->card.mem == 0) ctlr->card.mem = 0xD0000; if(ctlr->card.size == 0) ctlr->card.size = 8*1024; ctlr->card.reset = wd8003reset; ctlr->card.attach = dp8390attach; ctlr->card.mode = dp8390mode; ctlr->card.read = read; ctlr->card.write = write; ctlr->card.receive = dp8390receive; ctlr->card.transmit = dp8390transmit; ctlr->card.intr = dp8390intr; ctlr->card.watch = watch; ctlr->card.ram = 1; wd8003 = ctlr->card.port; /* * Look for the interface. We read the LAN address ROM * and validate the checksum - the sum of all 8 bytes * should be 0xFF. * While we're at it, get the (possible) interface chip * registers, we'll use them to check for aliasing later. */ sum = 0; for(i = 0; i < sizeof(ctlr->ea); i++){ ea[i] = inb(wd8003+Lar+i); sum += ea[i]; ic[i] = inb(wd8003+i); } id = inb(wd8003+Id); sum += id; sum += inb(wd8003+Cksum); if(sum != 0xFF) return -1; if((id & 0xFE) == 0x2A) reset8216(ctlr, ic); else reset8003(ctlr, ea, ic); . 189c ctlr->card.irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)]; . 186d 173d 170c if(memcmp(&ea[1], &ic[1], 5) == 0){ . 143,159d 116,141d 112,113d 104,110c static void reset8003(Ctlr *ctlr, uchar ea[Eaddrlen], uchar ic[8]) . 59a static int irq8216[8] = { 0, 9, 3, 5, 7, 10, 11, 15, }; . 56c static int irq8003[8] = { . 52a enum { /* Ijr */ Ienable = 0x01, /* 8216 interrupt enable */ }; . 22a Hcr = 0x04, /* 8216 hardware control */ . 13a * Also handles 8216 cards (Elite Ultra). . wq //GO.SYSIN DD VADIM ether8003.c sum=`{sum < 816407398/ether8003.c} if(~ af22b0577567 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether8003.c checksum error creating updated file exit checksum } target=816407398/ether8390.c echo -n '816407398/ether8390.c: ' if(! test -f $srcdir/ether8390.c || ! test -r $srcdir/ether8390.c){ echo $srcdir/ether8390.c unreadable exit unreadable } sum=`{sum < $srcdir/ether8390.c} if(! ~ 15cc457216852 $sum(1)^$sum(2)){ echo $srcdir/ether8390.c is not the original distribution file exit original } cp $srcdir/ether8390.c 816407398/ether8390.c ed 816407398/ether8390.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ether8390.c' 630c while(isr = (dp8390inb(dp8390+Isr) & (Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe))){ . 398a else{ dp8390outb(dp8390+Rsar0, to & 0xFF); dp8390outb(dp8390+Rsar1, (to>>8) & 0xFF); dp8390outb(dp8390+Rbcr0, len & 0xFF); dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); } . 393,396c if(crda == to){ /* * Start the remote DMA write and make sure * the registers are correct. */ dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); crda = dp8390inb(dp8390+Crda0); crda |= dp8390inb(dp8390+Crda1)<<8; if(crda != to) panic("crda write %d to %d\n", crda, to); break; } . 374,390c if(ctlr->card.dummyrr){ crda = to-1-ctlr->card.bit16; dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); dp8390outb(dp8390+Rsar0, crda & 0xFF); dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); for(;;){ . 372c * the initial set up for read unless told otherwise. . wq //GO.SYSIN DD VADIM ether8390.c sum=`{sum < 816407398/ether8390.c} if(~ 0030f5a817187 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether8390.c checksum error creating updated file exit checksum } target=816407398/fns.h echo -n '816407398/fns.h: ' if(! test -f $srcdir/fns.h || ! test -r $srcdir/fns.h){ echo $srcdir/fns.h unreadable exit unreadable } sum=`{sum < $srcdir/fns.h} if(! ~ b81c0b702762 $sum(1)^$sum(2)){ echo $srcdir/fns.h is not the original distribution file exit original } cp $srcdir/fns.h 816407398/fns.h ed 816407398/fns.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM fns.h' 72a void pcicfgr(int, int, int, int, void*, int); void pcicfgw(int, int, int, int, void*, int); void pcicfgw8(int, int, int, int, void*, int); int pcimatch(int, int, PCIcfg*); . 38a ulong getspace(int, int); . wq //GO.SYSIN DD VADIM fns.h sum=`{sum < 816407398/fns.h} if(~ fed86b842960 $sum(1)^$sum(2)) echo if not{ echo 816407398/fns.h checksum error creating updated file exit checksum } target=816407398/io.h echo -n '816407398/io.h: ' if(! test -f $srcdir/io.h || ! test -r $srcdir/io.h){ echo $srcdir/io.h unreadable exit unreadable } sum=`{sum < $srcdir/io.h} if(! ~ a93968c11482 $sum(1)^$sum(2)){ echo $srcdir/io.h is not the original distribution file exit original } cp $srcdir/io.h 816407398/io.h ed 816407398/io.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM io.h' 29a enum { MaxEISA = 16, EISAconfig = 0xC80, }; /* * PCI Local Bus support. * Quick hack until we figure out how to * deal with EISA, PCI, PCMCIA, PnP, etc. */ enum { /* configuration mechanism #1 */ PCIaddr = 0xCF8, /* CONFIG_ADDRESS */ PCIdata = 0xCFC, /* CONFIG_DATA */ /* configuration mechanism #2 */ PCIcse = 0xCF8, /* configuration space enable */ PCIforward = 0xCFA, /* which bus */ MaxPCI = 32, /* 16 for mechanism #2 */ }; typedef struct PCIcfg { ushort vid; /* vendor ID */ ushort did; /* device ID */ ushort command; ushort status; uchar rid; /* revision ID */ uchar loclass; /* specific register-level programming interface */ uchar subclass; uchar baseclass; uchar clsize; /* cache line size */ uchar latency; /* latency timer */ uchar header; /* header type */ uchar bist; /* built-in self-test */ ulong baseaddr[6]; /* memory or I/O base address registers */ ulong reserved28[2]; ulong romaddr; /* expansion ROM base address */ ulong reserved34[2]; uchar irq; /* interrupt line */ uchar irp; /* interrupt pin */ uchar mingnt; /* burst period length */ uchar maxlat; /* maximum latency between bursts */ } PCIcfg; . wq //GO.SYSIN DD VADIM io.h sum=`{sum < 816407398/io.h} if(~ c775b7f82689 $sum(1)^$sum(2)) echo if not{ echo 816407398/io.h checksum error creating updated file exit checksum } target=816407398/kbd.c echo -n '816407398/kbd.c: ' if(! test -f $srcdir/kbd.c || ! test -r $srcdir/kbd.c){ echo $srcdir/kbd.c unreadable exit unreadable } sum=`{sum < $srcdir/kbd.c} if(! ~ 35efc61811837 $sum(1)^$sum(2)){ echo $srcdir/kbd.c is not the original distribution file exit original } cp $srcdir/kbd.c 816407398/kbd.c ed 816407398/kbd.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM kbd.c' 276c ccc |= Csf | Ckbdint | Cscs1 | Cmousedis; . wq //GO.SYSIN DD VADIM kbd.c sum=`{sum < 816407398/kbd.c} if(~ bc90192211849 $sum(1)^$sum(2)) echo if not{ echo 816407398/kbd.c checksum error creating updated file exit checksum } target=816407398/main.c echo -n '816407398/main.c: ' if(! test -f $srcdir/main.c || ! test -r $srcdir/main.c){ echo $srcdir/main.c unreadable exit unreadable } sum=`{sum < $srcdir/main.c} if(! ~ 3e6d3c5213720 $sum(1)^$sum(2)){ echo $srcdir/main.c is not the original distribution file exit original } cp $srcdir/main.c 816407398/main.c ed 816407398/main.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM main.c' 739a } else if(isa->nopt < NISAOPT){ r = isa->opt[isa->nopt]; while(*p && *p != ' ' && *p != '\t'){ *r++ = *p++; if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1) break; } *r = '\0'; isa->nopt++; . 711a isa->nopt = 0; . 705c char cc[NAMELEN], *p, *q, *r; . 341,343d 339c /* * Strip out '\r', change '\t' -> ' '. */ p = cp; for(q = cp; *q; q++){ if(*q == '\r') continue; if(*q == '\t') *q = ' '; *p++ = *q; } *p = 0; n = getcfields(cp, line, MAXCONF, '\n'); . 329,330c char *cp, *line[MAXCONF], *p, *q; . 322a for(i=0; lp && *lp && i/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mem.h' 46c #define KTZERO 0x80100000 /* first address in kernel text */ . wq //GO.SYSIN DD VADIM mem.h sum=`{sum < 816407398/mem.h} if(~ 24aa9d983642 $sum(1)^$sum(2)) echo if not{ echo 816407398/mem.h checksum error creating updated file exit checksum } target=816407398/mkfile echo -n '816407398/mkfile: ' if(! test -f $srcdir/mkfile || ! test -r $srcdir/mkfile){ echo $srcdir/mkfile unreadable exit unreadable } sum=`{sum < $srcdir/mkfile} if(! ~ 676155eb1229 $sum(1)^$sum(2)){ echo $srcdir/mkfile is not the original distribution file exit original } cp $srcdir/mkfile 816407398/mkfile ed 816407398/mkfile >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mkfile' 47a %/9$CONF: 9$CONF cp 9$CONF $stem/9$CONF; strip $stem/9$CONF . 1,2c CONF=dos CONFLIST=dos pcdisk pc ROOT=/usr/jmk/pcdist . wq //GO.SYSIN DD VADIM mkfile sum=`{sum < 816407398/mkfile} if(~ 1e55f1761297 $sum(1)^$sum(2)) echo if not{ echo 816407398/mkfile checksum error creating updated file exit checksum } target=816407398/mmu.c echo -n '816407398/mmu.c: ' if(! test -f $srcdir/mmu.c || ! test -r $srcdir/mmu.c){ echo $srcdir/mmu.c unreadable exit unreadable } sum=`{sum < $srcdir/mmu.c} if(! ~ 88645e078394 $sum(1)^$sum(2)){ echo $srcdir/mmu.c is not the original distribution file exit original } cp $srcdir/mmu.c 816407398/mmu.c ed 816407398/mmu.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mmu.c' 409a } /* * get non-ISA memory space */ ulong getspace(int len, int span) { ulong x; lock(&msalloc); x = msalloc.s; if(span) x = ROUND(x, span); if(len > msalloc.e - x){ unlock(&msalloc); return 0; } msalloc.s = x + len; unlock(&msalloc); return x | KZERO; . 90a /* * allocatable, non ISA memory */ if(conf.topofmem > 16*1024*1024) msalloc.s = conf.topofmem; else msalloc.s = 16*1024*1024; msalloc.e = 128*1024*1024; . 54a /* unallocated space */ struct { Lock; ulong s; ulong e; } msalloc; . wq //GO.SYSIN DD VADIM mmu.c sum=`{sum < 816407398/mmu.c} if(~ 520ff7088907 $sum(1)^$sum(2)) echo if not{ echo 816407398/mmu.c checksum error creating updated file exit checksum } target=816407398/pc echo -n '816407398/pc: ' if(! test -f $srcdir/pc || ! test -r $srcdir/pc){ echo $srcdir/pc unreadable exit unreadable } sum=`{sum < $srcdir/pc} if(! ~ 810d2257559 $sum(1)^$sum(2)){ echo $srcdir/pc is not the original distribution file exit original } cp $srcdir/pc 816407398/pc ed 816407398/pc >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pc' 38a vgact65540 . 37a ether3210 ether8390 ether4100 ether8390 ether8003 ether8390 vgaark2000pv . 34,36c ether509 pci . wq //GO.SYSIN DD VADIM pc sum=`{sum < 816407398/pc} if(~ de14360f610 $sum(1)^$sum(2)) echo if not{ echo 816407398/pc checksum error creating updated file exit checksum } target=816407398/pcdisk echo -n '816407398/pcdisk: ' if(! test -f $srcdir/pcdisk || ! test -r $srcdir/pcdisk){ echo $srcdir/pcdisk unreadable exit unreadable } sum=`{sum < $srcdir/pcdisk} if(! ~ 787c9350583 $sum(1)^$sum(2)){ echo $srcdir/pcdisk is not the original distribution file exit original } cp $srcdir/pcdisk 816407398/pcdisk ed 816407398/pcdisk >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pcdisk' 38a vgact65540 . 37a vgaark2000pv . 33c ether509 pci . 26a sbcd m . wq //GO.SYSIN DD VADIM pcdisk sum=`{sum < 816407398/pcdisk} if(~ f00cc499621 $sum(1)^$sum(2)) echo if not{ echo 816407398/pcdisk checksum error creating updated file exit checksum } target=816407398/trap.c echo -n '816407398/trap.c: ' if(! test -f $srcdir/trap.c || ! test -r $srcdir/trap.c){ echo $srcdir/trap.c unreadable exit unreadable } sum=`{sum < $srcdir/trap.c} if(! ~ 4df1897714709 $sum(1)^$sum(2)){ echo $srcdir/trap.c is not the original distribution file exit original } cp $srcdir/trap.c 816407398/trap.c ed 816407398/trap.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM trap.c' 426a m->syscall++; . 384c if(i == 8){ . 262a m->intr++; . wq //GO.SYSIN DD VADIM trap.c sum=`{sum < 816407398/trap.c} if(~ 876d6dcf14737 $sum(1)^$sum(2)) echo if not{ echo 816407398/trap.c checksum error creating updated file exit checksum } target=816407398/vga.h echo -n '816407398/vga.h: ' if(! test -f $srcdir/vga.h || ! test -r $srcdir/vga.h){ echo $srcdir/vga.h unreadable exit unreadable } sum=`{sum < $srcdir/vga.h} if(! ~ 6e1dc5081495 $sum(1)^$sum(2)){ echo $srcdir/vga.h is not the original distribution file exit original } cp $srcdir/vga.h 816407398/vga.h ed 816407398/vga.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM vga.h' 26a Pblack = 0xFF, Pwhite = 0x00, . wq //GO.SYSIN DD VADIM vga.h sum=`{sum < 816407398/vga.h} if(~ feeb88e41530 $sum(1)^$sum(2)) echo if not{ echo 816407398/vga.h checksum error creating updated file exit checksum } target=816407398/vgatvp3020.c echo -n '816407398/vgatvp3020.c: ' if(! test -f $srcdir/vgatvp3020.c || ! test -r $srcdir/vgatvp3020.c){ echo $srcdir/vgatvp3020.c unreadable exit unreadable } sum=`{sum < $srcdir/vgatvp3020.c} if(! ~ 2449049b5422 $sum(1)^$sum(2)){ echo $srcdir/vgatvp3020.c is not the original distribution file exit original } cp $srcdir/vgatvp3020.c 816407398/vgatvp3020.c ed 816407398/vgatvp3020.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM vgatvp3020.c' 193,195c tvp3020xo(0x20, 0xFF); tvp3020xo(0x21, 0xFF); tvp3020xo(0x22, 0xFF); tvp3020xo(0x23, 0xFF); tvp3020xo(0x24, 0xFF); tvp3020xo(0x25, 0xFF); tvp3020xo(0x26, 0x00); tvp3020xo(0x27, 0x00); tvp3020xo(0x28, 0x00); . wq //GO.SYSIN DD VADIM vgatvp3020.c sum=`{sum < 816407398/vgatvp3020.c} if(~ d9a694235422 $sum(1)^$sum(2)) echo if not{ echo 816407398/vgatvp3020.c checksum error creating updated file exit checksum } target=816407398/devatapi.c echo -n '816407398/devatapi.c (new): ' cat > 816407398/devatapi.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * Alberto Nava beto@plan9.cs.su.oz.au * 16/6/95 */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "devtab.h" #define DPRINT if(debug) print typedef struct Drive Drive; typedef struct Ident Ident; typedef struct Controller Controller; typedef struct Atapicmd Atapicmd; enum { /* ports */ Pbase0= 0x1F0, Pbase1= 0x170, Pbase2= 0x1E8, Pdata= 0, /* data port (16 bits) */ Perror= 1, /* error port (read) */ Pprecomp= 1, /* buffer mode port (write) */ Pcount= 2, /* sector count port */ Psector= 3, /* sector number port */ Pcyllsb= 4, /* least significant byte cylinder # */ Pcylmsb= 5, /* most significant byte cylinder # */ Pdh= 6, /* drive/head port */ Pstatus= 7, /* status port (read) */ Sbusy= (1<<7), Sready= (1<<6), Sdrq= (1<<3), Serr= (1<<0), Pcmd= 7, /* cmd port (write) */ /* ATA commands */ Crecal= 0x10, Cread= 0x20, Cwrite= 0x30, Cident= 0xEC, Cident2= 0xFF, /* pseudo command for post Cident interrupt */ Cinitparam= 0x91, /* ATAPI commands */ Cpktcmd= 0xA0, Cpktcmd2= 0xFE, /* pseudo command for last Cpktcmd interrupt */ Cidentd= 0xA1, Ccapacity= 0x25, Cread2= 0x28, /* something we have to or into the drive/head reg */ DHmagic= 0xA0, /* file types */ Qdir= 0, Qdir2, Qcmd, Qdata, Qcd, Qcdctl, Qdebug, Maxxfer= BY2PG, /* maximum transfer size/cmd */ Hardtimeout= 4000, /* disk access timeout */ Maxloop= 1000000, }; /* * an atapi CD-ROM drive */ struct Drive { QLock; /* exclusive access to the disk */ Ref opens; /* how many Qcd opens */ Controller *cp; /* its controller */ int blocks; /* disk size in blocks */ int bsize; /* block size */ int online; /* ok */ int drive; /* drive number */ int bytes; /* for ATA ident*/ int drq; ushort config; }; /* * a controller for 2 drives */ struct Controller { QLock; /* exclusive access to the controller */ Lock reglock; /* exclusive access to the registers */ int pbase; /* base port */ /* * current operation */ int cmd; /* current command */ int lastcmd; /* debugging info */ Rendez r; /* wait here for command termination */ char *buf; /* xfer buffer */ int nsecs; /* length of transfer (sectors) */ int sofar; /* sectors transferred so far */ int status; /* last operation status */ int error; /* last operation error code */ int count; /* last operation bytes transfered */ Drive *dp; /* drive being accessed */ Atapicmd *ac; /* Atapi command being processed */ }; struct Atapicmd { QLock; int pid; /* process doing atapi cmd */ int len; /* lenght of buffer space */ char *buf; /* buffer for IN*/ ushort status; /* status after completition */ ushort error; /* error after completition */ ushort count; /* real count of bytes transfered */ uchar cmdblk[12]; }; Controller *atapic; Drive *atapi; Atapicmd *atapicmd; int debug; static void cdsize(Drive*); static long cdio(Chan*, char*, ulong, ulong); static void atapiintr(Ureg*, void*); static void atapiexec(Drive*,Atapicmd *); static void atapiident(Drive*); Dirtab atapitab[]={ "cmd", {Qcmd}, 0, 0600, "data", {Qdata}, 0, 0600, "cd", {Qcd}, 0, 0600, "cdctl", {Qcdctl}, 0, 0600, "debug", {Qdebug}, 1, 0666, }; #define Natapitab (sizeof(atapitab)/sizeof(Dirtab)) int atapigen(Chan *c, void *vp, int ntab, int i, Dir *dp) { Qid q; USED(vp); USED(ntab); q.vers = 0; /* top level directory contains the directory atapi */ if(c->qid.path == CHDIR){ if(i) return -1; q.path = CHDIR | Qdir2; devdir(c, q, "atapi", 0, eve, 0555, dp); return 1; } /* next level uses table */ return devgen(c, atapitab, Natapitab, i, dp); } void atapireset(void) { ISAConf atapiconf; Drive *dp; Controller *cp; int i; /* * BUG: just one disk */ atapiconf.port = Pbase2; atapiconf.irq = 11; if(isaconfig("cdrom", 0, &atapiconf) == 0) return; if(strcmp(atapiconf.type, "atapi") != 0) return; switch(atapiconf.port){ case 0x1F0: case 0x170: case 0x1E8: case 0x168: break; default: print("devatapi: bad atapi port 0x%x\n", atapiconf.port); return; } switch(atapiconf.irq){ case 10: case 11: case 12: case 14: case 15: break; default: print("devatapi: bad atapi irq %d\n", atapiconf.irq); return; } atapi = xalloc(sizeof(Drive)); atapic = xalloc(sizeof(Controller)); atapicmd = xalloc(sizeof(Atapicmd)); cp = atapic; cp->buf = 0; cp->pbase = atapiconf.port ; setvec(Int0vec+atapiconf.irq, atapiintr, 0); /* 3th interface */ dp = atapi; dp->drive = 0; dp->online = 0; dp->cp = cp; for(i = 0; i < atapiconf.nopt; i++){ if(strcmp(atapiconf.opt[i], "slave")) continue; dp->drive = 1; break; } print("atapi0: port %lux irq %d: drive %d online %d\n", cp->pbase, atapiconf.irq, dp->drive, dp->online); /* ilock(&cp->reglock); outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4)); outb(cp->pbase+Pcmd, 0x08); delay(20); print("%2.2uX %2.2uX %2.2uX\n", inb(cp->pbase+Pstatus), inb(cp->pbase+Pcylmsb), inb(cp->pbase+Pcyllsb)); iunlock(&cp->reglock); */ } void atapiinit(void) { } Chan* atapiattach(char *spec) { Drive *dp; dp = atapi; if(waserror()){ dp->online = 0; qunlock(dp); } else{ qlock(dp); if(!dp->online){ dp->bytes = 512; atapiident(dp); dp->online = 1; } qunlock(dp); poperror(); } return devattach('T', spec); } Chan* atapiclone(Chan *c, Chan *nc) { return devclone(c, nc); } int atapiwalk(Chan *c, char *name) { return devwalk(c, name, atapitab, (long)Natapitab, atapigen); } void atapistat(Chan *c, char *dp) { devstat(c, dp, atapitab, (long)Natapitab, atapigen); } Chan* atapiopen(Chan *c, int omode) { switch(c->qid.path) { case Qcd: if(incref(&atapi->opens) == 1) { if(waserror()) { decref(&atapi->opens); nexterror(); } cdsize(atapi); poperror(); } break; } return devopen(c, omode, atapitab, (long)Natapitab, atapigen); } void atapicreate(Chan *c, char *name, int omode, ulong perm) { USED(c, name, omode, perm); error(Eperm); } void atapiclose(Chan *c) { switch(c->qid.path) { default: break; case Qcd: if(c->flag & COPEN) decref(&atapi->opens); break; } } void atapiremove(Chan *c) { USED(c); error(Eperm); } void atapiwstat(Chan *c, char *dp) { USED(c, dp); error(Eperm); } long atapiread(Chan *c, char *a, long n, ulong offset) { char *t, buf[64]; USED(a, n, offset); if(c->qid.path & CHDIR) return devdirread(c, a, n, atapitab, Natapitab, atapigen); switch (c->qid.path) { case Qcmd: if (n < 4) error(Ebadarg); if (canqlock(atapicmd)) { qunlock(atapicmd); error(Egreg); } if(atapicmd->pid != u->p->pid) error(Egreg); n = 4; *a++ = 0; *a++ = 0; *a++ = atapicmd->error; *a = atapicmd->status; qunlock(atapicmd); break; case Qdata: if (canqlock(atapicmd)) { qunlock(atapicmd); error(Egreg); } if(atapicmd->pid != u->p->pid) error(Egreg); if (n > Maxxfer) error(Ebadarg); atapicmd->len = n; atapicmd->buf = 0; if (n == 0) { atapiexec(&atapi[0],atapicmd); break; } atapicmd->buf = smalloc(Maxxfer); if (waserror()) { free(atapicmd->buf); nexterror(); } atapiexec(&atapi[0],atapicmd); memmove(a,atapicmd->buf,atapicmd->count); poperror(); free(atapicmd->buf); n=atapicmd->count; break; case Qcd: n = cdio(c,a,n,offset); break; case Qcdctl: t = "atapi"; sprint(buf, "port=0x%ux drive=%s\n", atapic->pbase, t); return readstr(offset, a, n, buf); case Qdebug: if(offset == 0){ n=1; *a="01"[debug!=0]; }else n = 0; break; default: panic("atapiwrite"); } return n; } long atapiwrite(Chan *c, char *a, long n, ulong offset) { USED(c, a, n, offset); switch (c->qid.path) { case Qcmd: qlock(atapicmd); if (n != 12) { qunlock(atapicmd); error(Ebadarg); } atapicmd->pid = u->p->pid; memmove(atapicmd->cmdblk,a,n); break; case Qdata: error(Eperm); case Qcd: case Qcdctl: error(Eperm); break; case Qdebug: if(offset == 0){ debug = (*a=='1'); n = 1; }else n = 0; break; default: panic("atapiwrite"); } return n; } /* * did an interrupt happen? */ static int cmddone(void *a) { Controller *cp = a; return cp->cmd == 0; } /* * Wait for the controller to be ready to accept a command. */ static void cmdreadywait(Drive *dp) { long start; int period; Controller *cp = dp->cp; period = 2000; start = m->ticks; while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready) if(TK2MS(m->ticks - start) > period){ print("atapi0: cmdreadywait failed %lud %lud\n", m->ticks, start); error(Eio); } } static void cmddrqwait(Drive *dp) { long loop; Controller *cp = dp->cp; loop=0; while((inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0) if(++loop > Maxloop) { print("cmddrqwait:cmd=%lux status=%lux\n", cp->cmd, inb(cp->pbase+Pstatus)); error(Eio); } } static void atapisleep(Controller *cp) { tsleep(&cp->r, cmddone, cp, Hardtimeout); if(cp->cmd && cp->cmd != Cident2){ DPRINT("hard drive timeout\n"); error("ata drive timeout"); } } /* * ident sector from drive. this is from ANSI X3.221-1994 */ struct Ident { ushort config; /* general configuration info */ ushort cyls; /* # of cylinders (default) */ ushort reserved0; ushort heads; /* # of heads (default) */ ushort b2t; /* unformatted bytes/track */ ushort b2s; /* unformated bytes/sector */ ushort s2t; /* sectors/track (default) */ ushort reserved1[3]; /* 10 */ ushort serial[10]; /* serial number */ ushort type; /* buffer type */ ushort bsize; /* buffer size/512 */ ushort ecc; /* ecc bytes returned by read long */ ushort firm[4]; /* firmware revision */ ushort model[20]; /* model number */ /* 47 */ ushort s2i; /* number of sectors/interrupt */ ushort dwtf; /* double word transfer flag */ ushort capabilities; ushort reserved2; ushort piomode; ushort dmamode; ushort cvalid; /* (cvald&1) if next 4 words are valid */ ushort ccyls; /* current # cylinders */ ushort cheads; /* current # heads */ ushort cs2t; /* current sectors/track */ ushort ccap[2]; /* current capacity in sectors */ ushort cs2i; /* current number of sectors/interrupt */ /* 60 */ ushort lbasecs[2]; /* # LBA user addressable sectors */ ushort dmasingle; ushort dmadouble; /* 64 */ ushort reserved3[64]; ushort vendor[32]; /* vendor specific */ ushort reserved4[96]; }; /* * get parameters from the drive */ static void atapiident(Drive *dp) { Controller *cp; char *buf; Ident *ip; cp = dp->cp; buf = smalloc(Maxxfer); qlock(cp); if(waserror()){ qunlock(cp); nexterror(); } /* cmdreadywait(dp); */ ilock(&cp->reglock); cp->nsecs = 1; cp->sofar = 0; cp->cmd = Cidentd; cp->dp = dp; cp->buf = buf; outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4)); outb(cp->pbase+Pcmd, cp->cmd); iunlock(&cp->reglock); atapisleep(cp); if(cp->status & Serr){ print("bad disk ident status %ux\n",cp->error); error(Eio); } ip = (Ident*)buf; /* * this function appears to respond with an extra interrupt after * the ident information is read, except on the safari. The following * delay gives this extra interrupt a chance to happen while we are quiet. * Otherwise, the interrupt may come during a subsequent read or write, * causing a panic and much confusion. */ if (cp->cmd == Cident2) tsleep(&cp->r, return0, 0, Hardtimeout); dp->config = ip->config; DPRINT("ident config = %ux cap %ux \n",ip->config,ip->capabilities); cp->lastcmd = cp->cmd; cp->cmd = 0; cp->buf = 0; free(buf); poperror(); qunlock(cp); } static long cdio(Chan *c, char *a, ulong len, ulong offset) { Drive *d; ulong bn, n, o, m; int bsize; USED(c); d = &atapi[0]; bsize = 2048; qlock(atapicmd); atapicmd->buf = smalloc(Maxxfer); atapicmd->len = bsize; if (waserror()) { free(atapicmd->buf); qunlock(atapicmd); nexterror(); } n = len; while(n > 0) { bn = offset / bsize; o = offset % bsize; m = bsize - o; if (m > n) m = n; if (bn > d->blocks) { print("reading too far\n"); break; } memset(atapicmd->cmdblk,0,12); atapicmd->cmdblk[0] = Cread2; atapicmd->cmdblk[2] = bn >> 24; atapicmd->cmdblk[3] = bn >> 16; atapicmd->cmdblk[4] = bn >> 8; atapicmd->cmdblk[5] = bn; atapicmd->cmdblk[7] = 0; atapicmd->cmdblk[8] = 1; atapiexec(&atapi[0],atapicmd); if (atapicmd->count!=bsize) { print("short read\n"); break; } memmove(a, atapicmd->buf + o, m); n -= m; offset += m; a += m; } poperror(); free(atapicmd->buf); qunlock(atapicmd); return len-n; } /* * disk and block size */ static void cdsize(Drive *d) { Controller *cp; cp = d->cp; qlock(atapicmd); atapicmd->buf = smalloc(Maxxfer); atapicmd->len = 8; if (waserror()) { free(atapicmd->buf); qunlock(atapicmd); nexterror(); } memset(atapicmd->cmdblk,0,12); atapicmd->cmdblk[0] = Ccapacity; atapiexec(d,atapicmd); if (atapicmd->count!=8) { print("cmd=%2.2uX, lastcmd=%2.2uX ", cp->cmd, cp->lastcmd); print("cdsize count %d, status 0x%2.2uX, error 0x%2.2uX\n", atapicmd->count, atapicmd->status, atapicmd->error); error(Eio); } d->blocks = atapicmd->buf[0] << 24 | atapicmd->buf[1] <<16 | atapicmd->buf[2] << 8 | atapicmd->buf[3] ; d->bsize = atapicmd->buf[4] << 24 | atapicmd->buf[5] << 16 | atapicmd->buf[6] << 8 |atapicmd->buf[7]; poperror(); free(atapicmd->buf); qunlock(atapicmd); return; } void atapiexec(Drive *dp,Atapicmd *ac) { Controller *cp; cp = dp->cp; qlock(cp); if(waserror()){ qunlock(cp); nexterror(); } cmdreadywait(dp); ilock(&cp->reglock); cp->nsecs = 1; cp->sofar = 0; cp->cmd = Cpktcmd; cp->dp = dp; cp->buf = ac->buf; outb(cp->pbase+Pcount, 0); outb(cp->pbase+Psector, 0); outb(cp->pbase+Pprecomp, 0); outb(cp->pbase+Pcyllsb, ac->len); outb(cp->pbase+Pcylmsb, ac->len>>8); outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4)); outb(cp->pbase+Pcmd, Cpktcmd); iunlock(&cp->reglock); if((dp->config & 0x0060) != 0x0020){ dp->drq = 0; cmddrqwait(dp); ilock(&cp->reglock); outss(cp->pbase+Pdata, ac->cmdblk, 12/2); iunlock(&cp->reglock); DPRINT("CMD issue\n"); } else dp->drq = 1; atapisleep(cp); DPRINT("Wakeup %ux\n",ac); ac->status = cp->status; ac->error = cp->error; ac->count = cp->count; DPRINT("status %ux error %ux count %ux\n",cp->status,cp->error,cp->count); if(cp->status & Serr){ DPRINT("Bad packet command %ux\n",cp->error); error(Eio); } cp->buf = 0; cp->lastcmd = cp->cmd; cp->cmd = 0; poperror(); qunlock(cp); } int lastcount; static void atapiintr(Ureg *ur, void *arg) { Controller *cp; Drive *dp; long loop; int count; char *addr; USED(ur, arg); /* * BUG!! if there is ever more than one controller, we need a way to * distinguish which interrupted (use arg). */ cp = atapic; dp = cp->dp; ilock(&cp->reglock); loop = 0; while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){ if(++loop > Maxloop) { DPRINT("cmd=%lux status=%lux/%lux, error=%lux\n", cp->cmd, inb(cp->pbase+Pstatus), cp->status, inb(cp->pbase+Perror)); panic("atapiintr: wait busy"); } } switch(cp->cmd){ case Cpktcmd: DPRINT("pkt\n"); if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; } if(dp->drq == 1){ dp->drq = 0; outss(cp->pbase+Pdata, atapicmd->cmdblk, 12/2); break; } addr = cp->buf; if (addr == 0) { /* non-data command */ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->count = 0; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; } loop = 0; while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0) if(++loop > Maxloop) { DPRINT("cmd=%lux status=%lux error=%lux\n", cp->cmd, inb(cp->pbase+Pstatus),inb(cp->pbase+Perror)); /* * No data for cmd, probably a user level error * no Allocation length set or similar. */ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->count = 0; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; } lastcount = (count = inb(cp->pbase+Pcyllsb) | inb(cp->pbase+Pcylmsb) << 8); if (count > Maxxfer) count = Maxxfer; inss(cp->pbase+Pdata, addr, count/2); cp->count = count; cp->lastcmd = cp->cmd; cp->cmd = Cpktcmd2; break; case Cpktcmd2: DPRINT("pkt2 last count %d\n", lastcount); cp->lastcmd = cp->cmd; cp->cmd = 0; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; case Cidentd: loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ if(++loop > Maxloop) { DPRINT("cmd=%lux status=%lux\n", cp->cmd, inb(cp->pbase+Pstatus)); panic("ataintr: read/ident"); } cp->status = inb(cp->pbase+Pstatus); } if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; } addr = cp->buf; if(addr){ addr += cp->sofar*dp->bytes; inss(cp->pbase+Pdata, addr, dp->bytes/2); } cp->sofar++; if(cp->sofar > cp->nsecs) print("ataintr %d %d\n", cp->sofar, cp->nsecs); if(cp->sofar >= cp->nsecs){ cp->lastcmd = cp->cmd; if (cp->cmd == Cread) cp->cmd = 0; else cp->cmd = Cident2; wakeup(&cp->r); } break; case Cident2: cp->lastcmd = cp->cmd; cp->cmd = 0; break; default: count = inb(cp->pbase+Pcyllsb) | inb(cp->pbase+Pcylmsb); print("count=%.2ux\n",count); count = inb(cp->pbase+Psector); print("sector=%.2ux\n",count); print("weird disk interrupt, cmd=%.2ux, lastcmd= %.2ux status=%.2ux\n", cp->cmd, cp->lastcmd, cp->status); break; } iunlock(&cp->reglock); } //GO.SYSIN DD VADIM . sum=`{sum < 816407398/devatapi.c} if(~ e7f58a5017745 $sum(1)^$sum(2)) echo if not{ echo 816407398/devatapi.c checksum error extracting new file exit checksum } target=816407398/ether3210.c echo -n '816407398/ether3210.c (new): ' cat > 816407398/ether3210.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * EAGLE Technology Model NE3210 * 32-Bit EISA BUS Ethernet LAN Adapter. * Programmer's Reference Guide kindly supplied * by Artisoft Inc/Eagle Technology. * * BUGS: * no setting of values from config file; * should we worry about doubleword memmove restrictions? * no way to use mem addresses > 0xD8000 at present. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" #include "devtab.h" #include "ether.h" enum { /* EISA slot space */ NVLreset = 0xC84, /* 0 == reset, 1 == enable */ NVLconfig = 0xC90, DP83902off = 0x000, /* offset of DP83902 registers */ Eaddroff = 0x016, /* offset of Ethernet address */ }; static struct { ulong port; ulong config; } slotinfo[MaxEISA]; static ulong mem[8] = { 0x00FF0000, 0x00FE0000, 0x000D8000, 0x0FFF0000, 0x0FFE0000, 0x0FFC0000, 0x000D0000, 0x00000000, }; static ulong irq[8] = { 15, 12, 11, 10, 9, 7, 5, 3, }; static struct { char *type; uchar val; } media[] = { { "10BaseT", 0x00, }, { "RJ-45", 0x00, }, { "10Base5", 0x80, }, { "AUI", 0x80, }, { "10Base2", 0xC0, }, { "BNC", 0xC0, }, { 0, }, }; static void* read(Ctlr *ctlr, void *to, ulong from, ulong len) { /* * In this case, 'from' is an index into the shared memory. */ memmove(to, (void*)(ctlr->card.mem+from), len); return to; } static void* write(Ctlr *ctlr, ulong to, void *from, ulong len) { /* * In this case, 'to' is an index into the shared memory. */ memmove((void*)(ctlr->card.mem+to), from, len); return (void*)to; } static int reset(Ctlr *ctlr) { static int already; int i; ulong p; /* * First time through, check if this is an EISA machine. * If not, nothing to do. If it is, run through the slots * looking for appropriate cards and saving the * configuration info. */ if(already == 0){ already = 1; if(strncmp((char*)(KZERO|0xFFFD9), "EISA", 4)) return -1; for(i = 1; i < MaxEISA; i++){ p = i*0x1000; if(inl(p+EISAconfig) != 0x0118CC3A) continue; slotinfo[i].port = p; slotinfo[i].config = inb(p+NVLconfig); } } /* * Look through the found adapters for one that matches * the given port address (if any). The possibilties are: * 1) 0; * 2) a slot address. */ i = 0; if(ctlr->card.port == 0){ for(i = 1; i < MaxEISA; i++){ if(slotinfo[i].port) break; } } else if(ctlr->card.port >= 0x1000){ if((i = (ctlr->card.port>>16)) < MaxEISA){ if((ctlr->card.port & 0xFFF) || slotinfo[i].port == 0) i = 0; } } if(i >= MaxEISA || slotinfo[i].port == 0) return -1; /* * Set the software configuration using the values obtained. * For now, ignore any values from the config file. */ ctlr->card.port = slotinfo[i].port; ctlr->card.mem = KZERO|mem[slotinfo[i].config & 0x07]; ctlr->card.irq = irq[(slotinfo[i].config>>3) & 0x07]; ctlr->card.size = 32*1024; if((ctlr->ea[0]|ctlr->ea[1]|ctlr->ea[2]|ctlr->ea[3]|ctlr->ea[4]|ctlr->ea[5]) == 0){ for(i = 0; i < sizeof(ctlr->ea); i++) ctlr->ea[i] = inb(ctlr->card.port+Eaddroff+i); } /* * For now, can't map anything other than mem addresses * 0xD0000 and 0xD8000. */ if(getisa(ctlr->card.mem, ctlr->card.size, 0) == 0) panic("ether3210: 0x%lux reused or invalid", ctlr->card.mem); /* * Set up the stupid DP8390 configuration. */ ctlr->card.reset = reset; ctlr->card.attach = dp8390attach; ctlr->card.mode = dp8390mode; ctlr->card.read = read; ctlr->card.write = write; ctlr->card.receive = dp8390receive; ctlr->card.transmit = dp8390transmit; ctlr->card.intr = dp8390intr; ctlr->card.overflow = dp8390overflow; ctlr->card.bit16 = 1; ctlr->card.ram = 1; ctlr->card.dp8390 = ctlr->card.port+DP83902off; ctlr->card.tstart = 0; ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz); ctlr->card.pstop = HOWMANY(ctlr->card.size, Dp8390BufSz); /* * Reset the board, then * initialise the DP83902, * set the ether address. */ outb(ctlr->card.port+NVLreset, 0x00); delay(2); outb(ctlr->card.port+NVLreset, 0x01); dp8390reset(ctlr); dp8390setea(ctlr); return 0; } void ether3210link(void) { addethercard("NE3210", reset); } //GO.SYSIN DD VADIM . sum=`{sum < 816407398/ether3210.c} if(~ ba19e7ad4165 $sum(1)^$sum(2)) echo if not{ echo 816407398/ether3210.c checksum error extracting new file exit checksum } target=816407398/pci.c echo -n '816407398/pci.c (new): ' cat > 816407398/pci.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * Trivial PCI configuration code. * Only deals with bus 0, amongst other glaring omissions. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" static Lock pcicfglock; static int pcicfgmode = -1; static void pcicfginit(int) { /* * Try to determine which PCI configuration mode is implemented. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses * a DWORD at 0xCF8 and another at 0xCFC and will pass through * any non-DWORD accesses as normal I/O cycles. There shouldn't be * a device behind theses addresses so if Mode2 accesses fail try * for Mode1 (which is preferred, Mode2 is deprecated). */ outb(PCIcse, 0); if(inb(PCIcse) == 0){ pcicfgmode = 2; return; } outl(PCIaddr, 0); if(inl(PCIaddr) == 0){ pcicfgmode = 1; return; } pcicfgmode = -1; } /* * Read a chunk of PCI configuration space. * Assumes arguments are within limits and regno and * nbytes are DWORD aligned. */ void pcicfgr(int busno, int devno, int funcno, int regno, void* data, int nbytes) { ulong addr, *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ case 1: addr = 0x80000000|((busno & 0xFF)<<16)|((devno & 0x1F)<<11)|((funcno & 0x03)<<8); p = data; for(len = nbytes/sizeof(ulong); len > 0; len--){ outl(PCIaddr, addr|(regno & 0xFF)); *p = inl(PCIdata); p++; regno += sizeof(ulong); } outl(PCIaddr, 0); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(ulong); len > 0; len--){ *p = inl(base); p++; base += sizeof(*p); } outb(PCIcse, 0); break; } unlock(&pcicfglock); } void pcicfgw(int busno, int devno, int funcno, int regno, void* data, int nbytes) { ulong addr, *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ case 1: addr = 0x80000000|((busno & 0xFF)<<16)|((devno & 0x1F)<<11)|((funcno & 0x03)<<8); p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outl(PCIaddr, addr|(regno & 0xFF)); outl(PCIdata, *p); p++; regno += sizeof(*p); } outl(PCIaddr, 0); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outl(base, *p); p++; base += sizeof(*p); } outb(PCIcse, 0); } unlock(&pcicfglock); } /* * This is not in the spec, but at least the CMD640B requires it. */ void pcicfgw8(int busno, int devno, int funcno, int regno, void* data, int nbytes) { uchar *p; int base, len; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); switch(pcicfgmode){ default: panic("pcicfgw8: pcicfgmode %d\n", pcicfgmode); break; case 2: if(devno >= 16) break; outb(PCIcse, 0x80|((funcno & 0x07)<<1)); outb(PCIforward, busno); base = (0xC000|(devno<<8)) + regno; p = data; for(len = nbytes/sizeof(*p); len > 0; len--){ outb(base, *p); p++; base += sizeof(*p); } outb(PCIcse, 0); } unlock(&pcicfglock); } int pcimatch(int busno, int devno, PCIcfg* pcicfg) { ulong l; lock(&pcicfglock); if(pcicfgmode == -1) pcicfginit(busno); unlock(&pcicfglock); while(devno < MaxPCI){ if(pcicfgmode == 2 && devno >= 16) break; l = 0; pcicfgr(busno, devno, 0, 0, &l, sizeof(ulong)); devno++; if((l & 0xFFFF) != pcicfg->vid) continue; if(pcicfg->did && ((l>>16) & 0xFFFF) != pcicfg->did) continue; pcicfgr(busno, devno-1, 0, 0, pcicfg, sizeof(PCIcfg)); return devno; } return -1; } //GO.SYSIN DD VADIM . sum=`{sum < 816407398/pci.c} if(~ c64b5f8a3778 $sum(1)^$sum(2)) echo if not{ echo 816407398/pci.c checksum error extracting new file exit checksum } target=816407398/vgaark2000pv.c echo -n '816407398/vgaark2000pv.c (new): ' cat > 816407398/vgaark2000pv.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include #include #include "screen.h" #include "vga.h" extern GBitmap gscreen; extern Cursor curcursor; static Lock ark2000pvlock; static ulong storage; static Point hotpoint; static void setark2000pvpage(int page) { vgaxo(Seqx, 0x15, page); vgaxo(Seqx, 0x16, page); } static void disable(void) { uchar seq20; seq20 = vgaxi(Seqx, 0x20) & ~0x08; vgaxo(Seqx, 0x20, seq20); } static void enable(void) { uchar seq20; /* * Disable the cursor then configure for X-Windows style, * 64x64 and 4/8-bit colour depth. * Set cursor colours for 4/8-bit. */ seq20 = vgaxi(Seqx, 0x20) & ~0x1F; vgaxo(Seqx, 0x20, seq20); seq20 |= 0x1C; vgaxo(Seqx, 0x26, Pwhite); vgaxo(Seqx, 0x27, Pwhite); vgaxo(Seqx, 0x28, Pwhite); vgaxo(Seqx, 0x29, Pblack); vgaxo(Seqx, 0x2A, Pblack); vgaxo(Seqx, 0x2B, Pblack); /* * Cursor storage is a 1Kb block located in the last 16Kb * of video memory. Crt25 is the index of which 1Kb block. */ storage = (vgaxi(Seqx, 0x10)>>6) & 0x03; storage = (1024*1024)<>16); p = ((uchar*)gscreen.base) + (storage & 0xFFFF); } /* * The cursor is set in X11 mode which gives the following * truth table: * and xor colour * 0 0 underlying pixel colour * 0 1 underlying pixel colour * 1 0 background colour * 1 1 foreground colour * Put the cursor into the top-left of the 64x64 array. * The manual doesn't say what the data layout in memory is - * this worked out by trial and error. */ for(y = 0; y < 64; y++){ for(x = 0; x < 64/8; x++){ if(x < 16/8 && y < 16){ *p++ = c->clr[2*y + x]|c->set[2*y + x]; *p++ = c->set[2*y + x]; } else { *p++ = 0x00; *p++ = 0x00; } } } /* * Set the cursor hotpoint and enable the cursor. */ hotpoint = c->offset; vgaxo(Seqx, 0x20, seq20|0x08); unlock(&ark2000pvlock); } static int move(Point p) { int x, xo, y, yo; if(canlock(&ark2000pvlock) == 0) return 1; /* * Mustn't position the cursor offscreen even partially, * or it might disappear. Therefore, if x or y is -ve, adjust the * cursor origins instead. */ if((x = p.x+hotpoint.x) < 0){ xo = -x; x = 0; } else xo = 0; if((y = p.y+hotpoint.y) < 0){ yo = -y; y = 0; } else yo = 0; /* * Load the new values. */ vgaxo(Seqx, 0x2C, xo); vgaxo(Seqx, 0x2D, yo); vgaxo(Seqx, 0x21, (x>>8) & 0x0F); vgaxo(Seqx, 0x22, x & 0xFF); vgaxo(Seqx, 0x23, (y>>8) & 0x0F); vgaxo(Seqx, 0x24, y & 0xFF); unlock(&ark2000pvlock); return 0; } Hwgc ark2000pvhwgc = { "ark2000pvhwgc", enable, load, move, disable, 0, }; static void ark2000pvpage(int page) { /* * Shouldn't need to lock if linear addressing * is enabled. */ if((vgaxi(Seqx, 0x10) & 0x10) == 0 && hwgc == &ark2000pvhwgc){ lock(&ark2000pvlock); setark2000pvpage(page); unlock(&ark2000pvlock); } else setark2000pvpage(page); } static Vgac ark2000pv = { "ark2000pv", ark2000pvpage, 0, }; void vgaark2000pvlink(void) { addvgaclink(&ark2000pv); addhwgclink(&ark2000pvhwgc); } //GO.SYSIN DD VADIM . sum=`{sum < 816407398/vgaark2000pv.c} if(~ 7dbec7d53942 $sum(1)^$sum(2)) echo if not{ echo 816407398/vgaark2000pv.c checksum error extracting new file exit checksum } target=816407398/vgact65540.c echo -n '816407398/vgact65540.c (new): ' cat > 816407398/vgact65540.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include #include "screen.h" #include "vga.h" enum { Index= 0x3D6, /* index reg */ Data= 0x3D7, /* data reg */ }; static void ct65540page(int page) { outb(Index, 0x10); outb(Data, page<<6); } static Vgac ct65540 = { "ct65540", ct65540page, 0, }; void vgact65540link(void) { addvgaclink(&ct65540); } //GO.SYSIN DD VADIM . sum=`{sum < 816407398/vgact65540.c} if(~ 6ffecd39440 $sum(1)^$sum(2)) echo if not{ echo 816407398/vgact65540.c checksum error extracting new file exit checksum } echo obsolete files: /n/juke/plan_9/sys/src/9/pc/bootpccd.c /n/juke/plan_9/sys/src/9/pc/pccd.c