#!/bin/rc # # command: /bin/boddle /sys/src/9/pc . # srcdir: /sys/src/9/pc # version: 872180801 # date: Thu Aug 21 12:26:41 EDT 1997 # myname=$0 doextract=no fn usage{ echo $myname: usage: $myname '[-X] [src-directory]' >[1=2] exit usage } fn sigint{ rm -rf 872180801 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 872180801 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 872180801 mkdir 872180801 target=872180801/adaptec.c echo -n '872180801/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 872180801/adaptec.c ed 872180801/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 < 872180801/adaptec.c} if(~ 0c17c09015603 $sum(1)^$sum(2)) echo if not{ echo 872180801/adaptec.c checksum error creating updated file exit checksum } target=872180801/bbmalloc.c echo -n '872180801/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 872180801/bbmalloc.c ed 872180801/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 < 872180801/bbmalloc.c} if(~ 6d7538971387 $sum(1)^$sum(2)) echo if not{ echo 872180801/bbmalloc.c checksum error creating updated file exit checksum } target=872180801/dat.h echo -n '872180801/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 872180801/dat.h ed 872180801/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 < 872180801/dat.h} if(~ adde50898869 $sum(1)^$sum(2)) echo if not{ echo 872180801/dat.h checksum error creating updated file exit checksum } target=872180801/devata.c echo -n '872180801/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 872180801/devata.c ed 872180801/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); outb(cp->pbase+Pcmd, 0x08); if(atactlrwait(dp->cp, DHmagic, 0, MS2TK(100))){ DPRINT("%s: isatapi ctlrwait status %ux\n", dp->vol, inb(cp->pbase+Pstatus)); return 0; } 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, Hardtimeout); poperror(); if(loop) nexterror(); if(cp->status & Serr){ DPRINT("%s: Bad packet command %ux, error %ux\n", dp->vol, cp->cmdblk[0], 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 = 2; 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 = 2; retry: if(waserror()){ DPRINT("atapipart: cmd %uX error %uX\n", cp->cmd, cp->error); 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 & 0xF0; else err = 0; qunlock(cp->ctlrlock); if(err == 0x20) return; nexterror(); } cp->buf = buf; cp->dp = dp; cp->len = 18; cp->count = 0; memset(cp->cmdblk, 0, sizeof(cp->cmdblk)); cp->cmdblk[0] = Creqsense; cp->cmdblk[4] = 18; atapiexec(dp); if(cp->count != 18){ 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); } 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; . 1143c case Cedd: . 1139,1141c case Cfeature: . 1135a else cp->cmd = 0; inb(cp->pbase+Pstatus); . 1132,1134c if(cp->cmd != Cread) . 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 && cp->cmd != Cedd) 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) == 0) i = 1; else{ ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)) i = 1; } if(i){ dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; } . 997,1004c sprint(namebuf, "%spartition", dp->vol); if((p = getconf(namebuf)) == 0){ /* * Read second last sector from disk, null terminate. * The last sector used to hold 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 still check if there is a valid partition table in * the last sector if none is found in the second last. */ i = 0; ataxfer(dp, &dp->p[0], Cread, (dp->p[0].end-2)*dp->bytes, 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); . 829c atasleep(cp, Hardtimeout); . 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; XPRINT("%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; XPRINT("%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; XPRINT("%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(cp->error & Eabort){ if(isatapi(dp)){ cmd = Cidentd; goto retryatapi; } } . 740c DPRINT("%s: ident command %ux sent\n", dp->vol, cmd); if(cmd == Cident) atasleep(cp, 3000); else atasleep(cp, 10000); . 736,738c outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, cmd); IUNLOCK(&cp->reglock); . 733c cp->cmd = cmd; . 728,730c if(dp->atapi) cmd = Cidentd; else cmd = Cident; retryatapi: ILOCK(&cp->reglock); . 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); . 656c atasleep(cp, Hardtimeout); . 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; . 610,611c atasleep(cp, Hardtimeout); . 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 XPRINT("%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); . 503c tsleep(&cp->r, cmddone, cp, ms); . 501c atasleep(Controller *cp, int ms) . 496c DPRINT("%s: found bblk %ld at offset %ld\n", dp->vol, bblk, i); . 479,484c if(dp->atapi) ready = 0; else ready = Sready; return atactlrwait(dp->cp, dp->dh, ready, ticks); . 477c ticks = MS2TK(2000); . 475c ticks = MS2TK(10); . 473a dp->usetime = m->ticks; . 469,471c ulong ticks; uchar ready; . 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"); qlock(&ataprobelock); if(ataprobedone == 0){ atactlrreset(); ataprobedone = 1; } qunlock(&ataprobelock); for(driveno = 0; driveno < NDrive; driveno++){ if((dp = atadrive[driveno]) == 0) continue; . 240a int driveno; . 229a atareset(void) { } void . 225,226c for(i = 0; i < isa.nopt; i++){ DPRINT("ata%d: opt %s\n", ctlrno, isa.opt[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<resetok = 1; } } . 223c atadrive[driveno] = drive; } static int atactlrprobe(int ctlrno, int irq) { Controller *ctlr; int atapi, mask, port; uchar error, status, msb, lsb; /* * Check the existence of a controller by verifying a sensible * value can be written to and read from the drive/head register. * We define the primary/secondary/tertiary and quaternary controller * port addresses to be at fixed values. * If it's OK, allocate and initialise a Controller structure. */ port = pbase[ctlrno]; outb(port+Pdh, DHmagic); microdelay(1); if((inb(port+Pdh) & 0xFF) != DHmagic){ DPRINT("ata%d: DHmagic not ok\n", ctlrno); return -1; } DPRINT("ata%d: DHmagic ok\n", ctlrno); if((ctlr = xalloc(sizeof(Controller))) == 0) return -1; ctlr->pbase = port; ctlr->ctlrno = ctlrno; ctlr->lastcmd = 0xFF; /* * Attempt to check the existence of drives on the controller * by issuing a 'check device diagnostics' command. * Issuing a device reset here would possibly destroy any BIOS * drive remapping and, anyway, some controllers (Vibra16) don't * seem to implement the control-block registers; do it if requested. * Unfortunately the vector must be set at this point as the Cedd * command will generate an interrupt, which means the ataintr routine * will be left on the interrupt call chain even if there are no * drives found. * At least one controller/ATAPI-drive combination doesn't respond * to the Cedd (Micronics M54Li + Sanyo CRD-254P) so let's check for the * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ if(ctlr->resetok){ outb(port+Pctrl, Srst|nIEN); delay(10); outb(port+Pctrl, 0); if(atactlrwait(ctlr, DHmagic, 0, MS2TK(20))){ DPRINT("ata%d: Srst status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); } } atapi = 0; mask = 0; status = inb(port+Pstatus); DPRINT("ata%d: ATAPI %uX %uX %uX\n", ctlrno, status, inb(port+Pcylmsb), inb(port+Pcyllsb)); if(status == 0 && inb(port+Pcylmsb) == 0xEB && inb(port+Pcyllsb) == 0x14){ DPRINT("ata%d: ATAPI ok\n", ctlrno); setvec(irq, ataintr, ctlr); atapi |= 0x01; mask |= 0x01; goto skipedd; } if(atactlrwait(ctlr, DHmagic, 0, MS2TK(1)) || waserror()){ DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); return -1; } setvec(irq, ataintr, ctlr); ctlr->cmd = Cedd; outb(port+Pcmd, Cedd); atasleep(ctlr, Hardtimeout); poperror(); /* * The diagnostic returns a code in the error register, good * status is bits 6-0 == 0x01. * The existence of the slave is more difficult to determine, * different generations of controllers may respond in different * ways. The standards here offer little light but only more and * more heat: * 1) the slave must be done and have dropped Sbusy by now (six * seconds for the master, 5 seconds for the slave). If it * hasn't, then it has either failed or the controller is * broken in some way (e.g. Vibra16 returns status of 0xFF); * 2) theory says the status of a non-existent slave should be 0. * Of course, it's valid for all the bits to be 0 for a slave * that exists too... * 3) a valid ATAPI drive can have status 0 and the ATAPI signature * in the cylinder registers after reset. Of course, if the drive * has been messed about by the BIOS or some other O/S then the * signature may be gone. */ error = inb(port+Perror); DPRINT("ata%d: master diag error %ux\n", ctlr->ctlrno, error); if((error & ~0x80) == 0x01) mask |= 0x01; outb(port+Pdh, DHmagic|DHslave); microdelay(1); status = inb(port+Pstatus); error = inb(port+Perror); DPRINT("ata%d: slave diag status %ux, error %ux\n", ctlr->ctlrno, status, error); if(status && (status & (Sbusy|Serr)) == 0 && (error & ~0x80) == 0x01) mask |= 0x02; else if(status == 0){ msb = inb(port+Pcylmsb); lsb = inb(port+Pcyllsb); DPRINT("ata%d: ATAPI slave %uX %uX %uX\n", ctlrno, status, inb(port+Pcylmsb), inb(port+Pcyllsb)); if(msb == 0xEB && lsb == 0x14){ atapi |= 0x02; mask |= 0x02; } } skipedd: if(mask == 0){ xfree(ctlr); return -1; } atactlr[ctlrno] = ctlr; if(have640b >= 0 && (ctlrno & 0x01)) ctlr->ctlrlock = &atactlrlock[ctlrno-1]; else ctlr->ctlrlock = &atactlrlock[ctlrno]; if(mask & 0x01) atadrivealloc(ctlr, ctlrno*2, atapi & 0x01); if(mask & 0x02) atadrivealloc(ctlr, ctlrno*2+1, atapi & 0x02); return 0; } void atactlrreset(void) { int ctlrno, driveno, i, slave, spindown; ISAConf isa; cmd640b(); rz1000(); for(ctlrno = 0; ctlrno < NCtlr; ctlrno++){ memset(&isa, 0, sizeof(ISAConf)); if(isaconfig("ata", ctlrno, &isa) == 0 && ctlrno) continue; if(isa.irq == 0 && (isa.irq = defirq[ctlrno]) == 0) continue; if(atactlrprobe(ctlrno, Int0vec+isa.irq)) continue; . 217,221c drive->cp = ctlr; drive->driveno = driveno; sprint(drive->vol, "hd%d", drive->driveno); drive->dh = DHmagic; if(driveno & 0x01) drive->dh |= DHslave; drive->vers = 1; if(atapi){ sprint(drive->vol, "atapi%d", drive->driveno); drive->atapi = 1; . 210,215c static int atactlrwait(Controller* ctlr, uchar pdh, uchar ready, ulong ticks) { int port; uchar dh, status; port = ctlr->pbase; dh = (inb(port+Pdh) & DHslave)^(pdh & DHslave); ticks += m->ticks+1; do{ status = inb(port+Pstatus); if(status & Sbusy) continue; if(dh){ outb(port+Pdh, pdh); dh = 0; continue; } if((status & ready) == ready) return 0; }while(m->ticks < ticks); DPRINT("ata%d: ctlrwait failed %uX\n", ctlr->ctlrno, status); outb(port+Pdh, DHmagic); return 1; } static void atadrivealloc(Controller* ctlr, int driveno, int atapi) { Drive *drive; if((drive = xalloc(sizeof(Drive))) == 0){ DPRINT("ata%d: can't xalloc drive0\n", ctlr->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; extern void pcicfgw8(int, int, int, int, void*, int); . 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*); . 156a static void atasleep(Controller*, int); . 153c static void atafeature(Drive*, uchar); . 151c static long ataxfer(Drive*, Partition*, int, long, long, uchar*); . 146,148c static QLock ataprobelock; static int ataprobedone; 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, }; static int defirq[NCtlr] = { 14, 15, 0, 0, }; . 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; uchar resetok; . 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= 6000, /* 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, Ctur= 0x00, Creqsense= 0x03, Ccapacity= 0x25, Cread2= 0x28, . 50,51d 48d 44,46c Cident2= 0xFE, /* pseudo command for post Cident interrupt */ Cfeature= 0xEF, . 42a Cedd= 0x90, /* execute device diagnostics */ . 40c Cfirst= 0xFF, /* pseudo command for initialisation */ . 38a Pctrl= 0x206, /* device control, alternate status */ nIEN= (1<<1), Srst= (1<<2), . 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 XPRINT if(0)print #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 < 872180801/devata.c} if(~ dc8cefd440676 $sum(1)^$sum(2)) echo if not{ echo 872180801/devata.c checksum error creating updated file exit checksum } target=872180801/devi82365.c echo -n '872180801/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 872180801/devi82365.c ed 872180801/devi82365.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devi82365.c' 1303c static void . 1230c static void . 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 < 872180801/devi82365.c} if(~ b4c2629f24495 $sum(1)^$sum(2)) echo if not{ echo 872180801/devi82365.c checksum error creating updated file exit checksum } target=872180801/devincon.c echo -n '872180801/devincon.c: ' if(! test -f $srcdir/devincon.c || ! test -r $srcdir/devincon.c){ echo $srcdir/devincon.c unreadable exit unreadable } sum=`{sum < $srcdir/devincon.c} if(! ~ 7398783f19444 $sum(1)^$sum(2)){ echo $srcdir/devincon.c is not the original distribution file exit original } cp $srcdir/devincon.c 872180801/devincon.c ed 872180801/devincon.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM devincon.c' 744c static void . wq //GO.SYSIN DD VADIM devincon.c sum=`{sum < 872180801/devincon.c} if(~ 2faf92bf19451 $sum(1)^$sum(2)) echo if not{ echo 872180801/devincon.c checksum error creating updated file exit checksum } target=872180801/devsbcd.c echo -n '872180801/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 872180801/devsbcd.c ed 872180801/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 < 872180801/devsbcd.c} if(~ c107431113428 $sum(1)^$sum(2)) echo if not{ echo 872180801/devsbcd.c checksum error creating updated file exit checksum } target=872180801/devvga.c echo -n '872180801/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 872180801/devvga.c ed 872180801/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<= 8) gscreen.r.max = Pt(x, y); for(; (1< (footprint)/(vgascreen.width*BY2WD)) vgamaxy = (footprint)/(vgascreen.width*BY2WD); . 504c static void . 311,313c /* grab new space */ if(align == 0){ if(footprint >= size) return; } else { int s, e; s = screenmem & ~KZERO; e = s + footprint; s = ROUND(s, align); if(e >= s + size) return; } mem = getspace(size, align); if(mem == 0) error("not enough free address space"); screenmem = mem; vgascreen.base = (void*)mem; footprint = size; vgascreen.r.max.y = (footprint)/(vgascreen.width*BY2WD); for(n = 0; n < 31; n++) if((1<= footprint) break; footshift = n; . 309d 294,307c /* * See if it fits in the usual place. If some linear * space has already been allocated then this will drop it on * the floor and subsequent requests for something that * doesn't fit will allocate again. This shouldn't be a * problem as it's not a 'normal' sequence and, anyway, there * are probably hundreds of megabytes of space. */ if(size <= Footprint){ screenmem = SCREENMEM; if(size == 0){ footprint = Footprint; footshift = Footshift; } else { footprint = size; 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; . 292a size = strtoul(field[1], 0, 0); if(n < 3) align = 0; else align = strtoul(field[2], 0, 0); . 288,291c cursoroff(1); setscreen(x, y, z); cursoron(1); return; } else if(strcmp(field[0], "linear") == 0){ if(n < 2) . 284,285c if(parsevgasize(field[1], &x, &y, &z, &interlaced[0])) . 246c n = getfields(arg, field, 3, " \t\n"); if(n < 2) . 241,242c int n, x, y, z; char *field[3]; ulong mem, size, align; . 237a static int parsevgasize(char *p, int *x, int *y, int *z, char *i) { *x = strtol(p, &p, 0); if(*x == 0 || *x > 2048) return -1; if(*p) p++; *y = strtol(p, &p, 0); if(*y == 0 || *y > 1280) return -1; if(*p) p++; switch(strtol(p, &p, 0)){ case 8: *z = 3; break; case 4: *z = 2; break; case 2: *z = 1; break; case 1: *z = 0; break; default: return -1; } if(i){ if(*p == 'i') *i = 'i'; else if(*p) return -1; *i = 0; } return 0; } . 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' 37a vgargb524 . 35a vgact65540 . 34a vgaark2000pv . 31c ether509 pci . 20c scsi S scsi adaptec ultrastor dpt . wq //GO.SYSIN DD VADIM dos sum=`{sum < 872180801/dos} if(~ 28087c86605 $sum(1)^$sum(2)) echo if not{ echo 872180801/dos checksum error creating updated file exit checksum } target=872180801/ether.h echo -n '872180801/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 872180801/ether.h ed 872180801/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 < 872180801/ether.h} if(~ afcd2b694506 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether.h checksum error creating updated file exit checksum } target=872180801/ether2000.c echo -n '872180801/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 872180801/ether2000.c ed 872180801/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 < 872180801/ether2000.c} if(~ ccd8327d3036 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether2000.c checksum error creating updated file exit checksum } target=872180801/ether509.c echo -n '872180801/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 872180801/ether509.c ed 872180801/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 < 872180801/ether509.c} if(~ fdde614816590 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether509.c checksum error creating updated file exit checksum } target=872180801/ether589.c echo -n '872180801/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 872180801/ether589.c ed 872180801/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 < 872180801/ether589.c} if(~ a7490f5e1591 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether589.c checksum error creating updated file exit checksum } target=872180801/ether8003.c echo -n '872180801/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 872180801/ether8003.c ed 872180801/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 < 872180801/ether8003.c} if(~ af22b0577567 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether8003.c checksum error creating updated file exit checksum } target=872180801/ether8390.c echo -n '872180801/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 872180801/ether8390.c ed 872180801/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 < 872180801/ether8390.c} if(~ 0030f5a817187 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether8390.c checksum error creating updated file exit checksum } target=872180801/fns.h echo -n '872180801/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 872180801/fns.h ed 872180801/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 < 872180801/fns.h} if(~ fed86b842960 $sum(1)^$sum(2)) echo if not{ echo 872180801/fns.h checksum error creating updated file exit checksum } target=872180801/io.h echo -n '872180801/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 872180801/io.h ed 872180801/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 < 872180801/io.h} if(~ c775b7f82689 $sum(1)^$sum(2)) echo if not{ echo 872180801/io.h checksum error creating updated file exit checksum } target=872180801/kbd.c echo -n '872180801/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 872180801/kbd.c ed 872180801/kbd.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM kbd.c' 652c static void . 518c static void . wq //GO.SYSIN DD VADIM kbd.c sum=`{sum < 872180801/kbd.c} if(~ 0841e8e511851 $sum(1)^$sum(2)) echo if not{ echo 872180801/kbd.c checksum error creating updated file exit checksum } target=872180801/main.c echo -n '872180801/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 872180801/main.c ed 872180801/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,343c if(*line[j] == '#') continue; . 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 < 872180801/mem.h} if(~ 24aa9d983642 $sum(1)^$sum(2)) echo if not{ echo 872180801/mem.h checksum error creating updated file exit checksum } target=872180801/mkfile echo -n '872180801/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 872180801/mkfile ed 872180801/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 < 872180801/mkfile} if(~ 1e55f1761297 $sum(1)^$sum(2)) echo if not{ echo 872180801/mkfile checksum error creating updated file exit checksum } target=872180801/mmu.c echo -n '872180801/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 872180801/mmu.c ed 872180801/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 < 872180801/mmu.c} if(~ 520ff7088907 $sum(1)^$sum(2)) echo if not{ echo 872180801/mmu.c checksum error creating updated file exit checksum } target=872180801/pc echo -n '872180801/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 872180801/pc ed 872180801/pc >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pc' 40a vgargb524 . 38a vgact65540 . 37a ether3210 ether8390 ether4100 ether8390 ether8003 ether8390 vgaark2000pv . 34,36c ether509 pci . wq //GO.SYSIN DD VADIM pc sum=`{sum < 872180801/pc} if(~ a6d33065621 $sum(1)^$sum(2)) echo if not{ echo 872180801/pc checksum error creating updated file exit checksum } target=872180801/pcdisk echo -n '872180801/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 872180801/pcdisk ed 872180801/pcdisk >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pcdisk' 40a vgargb524 . 38a vgact65540 . 37a vgaark2000pv . 33c ether509 pci . 26a sbcd m . 23c scsi S scsi adaptec ultrastor dpt . wq //GO.SYSIN DD VADIM pcdisk sum=`{sum < 872180801/pcdisk} if(~ d36c5d16636 $sum(1)^$sum(2)) echo if not{ echo 872180801/pcdisk checksum error creating updated file exit checksum } target=872180801/scsi.c echo -n '872180801/scsi.c: ' if(! test -f $srcdir/scsi.c || ! test -r $srcdir/scsi.c){ echo $srcdir/scsi.c unreadable exit unreadable } sum=`{sum < $srcdir/scsi.c} if(! ~ 82e753811029 $sum(1)^$sum(2)){ echo $srcdir/scsi.c is not the original distribution file exit original } cp $srcdir/scsi.c 872180801/scsi.c ed 872180801/scsi.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM scsi.c' 69c if(exec = ultra14freset()) return; exec = dpt3334reset(); . 52a extern int (*dpt3334reset(void))(Scsi*, int); . 47,48c if(salloc.n <= 0){ free(b->virt); free(b); }else{ lock(&salloc.llock); b->next = salloc.avail; salloc.avail = b; unlock(&salloc.llock); if(salloc.br.p) wakeup(&salloc.br); } . 38,40c if(salloc.n <= 0){ b = smalloc(sizeof(*b)); b->virt = smalloc(bufdatasize); b->phys = (void *)(PADDR(b->virt)); }else for(;;){ lock(&salloc.llock); if(b = salloc.avail){ /* assign = */ salloc.avail = b->next; unlock(&salloc.llock); break; }else{ unlock(&salloc.llock); qlock(&salloc.rlock); if(waserror()){ qunlock(&salloc.rlock); continue; } sleep(&salloc.br, isavail, &salloc); poperror(); qunlock(&salloc.rlock); } } . 30a if(conf.topofmem > 16*MB){ for(salloc.n=0; salloc.n<4; salloc.n++){ b = xalloc(sizeof(*b)); b->virt = xalloc(bufdatasize); b->phys = (void *)(PADDR(b->virt)); b->next = salloc.avail; salloc.avail = b; #ifdef DEBUG print("scsibuf: 0x%.6lux\n", b->phys); #endif if((ulong)b->phys > 16*MB) panic("scsibuf"); } } . 29a Scsibuf *b; . 14a extern Conf conf; typedef struct Salloc Salloc; struct Salloc { int n; Lock llock; QLock rlock; Rendez br; Scsibuf *avail; }; static Salloc salloc; static int isavail(void *p) { return ((Salloc *)p)->avail != 0; } . 13a int scsidebugs[8] = {0}; int scsiownid = 7; . 11,12d wq //GO.SYSIN DD VADIM scsi.c sum=`{sum < 872180801/scsi.c} if(~ 0e2d08812239 $sum(1)^$sum(2)) echo if not{ echo 872180801/scsi.c checksum error creating updated file exit checksum } target=872180801/trap.c echo -n '872180801/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 872180801/trap.c ed 872180801/trap.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM trap.c' 426a m->syscall++; . 384c if(i == 8){ . 316a checkuser: . 281c goto checkuser; . 278a spllo(); . 272,274d 262a m->intr++; . wq //GO.SYSIN DD VADIM trap.c sum=`{sum < 872180801/trap.c} if(~ 3d4d89d014684 $sum(1)^$sum(2)) echo if not{ echo 872180801/trap.c checksum error creating updated file exit checksum } target=872180801/ultrastor.c echo -n '872180801/ultrastor.c: ' if(! test -f $srcdir/ultrastor.c || ! test -r $srcdir/ultrastor.c){ echo $srcdir/ultrastor.c unreadable exit unreadable } sum=`{sum < $srcdir/ultrastor.c} if(! ~ 8047458611748 $sum(1)^$sum(2)){ echo $srcdir/ultrastor.c is not the original distribution file exit original } cp $srcdir/ultrastor.c 872180801/ultrastor.c ed 872180801/ultrastor.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM ultrastor.c' 131,132c /* * int scsidebugs[8] = {0}; * int scsiownid = 7; */ extern int scsidebugs[8]; extern int scsiownid; . wq //GO.SYSIN DD VADIM ultrastor.c sum=`{sum < 872180801/ultrastor.c} if(~ fc407d6b11810 $sum(1)^$sum(2)) echo if not{ echo 872180801/ultrastor.c checksum error creating updated file exit checksum } target=872180801/vga.h echo -n '872180801/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 872180801/vga.h ed 872180801/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 < 872180801/vga.h} if(~ feeb88e41530 $sum(1)^$sum(2)) echo if not{ echo 872180801/vga.h checksum error creating updated file exit checksum } target=872180801/vgatvp3020.c echo -n '872180801/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 872180801/vgatvp3020.c ed 872180801/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 < 872180801/vgatvp3020.c} if(~ d9a694235422 $sum(1)^$sum(2)) echo if not{ echo 872180801/vgatvp3020.c checksum error creating updated file exit checksum } target=872180801/devatapi.c echo -n '872180801/devatapi.c (new): ' cat > 872180801/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 < 872180801/devatapi.c} if(~ e7f58a5017745 $sum(1)^$sum(2)) echo if not{ echo 872180801/devatapi.c checksum error extracting new file exit checksum } target=872180801/dpt.c echo -n '872180801/dpt.c (new): ' cat > 872180801/dpt.c >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * DPT 3334 SCSI Host Adapter. * Version 0.9 - Sat Apr 5, 1997 - John L. Chmielewski, jlc@att.com * Needs work: * handle multiple controllers; */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #define ETA_SIG (((long) 'E') | (((long) 'A') << 8) |\ (((long) 'T') << 16) | (((long) 'A') << 24)) enum { Nctl = 1, /* Max # of Controllers */ CtrlID = 7, /* Default Controller ID */ NTarget = 16, /* Max targets/controller-chan */ Timeout = 10, /* Timeout in seconds */ SenLen = 0xFF, /* Maximum Sense Data Length */ PCIvid = 0x1044, /* PCI Vendor ID: DPT */ PCIdid = 0xA400, /* PCI Device ID: DPT */ }; enum { /* Eata Register Commands */ ReadCfg = 0xFD, /* Read Configuration Data, DMA */ SendCP = 0xFF, /* Execute Command, DMA */ Reset = 0xF9, /* Reset Controller */ }; enum { /* Eata Register Sets - PCI */ Cmd = 0x17, /* Command Register (write) */ CP3 = 0x15, /* CP Address (MSB) (write) */ CP2 = 0x14, /* CP Address (MSB -1) (write) */ CP1 = 0x13, /* CP Address (MSB-2) (write) */ CP0 = 0x12, /* CP Address (LSB) (write) */ ASR = 0X18, /* Aux Status Register (read) */ SR = 0x17, /* Status Register (read) */ DR = 0x10, /* 16 bit Data Register (read) */ }; enum { /* Eata Register Sets Bits */ /* Status Register */ ERROR = 0x01, /* Command ended in error */ DRQ = 0x08, /* Drive is Ready */ SC = 0x10, /* Seek Complete */ RDY = 0x40, /* Active data request */ BSY = 0x80, /* Controller busy - clear IRQ */ /* Aux Status Register */ ABSY = 0x01, /* Controller busy */ IRQ = 0x02, /* Drive interrupt asserted */ }; /* * DPT DMA Status Packet * Big Endian Format */ typedef struct DPTstat DPTstat; struct DPTstat { uchar info; /* Bits defined */ uchar sbs; /* SCSI Bus Status */ uchar reserved0[2]; ulong irl; /* Bytes Not Transfered */ ulong va; /* Virtual Address of CP */ uchar idmsg; uchar quemsg; uchar tagmsg; uchar msg[9]; }; enum { /* Status Packet bits */ /* info byte bits */ CS = 0x7F, /* Controller Status */ EOC = 0x80, /* End of Command - not safe */ }; /* * EATA Command Packet * */ typedef struct EATAcp EATAcp; struct EATAcp { uchar control; /* Bits defined */ uchar ReqSenLen; /* AutoRequestSense Data length */ uchar reserved1[3]; uchar FWNest; /* Firmware Nested Byte for RAID */ uchar PhsUnit; /* Physical Byte for RAID */ uchar device; /* Bits defined */ uchar msg[4]; /* Identify and Disconnect Message */ uchar CDB[12]; /* Total SCSI CDB */ ulong DTL; /* Byte Swapped Data Length In Bytes */ ulong va; /* Command Packet Virtual Address */ ulong dataDMA; /* Byte Swapped Data Physical Address */ ulong statDMA; /* Byte Swapped Status Packet Physical */ ulong reqDMA; /* Byte Swapped AutoRequestSense Phys */ }; enum { /* Command Packet bits */ /* control byte bits */ Sreset = 0x01, /* Issue A SCSI Bus Reset */ Init = 0x02, /* ReInitialize The Controller */ ReqSen = 0x04, /* Do Auto Request Sense */ SG = 0x08, /* Data Pointer To S.G. List */ Quick = 0x10, /* Quick PIOin, DMA in/out */ Interpret = 0x20, /* CDB Interpreted By Controller */ DataOut = 0x40, /* Data Out Phase With Command */ DataIn = 0x80, /* Data In Phase With Command */ /* device byte bits */ id = 0x1F, /* SCSI Target ID */ Channel = 0xE0, /* HBA Channel Number */ /* Message byte 0 bits */ MsgLun = 0x07, /* Message Lun */ MsgLuntar = 0x20, /* Target Routine */ MsgDisPri = 0x40, /* Disconnect Reconnect */ MsgIdent = 0x80, /* Indentify */ }; /* * ReadConfig Data Structure - This Structure Contains The EATA Configuration * Big Endian Format */ typedef struct DPTcfg DPTcfg; struct DPTcfg { /* Extra bytes returned form a SCSI Inquiry Command */ uchar DevType; uchar PageCode; uchar reserved2; uchar ConfigLength; /* Length In Bytes After This Field */ ulong EATAsig; /* EATA Signature Bytes */ uchar EATAver; /* EATA Version Number */ uchar byte9; /* Bits defined */ ushort PadLen; /* Pad Bytes For PIO Commands */ uchar reserved3; uchar Chan2; /* Channel 2 SCSI ID */ uchar Chan1; /* Channel 1 SCSI ID */ uchar Chan0; /* Channel 0 SCSI ID */ ulong CPlength; /* Command Packet Length */ ulong SPlength; /* Status Packet Length */ ushort QueueSize; /* Controller Queue Depth */ uchar reserved4[2]; ushort SG_Size; /* Maximum Scatter Gather List Size */ uchar byte30; /* Bits defined */ uchar IRQ; /* IRQ address */ uchar byte32; /* Bits defined */ uchar byte33; /* Bits defined */ uchar MaxLUN; /* Maximum SCSI LUN Supported */ uchar byte35; /* Bits defined */ uchar RaidNum; /* Raid Host Adapter Number */ }; enum { /* Read Config Bits */ /* Byte 9 */ OverLapCmds = 0x01, /* Overlapped Cmds Supported */ TargetMode = 0x02, /* SCSI Target Mode Supported */ TrunNotNec = 0x04, /* Truncate Command Not Supported */ MoreSupported = 0x08, /* More Command Supported */ MAsupported = 0x10, /* DMA Mode Supported */ DMAvalid = 0x20, /* DMA Channel Field Is Valid. */ ATAdevice = 0x40, /* This Is An ATA Device */ HBAvalid = 0x80, /* HBA field Is Valid */ /* Byte 30 */ IRQn = 0x0F, /* IRQ Number */ IRQt = 0x10, /* IRQ Trigger: 0 = Edge, 1 = Level */ Secondary = 0x20, /* Controller Not At Address 0x170 */ DMAchan = 0xD0, /* DMA Channel Index For ISA */ /* Byte 32 */ Disable = 0x01, /* ISA I/O Address Disabled */ ForceAddr = 0x02, /* PCI Forced To An EISA/ISA Addr */ SG64K = 0x04, /* 64K of SG space */ SGUAE = 0x08, /* Supports unaligned SG Table */ /* Byte 33 */ MaxID = 0x1F, /* Maximun SCSI Target ID Supported */ MaxChan = 0xE0, /* Maximun Channel Number Supported */ /* Byte 35 */ AutoTerm = 0x08, /* Support auto term (low byte) */ PCIM1 = 0x10, /* PCI M1 chipset */ RIDQ = 0x20, /* Raid ID may be questionable */ PCIbus = 0x40, /* PCI Adapter Flag */ EISAbus = 0x80, /* EISA Adapter Flag */ }; typedef struct Target Target; struct Target { QLock; Rendez; int done; int senval; /* Sense data valid */ uchar sense[SenLen]; /* Sense data */ EATAcp; /* Command Packet */ uchar ctlrStatus; uchar scsiStatus; }; typedef struct Ctlr Ctlr; struct Ctlr { Lock; int port; /* base port */ int channel; /* Controller Channel Number */ DPTcfg; /* Controller Configuration */ DPTstat; /* Status Packet */ PCIcfg; /* PCI info */ Target target[NTarget]; /* CCP's in use */ }; static Ctlr ctlr[Nctl]; static long LongEndCvt(long x) { long t; char *p = (char *) &t; *p++ = (x>>24) & 0xFF; *p++ = (x>>16) & 0xFF; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } static short ShortEndCvt(short x) { short t; char *p = (char *) &t; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } #ifdef DEBUG static void printinfo(Ctlr *cp) { print("\nVendor ID: 0x%x\tDevice ID: 0x%x\tBase Address: 0x%x\n", cp->vid, cp->did, cp->baseaddr[0] & ~0x01); print("Signiture: %x\tIRQ: %d\t\t\tDMA: %d\n", LongEndCvt(cp->EATAsig), cp->byte30 & IRQn, cp->byte30 & DMAchan); print("CtlrChan0ID: %d\t\tCtlrChan1ID: %d\t\tCtlrChan2ID: %d\n", cp->Chan0, cp->Chan1, cp->Chan2); print("MaxChanID: %d\t\tMaxChanNum: %d\t\tInterrupt Vector: %d\n\n", cp->byte33 & MaxID, cp->byte33 & MaxChan, Int0vec); } #endif static void dptcmd(int port, ulong ccpaddr) { ulong paddr; paddr = PADDR(ccpaddr); outb(port+CP0, paddr & 0xFF); outb(port+CP1, (paddr>>8) & 0xFF); outb(port+CP2, (paddr>>16) & 0xFF); outb(port+CP3, (paddr>>24) & 0xFF); outb(port+Cmd, SendCP); } static int done(void *arg) { return ((Target *)arg)->done; } static int dptio(int bus, Scsi *p, int rw) { Ctlr *cp = &ctlr[bus]; Target *tp = &cp->target[p->target]; EATAcp *ccp = tp; ulong len; ushort status; int x; qlock(tp); if (waserror()) { qunlock(tp); nexterror(); } /* * If this is a request-sense and there is valid sense data * from the loas command, return it immediately. */ if (p->cmd.base[0] == ScsiExtsens && tp->senval) { len = tp->ReqSenLen; memmove(p->data.ptr, tp->sense, len); p->data.ptr += len; tp->senval = 0; qunlock(tp); poperror(); return 0x6000; } /* * Fill in the ccp */ memset(ccp, 0, sizeof(EATAcp)); ccp->control |= (rw == ScsiIn ? DataIn : DataOut) | ReqSen; ccp->device = (cp->channel<<5) | (p->target & id); ccp->ReqSenLen = SenLen; ccp->dataDMA = LongEndCvt(PADDR(p->data.base)); ccp->DTL = LongEndCvt(p->data.lim - p->data.base); ccp->statDMA = LongEndCvt(PADDR(&cp->DPTstat)); ccp->reqDMA = LongEndCvt(PADDR(tp->sense)); ccp->ReqSenLen = SenLen; ccp->va = (ulong) tp; ccp->msg[0] |= (p->lun & MsgLun) | MsgDisPri | MsgIdent; len = p->cmd.lim - p->cmd.base; memmove(ccp->CDB, p->cmd.base, len); /* * Send the request */ x = splhi(); tp->done = 0; dptcmd(cp->port, (ulong) ccp); splx(x); /* * Wait for the request to complete. */ tsleep(tp, done, tp, 60*5*1000); if (tp->done == 0) print("dpt%d: timeout cmd=#%2.2ux\n", p->target, p->cmd.base[0]); switch (tp->ctlrStatus) { case 0x00: /* no error */ status = 0x6000 | tp->scsiStatus; p->data.ptr = p->data.lim; /* assume no residue */ break; case 0x01: /* selection timed out */ status = 0x20; break; default: /* controller error */ status = 0x1000 | tp->ctlrStatus; break; } qunlock(tp); poperror(); return status; } static int dptexec(Scsi *p, int rw) { Ctlr *cp = &ctlr[0]; if (cp->port == 0) error(Enodev); if (p->target == cp->Chan0) return 0x6002; /* controller ID */ return p->status = dptio(0, p, rw); } static void interrupt(Ureg *ur, void *a) { Ctlr *cp = &ctlr[0]; Target *tp; USED(ur, a); if (active.machs > 1) lock(cp); /* * Check the interrupt. */ if ((cp->info & EOC) == 0) return; /* * Get ccb address, status information, and set flags. */ tp = (Target *) cp->va; if (tp == 0) panic("DPT: no target for ccb #%lux\n", tp); tp->ctlrStatus = cp->info & CS; tp->scsiStatus = cp->sbs; cp->info &= ~EOC; tp->done = 1; if (tp->scsiStatus == 0x02) tp->senval = 1; /* indicate command returned sense data */ wakeup(tp); inb(cp->port+SR); /* clear the interrupt */ if (active.machs > 1) unlock(cp); } static ISAConf dpt3334 = { "dpt3334", 0, 0, 0, 0, }; /* * Locate the SCSI controller PCI cards. */ static Ctlr* locate(void) { Ctlr *cp = &ctlr[0]; static int devno; int i; for(i = 0; i < Nctl; ++i) { cp = &ctlr[i]; memset(cp, 0, sizeof(Ctlr)); cp->vid = PCIvid; cp->did = PCIdid; if((devno = pcimatch(0, devno, cp)) == -1) break; /* no boards found */ cp->port = cp->baseaddr[0] & ~0x01; dpt3334.port = cp->port; dpt3334.irq = cp->irq; } if (cp->port) return &ctlr[0]; /* always return the 1st board found */ return 0; } int (* dpt3334reset(void))(Scsi*, int) { Ctlr *cp; EATAcp *ccp; int x; /* * Is the adapter configured? */ if (isaconfig("scsi", 0, &dpt3334) == 0) return 0; /* * Assume one controller. */ if ((cp = locate()) == 0) return 0; /* * Do a Read Vital Data Page SCSI command * to get the configuration information * instead of using a Read Config Command. * This will cause an interrupt, but which * one isn't known yet. */ ccp = &cp->target[CtrlID].EATAcp; ccp->control |= (Interpret | DataIn | ReqSen); ccp->dataDMA = LongEndCvt(PADDR(&cp->DPTcfg)); ccp->DTL = LongEndCvt(sizeof(DPTcfg)); ccp->statDMA = LongEndCvt(PADDR(&cp->DPTstat)); ccp->va = (ulong) &cp->target[CtrlID]; ccp->msg[0] |= MsgIdent; ccp->CDB[0] = ScsiInquiry; /* SCSI Command */ ccp->CDB[1] |= 0x01; /* SCSI Extent */ ccp->CDB[2] = 0xC1; /* SCSI Page */ ccp->CDB[7] = sizeof(DPTcfg); /* Data Length */ x = splhi(); dptcmd(cp->port, (ulong) ccp); while ((inb(cp->port+ASR)&IRQ) == 0) ; inb(cp->port+SR); /* Clear interrupt */ splx(x); setvec(Int0vec+(cp->byte30 & IRQn), interrupt, cp); outb(cp->port+Cmd, Reset); /* Reset Controller and SCSI Bus */ delay(5000); #ifdef DEBUG printinfo(cp); #endif return dptexec; } //GO.SYSIN DD VADIM . sum=`{sum < 872180801/dpt.c} if(~ 9103c7ef12113 $sum(1)^$sum(2)) echo if not{ echo 872180801/dpt.c checksum error extracting new file exit checksum } target=872180801/dpt.c.old echo -n '872180801/dpt.c.old (new): ' cat > 872180801/dpt.c.old >[2]/dev/null <<'//GO.SYSIN DD VADIM .' /* * DPT 3334 SCSI Host Adapter. * Version 0.9 - Sat Mar 22, 1997 - John L. Chmielewski, jlc@attmail.com * Needs work: * handle multiple controllers; */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #define ETA_SIG (((long) 'E') | (((long) 'A') << 8) |\ (((long) 'T') << 16) | (((long) 'A') << 24)) enum { Nctl = 1, /* Max # of Controllers */ CtrlID = 7, /* Default Controller ID */ NTarget = 16, /* Max targets/controller-chan */ Timeout = 10, /* Timeout in seconds */ SenLen = 0xFF, /* Maximum Sense Data Length */ PCIvid = 0x1044, /* PCI Vendor ID: DPT */ PCIdid = 0xA400, /* PCI Device ID: DPT */ }; enum { /* Eata Register Commands */ ReadCfg = 0xFD, /* Read Configuration Data, DMA */ SendCP = 0xFF, /* Execute Command, DMA */ Reset = 0xF9, /* Reset Controller */ }; enum { /* Eata Register Sets - PCI */ Cmd = 0x17, /* Command Register (write) */ CP3 = 0x15, /* CP Address (MSB) (write) */ CP2 = 0x14, /* CP Address (MSB -1) (write) */ CP1 = 0x13, /* CP Address (MSB-2) (write) */ CP0 = 0x12, /* CP Address (LSB) (write) */ ASR = 0X18, /* Aux Status Register (read) */ SR = 0x17, /* Status Register (read) */ DR = 0x10, /* 16 bit Data Register (read) */ }; enum { /* Eata Register Sets Bits */ /* Status Register */ ERROR = 0x01, /* Command ended in error */ DRQ = 0x08, /* Drive is Ready */ SC = 0x10, /* Seek Complete */ RDY = 0x40, /* Active data request */ BSY = 0x80, /* Controller busy - clear IRQ */ /* Aux Status Register */ ABSY = 0x01, /* Controller busy */ IRQ = 0x02, /* Drive interrupt asserted */ }; /* * DPT DMA Status Packet * Big Endian Format */ typedef struct DPTstat DPTstat; struct DPTstat { uchar status; /* Bits defined */ uchar sbs; /* SCSI Bus Status */ uchar reserved0[2]; ulong irl; /* Bytes Not Transfered */ ulong va; /* Virtual Address of CP */ uchar idmsg; uchar quemsg; uchar tagmsg; uchar msg[9]; }; enum { /* Status Packet bits */ /* status byte bits */ CS = 0x7F, /* Controller Status */ EOC = 0x80, /* End of Command - not safe */ }; /* * EATA Command Packet * */ typedef struct EATAcp EATAcp; struct EATAcp { uchar control; /* Bits defined */ uchar ReqSenLen; /* AutoRequestSense Data length */ uchar reserved1[3]; uchar FWNest; /* Firmware Nested Byte for RAID */ uchar PhsUnit; /* Physical Byte for RAID */ uchar device; /* Bits defined */ uchar msg[4]; /* Identify and Disconnect Message */ uchar CDB[12]; /* Total SCSI CDB */ ulong DTL; /* Byte Swapped Data Length In Bytes */ ulong va; /* Command Packet Virtual Address */ ulong dataDMA; /* Byte Swapped Data Physical Address */ ulong statDMA; /* Byte Swapped Status Packet Physical */ ulong reqDMA; /* Byte Swapped AutoRequestSense Phys */ }; enum { /* Command Packet bits */ /* control byte bits */ Sreset = 0x01, /* Issue A SCSI Bus Reset */ Init = 0x02, /* ReInitialize The Controller */ ReqSen = 0x04, /* Do Auto Request Sense */ SG = 0x08, /* Data Pointer To S.G. List */ Quick = 0x10, /* Quick PIOin, DMA in/out */ Interpret = 0x20, /* CDB Interpreted By Controller */ DataOut = 0x40, /* Data Out Phase With Command */ DataIn = 0x80, /* Data In Phase With Command */ /* device byte bits */ id = 0x1F, /* SCSI Target ID */ Channel = 0xE0, /* HBA Channel Number */ /* Message byte 0 bits */ MsgLun = 0x07, /* Message Lun */ MsgLuntar = 0x20, /* Target Routine */ MsgDisPri = 0x40, /* Disconnect Reconnect */ MsgIdent = 0x80, /* Indentify */ }; /* * ReadConfig Data Structure - This Structure Contains The EATA Configuration * Big Endian Format */ typedef struct DPTcfg DPTcfg; struct DPTcfg { /* Extra bytes returned form a SCSI Inquiry Command */ uchar DevType; uchar PageCode; uchar reserved2; uchar ConfigLength; /* Length In Bytes After This Field */ ulong EATAsig; /* EATA Signature Bytes */ uchar EATAver; /* EATA Version Number */ uchar byte9; /* Bits defined */ ushort PadLen; /* Pad Bytes For PIO Commands */ uchar reserved3; uchar Chan2; /* Channel 2 SCSI ID */ uchar Chan1; /* Channel 1 SCSI ID */ uchar Chan0; /* Channel 0 SCSI ID */ ulong CPlength; /* Command Packet Length */ ulong SPlength; /* Status Packet Length */ ushort QueueSize; /* Controller Queue Depth */ uchar reserved4[2]; ushort SG_Size; /* Maximum Scatter Gather List Size */ uchar byte30; /* Bits defined */ uchar IRQ; /* IRQ address */ uchar byte32; /* Bits defined */ uchar byte33; /* Bits defined */ uchar MaxLUN; /* Maximum SCSI LUN Supported */ uchar byte35; /* Bits defined */ uchar RaidNum; /* Raid Host Adapter Number */ }; enum { /* Read Config Bits */ /* Byte 9 */ OverLapCmds = 0x01, /* Overlapped Cmds Supported */ TargetMode = 0x02, /* SCSI Target Mode Supported */ TrunNotNec = 0x04, /* Truncate Command Not Supported */ MoreSupported = 0x08, /* More Command Supported */ MAsupported = 0x10, /* DMA Mode Supported */ DMAvalid = 0x20, /* DMA Channel Field Is Valid. */ ATAdevice = 0x40, /* This Is An ATA Device */ HBAvalid = 0x80, /* HBA field Is Valid */ /* Byte 30 */ IRQn = 0x0F, /* IRQ Number */ IRQt = 0x10, /* IRQ Trigger: 0 = Edge, 1 = Level */ Secondary = 0x20, /* Controller Not At Address 0x170 */ DMAchan = 0xD0, /* DMA Channel Index For ISA */ /* Byte 32 */ Disable = 0x01, /* ISA I/O Address Disabled */ ForceAddr = 0x02, /* PCI Forced To An EISA/ISA Addr */ SG64K = 0x04, /* 64K of SG space */ SGUAE = 0x08, /* Supports unaligned SG Table */ /* Byte 33 */ MaxID = 0x1F, /* Maximun SCSI Target ID Supported */ MaxChan = 0xE0, /* Maximun Channel Number Supported */ /* Byte 35 */ AutoTerm = 0x08, /* Support auto term (low byte) */ PCIM1 = 0x10, /* PCI M1 chipset */ RIDQ = 0x20, /* Raid ID may be questionable */ PCIbus = 0x40, /* PCI Adapter Flag */ EISAbus = 0x80, /* EISA Adapter Flag */ }; typedef struct Target Target; struct Target { QLock; Rendez; int done; int senval; /* Sense data valid */ uchar sense[SenLen]; /* Sense data */ EATAcp eatacp; /* Command Packet */ uchar ctlrStatus; uchar scsiStatus; }; typedef struct Ctlr Ctlr; struct Ctlr { Lock; int port; /* base port */ int channel; /* Controller Channel Number */ DPTcfg dptcfg; /* Controller Configuration */ DPTstat dptsp; /* Status Packet */ PCIcfg pcicfg; /* PCI info */ Target target[NTarget]; /* CCP's in use */ }; static Ctlr ctlr[Nctl]; static long LongEndCvt(long x) { long t; char *p = (char *) &t; *p++ = (x>>24) & 0xFF; *p++ = (x>>16) & 0xFF; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } static short ShortEndCvt(short x) { short t; char *p = (char *) &t; *p++ = (x>>8) & 0xFF; *p = x & 0xFF; return t; } #ifdef DEBUG static void pciinfo(PCIcfg *pcicfg) { print("Vendor ID: 0x%x\tDevice ID: 0x%x\tCommand: 0x%.4x\n", pcicfg->vid, pcicfg->did, pcicfg->command); print("Status: 0x%.4x\t\tRevision ID: 0x%.2x\tProg: 0x%.2x\n", pcicfg->status, pcicfg->rid, pcicfg->loclass); print("Sub Class: 0x%.2x\t\tBase Class: 0x%.2x\tCache Line Size: 0x%.2x\n", pcicfg->subclass, pcicfg->baseclass, pcicfg->clsize); print("Latency Timer: 0x%.2x\tHeader Type: 0x%.2x\tBIST: 0x%.2x\n", pcicfg->latency, pcicfg->header, pcicfg->bist); print("Base Address: 0x%x\tIRQ: %d\n\n", pcicfg->baseaddr[0] & ~0x01, pcicfg->irq); } static void dptinfo(Ctlr *cp) { struct DPTcfg *cfg = &cp->dptcfg; print("Signiture: %x\tIRQ: %d\t\t\tDMA: %d\n", LongEndCvt(cfg->EATAsig), cfg->byte30 & IRQn, cfg->byte30 & DMAchan); print("CtlrChan0ID: %d\t\tCtlrChan1ID: %d\t\tCtlrChan2ID: %d\n", cfg->Chan0, cfg->Chan1, cfg->Chan2); print("MaxChanID: %d\t\tMaxChanNum: %d\t\tInterrupt Vector: %d\n\n", cfg->byte33 & MaxID, cfg->byte33 & MaxChan, Int0vec); } #endif static void dptcmd(int port, ulong ccpaddr) { ulong paddr; paddr = PADDR(ccpaddr); outb(port+CP0, paddr & 0xFF); outb(port+CP1, (paddr>>8) & 0xFF); outb(port+CP2, (paddr>>16) & 0xFF); outb(port+CP3, (paddr>>24) & 0xFF); outb(port+Cmd, SendCP); } static int done(void *arg) { return ((Target *)arg)->done; } static int dptio(int bus, Scsi *p, int rw) { Ctlr *cp = &ctlr[bus]; Target *tp = &cp->target[p->target]; EATAcp *ccp = &tp->eatacp; ulong len; ushort status; int x; qlock(tp); if (waserror()) { qunlock(tp); nexterror(); } /* * If this is a request-sense and there is valid sense data * from the loas command, return it immediately. */ if (p->cmd.base[0] == ScsiExtsens && tp->senval) { len = tp->eatacp.ReqSenLen; memmove(p->data.ptr, tp->sense, len); p->data.ptr += len; tp->senval = 0; qunlock(tp); poperror(); return 0x6000; } /* * Fill in the ccp */ memset(ccp, 0, sizeof(EATAcp)); ccp->control |= (rw == ScsiIn ? DataIn : DataOut) | ReqSen; ccp->device = (cp->channel<<5) | (p->target & id); ccp->ReqSenLen = SenLen; ccp->dataDMA = LongEndCvt(PADDR(p->data.base)); ccp->DTL = LongEndCvt(p->data.lim - p->data.base); ccp->statDMA = LongEndCvt(PADDR(&cp->dptsp)); ccp->reqDMA = LongEndCvt(PADDR(tp->sense)); ccp->ReqSenLen = SenLen; ccp->va = (ulong) tp; ccp->msg[0] |= (p->lun & MsgLun) | MsgDisPri | MsgIdent; len = p->cmd.lim - p->cmd.base; memmove(ccp->CDB, p->cmd.base, len); /* * Send the request */ x = splhi(); tp->done = 0; dptcmd(cp->port, (ulong) ccp); splx(x); /* * Wait for the request to complete. */ tsleep(tp, done, tp, 60*5*1000); if (tp->done == 0) print("dpt%d: timeout cmd=#%2.2ux\n", p->target, p->cmd.base[0]); switch (tp->ctlrStatus) { case 0x00: /* no error */ status = 0x6000 | tp->scsiStatus; p->data.ptr = p->data.lim; /* assume no residue */ break; case 0x01: /* selection timed out */ status = 0x20; break; default: /* controller error */ status = 0x1000 | tp->ctlrStatus; break; } #ifdef DEBUG print("Target: %d\tSCSI Cmd: 0x%x\tStatus: 0x%x\n", p->target, p->cmd.base[0], status); #endif qunlock(tp); poperror(); return status; } static int dptexec(Scsi *p, int rw) { Ctlr *cp = &ctlr[0]; if (cp->port == 0) error(Enodev); if (p->target == cp->dptcfg.Chan0) return 0x6002; /* controller ID */ return p->status = dptio(0, p, rw); } static void interrupt(Ureg *ur, void *a) { Ctlr *cp = &ctlr[0]; Target *tp; USED(ur, a); if (active.machs > 1) lock(cp); /* * Check the interrupt. */ if ((cp->dptsp.status & EOC) == 0) return; /* * Get ccb address, status information, and set flags. */ tp = (Target *) cp->dptsp.va; if (tp == 0) panic("DPT: no target for ccb #%lux\n", tp); tp->ctlrStatus = cp->dptsp.status & CS; tp->scsiStatus = cp->dptsp.sbs; cp->dptsp.status &= ~EOC; tp->done = 1; if (tp->scsiStatus == 0x02) tp->senval = 1; /* indicate command returned sense data */ wakeup(tp); inb(cp->port+SR); /* clear the interrupt */ if (active.machs > 1) unlock(cp); } static ISAConf dpt3334 = { "dpt3334", 0, 0, 0, 0, }; /* * Locate the SCSI controller PCI cards. */ static Ctlr* locate(void) { Ctlr *cp = &ctlr[0]; static int devno; int i; for(i = 0; i < Nctl; ++i) { cp = &ctlr[i]; memset(cp, 0, sizeof(Ctlr)); cp->pcicfg.vid = PCIvid; cp->pcicfg.did = PCIdid; if((devno = pcimatch(0, devno, &cp->pcicfg)) == -1) break; /* no boards found */ cp->port = cp->pcicfg.baseaddr[0] & ~0x01; dpt3334.port = cp->port; dpt3334.irq = cp->pcicfg.irq; } if (cp->port) return &ctlr[0]; /* always return the 1st board found */ return 0; } int (* dpt3334reset(void))(Scsi*, int) { Ctlr *cp; EATAcp *ccp; int x; /* * Is the adapter configured? */ if (isaconfig("scsi", 0, &dpt3334) == 0) return 0; /* * Assume one controller. */ if ((cp = locate()) == 0) return 0; /* * Do a Read Vital Data Page SCSI command * to get the configuration information * instead of using a Read Config Command. * This will cause an interrupt, but which * one isn't known yet. */ ccp = &cp->target[CtrlID].eatacp; ccp->control |= (Interpret | DataIn | ReqSen); ccp->dataDMA = LongEndCvt(PADDR(&cp->dptcfg)); ccp->DTL = LongEndCvt(sizeof(DPTcfg)); ccp->statDMA = LongEndCvt(PADDR(&cp->dptsp)); ccp->va = (ulong) &cp->target[CtrlID]; ccp->msg[0] |= MsgIdent; ccp->CDB[0] = ScsiInquiry; /* SCSI Command */ ccp->CDB[1] |= 0x01; /* SCSI Extent */ ccp->CDB[2] = 0xC1; /* SCSI Page */ ccp->CDB[7] = sizeof(DPTcfg); /* Data Length */ x = splhi(); dptcmd(cp->port, (ulong) ccp); while ((inb(cp->port+ASR)&IRQ) == 0) ; inb(cp->port+SR); /* Clear interrupt */ splx(x); setvec(Int0vec+(cp->dptcfg.byte30 & IRQn), interrupt, cp); outb(cp->port+Cmd, Reset); /* Reset Controller and SCSI Bus */ delay(5000); #ifdef DEBUG pciinfo(&cp->pcicfg); /* jlc */ dptinfo(cp); /* jlc */ #endif return dptexec; } //GO.SYSIN DD VADIM . sum=`{sum < 872180801/dpt.c.old} if(~ aaf59d2d12928 $sum(1)^$sum(2)) echo if not{ echo 872180801/dpt.c.old checksum error extracting new file exit checksum } target=872180801/ether3210.c echo -n '872180801/ether3210.c (new): ' cat > 872180801/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 < 872180801/ether3210.c} if(~ ba19e7ad4165 $sum(1)^$sum(2)) echo if not{ echo 872180801/ether3210.c checksum error extracting new file exit checksum } target=872180801/pci.c echo -n '872180801/pci.c (new): ' cat > 872180801/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 < 872180801/pci.c} if(~ c64b5f8a3778 $sum(1)^$sum(2)) echo if not{ echo 872180801/pci.c checksum error extracting new file exit checksum } target=872180801/vgaark2000pv.c echo -n '872180801/vgaark2000pv.c (new): ' cat > 872180801/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 GBitmap vgascreen; 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, * 32x32 and 4/8-bit colour depth. * Set cursor colours for 4/8-bit. */ seq20 = vgaxi(Seqx, 0x20) & ~0x1F; vgaxo(Seqx, 0x20, seq20); seq20 |= 0x18; 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 256 byte or 1Kb block located in the last * 16Kb of video memory. Crt25 is the index of which block. */ storage = (vgaxi(Seqx, 0x10)>>6) & 0x03; storage = (1024*1024)<>16); p = ((uchar*)vgascreen.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 32x32 array. * The manual doesn't say what the data layout in memory is - * this worked out by trial and error. */ memmove(clr, c->clr, sizeof(clr)); pixreverse(clr, sizeof(clr), 0); memmove(set, c->set, sizeof(set)); pixreverse(set, sizeof(set), 0); for(y = 0; y < 32; y++){ for(x = 0; x < 32/8; x++){ if(x < 16/8 && y < 16){ *p++ = clr[2*y + x]|set[2*y + x]; *p++ = set[2*y + x]; } else { *p++ = 0x00; *p++ = 0x00; } } } /* * Set the cursor hotpoint. */ hotpoint = c->offset; 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 < 872180801/vgaark2000pv.c} if(~ 2d3b8c1c4033 $sum(1)^$sum(2)) echo if not{ echo 872180801/vgaark2000pv.c checksum error extracting new file exit checksum } target=872180801/vgact65540.c echo -n '872180801/vgact65540.c (new): ' cat > 872180801/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 < 872180801/vgact65540.c} if(~ 6ffecd39440 $sum(1)^$sum(2)) echo if not{ echo 872180801/vgact65540.c checksum error extracting new file exit checksum } target=872180801/vgargb524.c echo -n '872180801/vgargb524.c (new): ' cat > 872180801/vgargb524.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 Cursor curcursor; /* * IBM RGB524. * 170/220MHz High Performance Palette DAC. * * Assumes hooked up to an S3 Vision96[48]. */ enum { IndexLo = 0x00, IndexHi = 0x01, Data = 0x02, IndexCtl = 0x03, }; enum { /* index registers */ CursorCtl = 0x30, CursorXLo = 0x31, CursorXHi = 0x32, CursorYLo = 0x33, CursorYHi = 0x34, CursorHotX = 0x35, CursorHotY = 0x36, CursorR1 = 0x40, CursorG1 = 0x41, CursorB1 = 0x42, CursorR2 = 0x43, CursorG2 = 0x44, CursorB2 = 0x45, CursorR3 = 0x46, CursorG3 = 0x47, CursorB3 = 0x48, CursorArray = 0x100, }; /* * Lower 2-bits of indirect DAC register * addressing. */ static ushort dacxreg[4] = { PaddrW, Pdata, Pixmask, PaddrR }; static uchar setrs2(void) { uchar rs2; rs2 = vgaxi(Crtx, 0x55); vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01); return rs2; } static void rgb524xo(int index, uchar data) { vgao(dacxreg[IndexLo], index & 0xFF); vgao(dacxreg[IndexHi], (index>>8) & 0xFF); vgao(dacxreg[Data], data); } static void restorers2(uchar rs2) { vgaxo(Crtx, 0x55, rs2); } static void load(Cursor *c) { uchar p, p0, p1, rs2; int x, y; uchar clr[2*16], set[2*16]; /* * Lock the DAC registers so we can update the * cursor bitmap if necessary. * If it's the same as the last cursor we loaded, * just make sure it's enabled. */ lock(&palettelock); rs2 = setrs2(); /* if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){ rgb524xo(CursorCtl, 0x23); restorers2(rs2); unlock(&palettelock); return; } memmove(&curcursor, c, sizeof(Cursor)); */ /* * Make sure cursor is off by initialising the cursor * control to defaults. */ rgb524xo(CursorCtl, 0x00); /* * Set auto-increment mode for index-register addressing * and initialise the cursor array index. */ vgao(dacxreg[IndexCtl], 0x01); vgao(dacxreg[IndexLo], CursorArray & 0xFF); vgao(dacxreg[IndexHi], (CursorArray>>8) & 0xFF); /* * Initialise the 32x32 cursor RAM array. There are 2 planes, * p0 and p1. Data is written 4 pixels per byte, with p1 the * MS bit of each pixel. * The cursor is set in X-Windows mode which gives the following * truth table: * p1 p0 colour * 0 0 underlying pixel colour * 0 1 underlying pixel colour * 1 0 cursor colour 1 * 1 1 cursor colour 2 * Put the cursor into the top-left of the 32x32 array. */ memmove(clr, c->clr, sizeof(clr)); pixreverse(clr, sizeof(clr), 0); memmove(set, c->set, sizeof(set)); pixreverse(set, sizeof(set), 0); for(y = 0; y < 32; y++){ for(x = 0; x < 32/8; x++){ if(x < 16/8 && y < 16){ p0 = clr[x+y*2]; p1 = set[x+y*2]; p = 0x00; if(p1 & 0x80) p |= 0xC0; else if(p0 & 0x80) p |= 0x80; if(p1 & 0x40) p |= 0x30; else if(p0 & 0x40) p |= 0x20; if(p1 & 0x20) p |= 0x0C; else if(p0 & 0x20) p |= 0x08; if(p1 & 0x10) p |= 0x03; else if(p0 & 0x10) p |= 0x02; vgao(dacxreg[Data], p); p = 0x00; if(p1 & 0x08) p |= 0xC0; else if(p0 & 0x08) p |= 0x80; if(p1 & 0x04) p |= 0x30; else if(p0 & 0x04) p |= 0x20; if(p1 & 0x02) p |= 0x0C; else if(p0 & 0x02) p |= 0x08; if(p1 & 0x01) p |= 0x03; else if(p0 & 0x01) p |= 0x02; vgao(dacxreg[Data], p); } else{ vgao(dacxreg[Data], 0x00); vgao(dacxreg[Data], 0x00); } } } /* * Initialise the cursor hot-point, * enable the cursor and restore state. */ rgb524xo(CursorHotX, -c->offset.x); rgb524xo(CursorHotY, -c->offset.y); rgb524xo(CursorCtl, 0x23); restorers2(rs2); unlock(&palettelock); } static void enable(void) { uchar rs2; lock(&palettelock); rs2 = setrs2(); /* * Make sure cursor is off by initialising the cursor * control to defaults. */ rgb524xo(CursorCtl, 0x00); /* * Cursor colour 1 (black), * cursor colour 2 (white). */ rgb524xo(CursorR1, Pblack); rgb524xo(CursorG1, Pblack); rgb524xo(CursorB1, Pblack); rgb524xo(CursorR2, Pwhite); rgb524xo(CursorG2, Pwhite); rgb524xo(CursorB2, Pwhite); /* * Enable the cursor, 32x32, mode 2. */ rgb524xo(CursorCtl, 0x23); restorers2(rs2); unlock(&palettelock); } static int move(Point p) { uchar rs2; if(canlock(&palettelock) == 0) return 1; rs2 = setrs2(); rgb524xo(CursorXLo, p.x & 0xFF); rgb524xo(CursorXHi, (p.x>>8) & 0x0F); rgb524xo(CursorYLo, p.y & 0xFF); rgb524xo(CursorYHi, (p.y>>8) & 0x0F); restorers2(rs2); unlock(&palettelock); return 0; } static void disable(void) { uchar rs2; lock(&palettelock); rs2 = setrs2(); rgb524xo(CursorCtl, 0x00); restorers2(rs2); unlock(&palettelock); } static Hwgc rgb524hwgc = { "rgb524hwgc", enable, load, move, disable, 0, }; void vgargb524link(void) { addhwgclink(&rgb524hwgc); } //GO.SYSIN DD VADIM . sum=`{sum < 872180801/vgargb524.c} if(~ 06bffa634939 $sum(1)^$sum(2)) echo if not{ echo 872180801/vgargb524.c checksum error extracting new file exit checksum } echo obsolete files: /sys/src/9/pc/bootpccd.c /sys/src/9/pc/pccd.c