| plan 9 kernel history: overview | file list | diff list |
1998/0106/pc/devata.c (diff list | history)
| 1995/0213/sys/src/9/pc/devata.c:118,124 – 1995/0214/sys/src/9/pc/devata.c:118,124 (short | long) | ||
|
BUG fix/clarity fix?: explicitly name reglock so that ilock can be explicitly told to use the lock, not the qlock. XXX check compiler
rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | { QLock; /* exclusive access to the controller */ | |
| 1995/0214 | Lock reglock; /* exclusive access to the registers */ | |
| 1995/0213 | int confused; /* needs to be recalibrated (or worse) */ int pbase; /* base port */ | |
| 1995/0213/sys/src/9/pc/devata.c:566,572 – 1995/0214/sys/src/9/pc/devata.c:566,572 | ||
| 1995/0213 | dp->usetime = m->ticks; cmdreadywait(dp); | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->sofar = 0; cp->buf = buf; cp->nsecs = len; | |
| 1995/0213/sys/src/9/pc/devata.c:589,595 – 1995/0214/sys/src/9/pc/devata.c:589,595 | ||
| 1995/0213 | outss(cp->pbase+Pdata, cp->buf, dp->bytes/2); } else stat = 0; | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | if(stat & Serr) error(Eio); | |
| 1995/0213/sys/src/9/pc/devata.c:646,657 – 1995/0214/sys/src/9/pc/devata.c:646,657 | ||
| 1995/0213 | cmdreadywait(dp); | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->cmd = Csetbuf; outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55); /* read look ahead */ outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4)); outb(cp->pbase+Pcmd, Csetbuf); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | sleep(&cp->r, cmddone, cp); | |
| 1995/0213/sys/src/9/pc/devata.c:727,733 – 1995/0214/sys/src/9/pc/devata.c:727,733 | ||
| 1995/0213 | cmdreadywait(dp); | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->nsecs = 1; cp->sofar = 0; cp->cmd = Cident; | |
| 1995/0213/sys/src/9/pc/devata.c:735,741 – 1995/0214/sys/src/9/pc/devata.c:735,741 | ||
| 1995/0213 | cp->buf = buf; outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4)); outb(cp->pbase+Pcmd, Cident); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | sleep(&cp->r, cmddone, cp); if(cp->status & Serr){ | |
| 1995/0213/sys/src/9/pc/devata.c:812,818 – 1995/0214/sys/src/9/pc/devata.c:812,818 | ||
| 1995/0213 | cmdreadywait(dp); | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->cmd = Cread; cp->dp = dp; cp->status = 0; | |
| 1995/0213/sys/src/9/pc/devata.c:825,831 – 1995/0214/sys/src/9/pc/devata.c:825,831 | ||
| 1995/0213 | outb(cp->pbase+Pcyllsb, cyl); outb(cp->pbase+Pcylmsb, cyl>>8); outb(cp->pbase+Pcmd, Cread); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | sleep(&cp->r, cmddone, cp); | |
| 1995/0213/sys/src/9/pc/devata.c:1058,1064 – 1995/0214/sys/src/9/pc/devata.c:1058,1064 | ||
| 1995/0213 | cp = &atac[0]; dp = cp->dp; | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | loop = 0; while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){ | |
| 1995/0213/sys/src/9/pc/devata.c:1152,1158 – 1995/0214/sys/src/9/pc/devata.c:1152,1158 | ||
| 1995/0213 | break; } | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | } void | |
| 1995/0213/sys/src/9/pc/devata.c:1172,1183 – 1995/0214/sys/src/9/pc/devata.c:1172,1183 | ||
| 1995/0213 | diff = TK2SEC(m->ticks - dp->usetime); if((dp->state == Sspinning) && (diff >= spindowntime)){ | |
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->cmd = Cstandby; outb(cp->pbase+Pcount, 0); outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | 0); outb(cp->pbase+Pcmd, cp->cmd); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | dp->state = Sstandby; } } | |
| 1995/0214/sys/src/9/pc/devata.c:8,14 – 1995/0215/sys/src/9/pc/devata.c:8,14 (short | long) | ||
|
disable debugging prints
BUG fix: ignore drives that are not online.
remove conf.nhard; configure all existing drives. HW BUG fix: use DHmagic to make sure or in 0xA0 not just 0x20 on head register. rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | #include "devtab.h" | |
| 1995/0215 | #define DPRINT if(0)print | |
| 1995/0213 | typedef struct Drive Drive; typedef struct Ident Ident; | |
| 1995/0214/sys/src/9/pc/devata.c:55,60 – 1995/0215/sys/src/9/pc/devata.c:55,63 | ||
| 1995/0213 | Sidle, Spowerdown, | |
| 1995/0215 | /* something we have to or into the drive/head reg */ DHmagic= 0xA0, | |
| 1995/0213 | /* file types */ Qdir= 0, | |
| 1995/0214/sys/src/9/pc/devata.c:167,173 – 1995/0215/sys/src/9/pc/devata.c:170,176 | ||
| 1995/0213 | return -1; dp = &ata[drive]; | |
| 1995/0215 | if(dp->online == 0 || s >= dp->npart) | |
| 1995/0213 | return 0; pp = &dp->p[s]; | |
| 1995/0214/sys/src/9/pc/devata.c:179,225 – 1995/0215/sys/src/9/pc/devata.c:182,223 | ||
| 1995/0213 | return 1; } | |
| 1995/0215 | if(equip == 0) equip = 0x10; /* the Globalyst 250 lies */ | |
| 1995/0213 |
| |
| 1995/0215 | ata = xalloc(2 * sizeof(Drive)); atac = xalloc(sizeof(Controller)); cp = atac; cp->buf = 0; cp->lastcmd = cp->cmd; cp->cmd = 0; cp->pbase = Pbase; setvec(Hardvec, ataintr, 0); dp = ata; if(equip & 0xf0){ dp->drive = 0; | |
| 1995/0213 | dp->online = 0; dp->cp = cp; | |
| 1995/0215 | dp++; | |
| 1995/0213 | } | |
| 1995/0215 | if((equip & 0x0f)){ dp->drive = 1; dp->online = 0; dp->cp = cp; dp++; } conf.nhard = dp - ata; | |
| 1995/0213 | if(conf.nhard && (p = getconf("spindowntime"))) spindowntime = atoi(p); | |
| 1995/0214/sys/src/9/pc/devata.c:576,582 – 1995/0215/sys/src/9/pc/devata.c:574,580 | ||
| 1995/0213 | outb(cp->pbase+Pcount, cp->nsecs); outb(cp->pbase+Psector, sec); | |
| 1995/0215 | outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4) | (dp->lba<<6) | head); | |
| 1995/0213 | outb(cp->pbase+Pcyllsb, cyl); outb(cp->pbase+Pcylmsb, cyl>>8); outb(cp->pbase+Pcmd, cmd); | |
| 1995/0214/sys/src/9/pc/devata.c:649,655 – 1995/0215/sys/src/9/pc/devata.c:647,653 | ||
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->cmd = Csetbuf; outb(cp->pbase+Pprecomp, on ? 0xAA : 0x55); /* read look ahead */ | |
| 1995/0215 | outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4)); | |
| 1995/0213 | outb(cp->pbase+Pcmd, Csetbuf); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0214/sys/src/9/pc/devata.c:733,739 – 1995/0215/sys/src/9/pc/devata.c:731,737 | ||
| 1995/0213 | cp->cmd = Cident; cp->dp = dp; cp->buf = buf; | |
| 1995/0215 | outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4)); | |
| 1995/0213 | outb(cp->pbase+Pcmd, Cident); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0214/sys/src/9/pc/devata.c:761,768 – 1995/0215/sys/src/9/pc/devata.c:759,765 | ||
| 1995/0213 | dp->lba = 1; dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); dp->cap = dp->bytes * dp->sectors; | |
| 1995/0215 | print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors); | |
| 1995/0213 | } else { dp->lba = 0; | |
| 1995/0214/sys/src/9/pc/devata.c:770,777 – 1995/0215/sys/src/9/pc/devata.c:767,774 | ||
| 1995/0213 | dp->cyl = ip->cyls; dp->heads = ip->heads; dp->sectors = ip->s2t; | |
| 1995/0215 | /*print("\nata%d model %s with default %d cyl %d head %d sec\n", dp->drive, id, dp->cyl, dp->heads, dp->sectors);/**/ | |
| 1995/0213 | if(ip->cvalid&(1<<0)){ /* use current settings */ | |
| 1995/0214/sys/src/9/pc/devata.c:778,785 – 1995/0215/sys/src/9/pc/devata.c:775,781 | ||
| 1995/0213 | dp->cyl = ip->ccyls; dp->heads = ip->cheads; dp->sectors = ip->cs2t; | |
| 1995/0215 | /*print("\tchanged to %d cyl %d head %d sec\n", dp->cyl, dp->heads, dp->sectors);/**/ | |
| 1995/0213 | } dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors; } | |
| 1995/0214/sys/src/9/pc/devata.c:821,827 – 1995/0215/sys/src/9/pc/devata.c:817,823 | ||
| 1995/0213 | outb(cp->pbase+Pcount, 1); outb(cp->pbase+Psector, sec+1); | |
| 1995/0215 | outb(cp->pbase+Pdh, DHmagic | head | (dp->lba<<6) | (dp->drive<<4)); | |
| 1995/0213 | outb(cp->pbase+Pcyllsb, cyl); outb(cp->pbase+Pcylmsb, cyl>>8); outb(cp->pbase+Pcmd, Cread); | |
| 1995/0214/sys/src/9/pc/devata.c:857,863 – 1995/0215/sys/src/9/pc/devata.c:853,859 | ||
| 1995/0213 | ataident(dp); if(dp->lba){ i = dp->sectors - 1; | |
| 1995/0215 | if(ataprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0) | |
| 1995/0213 | return; } else { if(ataprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0) | |
| 1995/0214/sys/src/9/pc/devata.c:868,874 – 1995/0215/sys/src/9/pc/devata.c:864,870 | ||
| 1995/0213 | * the drive lied, determine parameters by seeing which ones * work to read sectors. */ | |
| 1995/0215 | print("ata%d probing...\n", dp->drive); | |
| 1995/0213 | dp->lba = 0; for(i = 0; i < 32; i++) if(ataprobe(dp, 0, 0, i) < 0) | |
| 1995/0214/sys/src/9/pc/devata.c:1038,1043 – 1995/0215/sys/src/9/pc/devata.c:1034,1044 | ||
| 1995/0213 | atareplinit(dp); } | |
| 1995/0215 | enum { Maxloop= 10000, }; | |
| 1995/0213 | /* * we get an interrupt for every sector transferred */ | |
| 1995/0214/sys/src/9/pc/devata.c:1062,1068 – 1995/0215/sys/src/9/pc/devata.c:1063,1069 | ||
| 1995/0213 | loop = 0; while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){ | |
| 1995/0215 | if(++loop > Maxloop) { | |
| 1995/0213 | DPRINT("cmd=%lux status=%lux\n", cp->cmd, inb(cp->pbase+Pstatus)); panic("ataintr: wait busy"); | |
| 1995/0214/sys/src/9/pc/devata.c:1082,1088 – 1995/0215/sys/src/9/pc/devata.c:1083,1089 | ||
| 1995/0213 | if(cp->sofar < cp->nsecs){ loop = 0; while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0) | |
| 1995/0215 | if(++loop > Maxloop) { | |
| 1995/0213 | DPRINT("cmd=%lux status=%lux\n", cp->cmd, inb(cp->pbase+Pstatus)); panic("ataintr: write"); | |
| 1995/0214/sys/src/9/pc/devata.c:1102,1108 – 1995/0215/sys/src/9/pc/devata.c:1103,1109 | ||
| 1995/0213 | case Cident: loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ | |
| 1995/0215 | if(++loop > Maxloop) { | |
| 1995/0213 | DPRINT("cmd=%lux status=%lux\n", cp->cmd, inb(cp->pbase+Pstatus)); panic("ataintr: read/ident"); | |
| 1995/0214/sys/src/9/pc/devata.c:1175,1181 – 1995/0215/sys/src/9/pc/devata.c:1176,1182 | ||
| 1995/0214 | ilock(&cp->reglock); | |
| 1995/0213 | cp->cmd = Cstandby; outb(cp->pbase+Pcount, 0); | |
| 1995/0215 | outb(cp->pbase+Pdh, DHmagic | (dp->drive<<4) | 0); | |
| 1995/0213 | outb(cp->pbase+Pcmd, cp->cmd); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 | dp->state = Sstandby; | |
| 1995/0215/sys/src/9/pc/devata.c:759,765 – 1995/0222/sys/src/9/pc/devata.c:759,765 (short | long) | ||
|
disable debugging prints
rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | dp->lba = 1; dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); dp->cap = dp->bytes * dp->sectors; | |
| 1995/0215 |
| |
| 1995/0222 | /*print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors);/**/ | |
| 1995/0213 | } else { dp->lba = 0; | |
| 1995/0222/sys/src/9/pc/devata.c:290,298 – 1995/0726/sys/src/9/pc/devata.c:290,297 (short | long) | ||
|
anonymize
rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | } void | |
| 1995/0726 | atacreate(Chan*, char*, int, ulong) | |
| 1995/0213 | { | |
| 1995/0726/sys/src/9/pc/devata.c:813,818 – 1995/0728/sys/src/9/pc/devata.c:813,819 (short | long) | ||
|
HW BUG double fix: empty buffer always; also set cp->buf even though we don't need to in ataprobe. (Either would fix the HW bug).
rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | cp->status = 0; cp->nsecs = 1; cp->sofar = 0; | |
| 1995/0728 | cp->buf = buf; | |
| 1995/0213 | outb(cp->pbase+Pcount, 1); outb(cp->pbase+Psector, sec+1); | |
| 1995/0726/sys/src/9/pc/devata.c:1120,1125 – 1995/0728/sys/src/9/pc/devata.c:1121,1130 | ||
| 1995/0213 | if(addr){ addr += cp->sofar*dp->bytes; inss(cp->pbase+Pdata, addr, dp->bytes/2); | |
| 1995/0728 | } else { /* old drives/controllers hang unless the buffer is emptied */ for(loop = dp->bytes/2; --loop >= 0;) ins(cp->pbase+Pdata); | |
| 1995/0213 | } cp->sofar++; if(cp->sofar > cp->nsecs) | |
| 1995/0728/sys/src/9/pc/devata.c:19,25 – 1995/0818/sys/src/9/pc/devata.c:19,26 (short | long) | ||
|
deanonymize atacreate (XXX).
look for drives on both controllers. add atasleep, which has a timeout. HW BUG fix: make Hardtimeout 4 seconds, not 10ms. HW BUG fix: use atasleep everywhere, in case of buggy controllers. HW BUG fix: ignore lbasecs if all 'F's. HW BUG fix: increase Maxloop XXX. HW BUG fix? do not read buffer if no cp->buf. (XXX look for cmd with cp->buf==0. rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | enum { /* ports */ | |
| 1995/0818 | Pbase0= 0x1F0, Pbase1= 0x170, | |
| 1995/0213 | Pdata= 0, /* data port (16 bits) */ Perror= 1, /* error port (read) */ Pprecomp= 1, /* buffer mode port (write) */ | |
| 1995/0728/sys/src/9/pc/devata.c:64,69 – 1995/0818/sys/src/9/pc/devata.c:65,72 | ||
| 1995/0213 | Maxxfer= BY2PG, /* maximum transfer size/cmd */ Npart= 8+2, /* 8 sub partitions, disk, and partition */ Nrepl= 64, /* maximum replacement blocks */ | |
| 1995/0818 | Hardtimeout= 4000, /* disk access timeout */ | |
| 1995/0213 | }; #define PART(x) ((x)&0xF) #define DRIVE(x) (((x)>>4)&0x7) | |
| 1995/0728/sys/src/9/pc/devata.c:201,208 – 1995/0818/sys/src/9/pc/devata.c:204,211 | ||
| 1995/0215 | cp->buf = 0; cp->lastcmd = cp->cmd; cp->cmd = 0; | |
| 1995/0818 | cp->pbase = Pbase0; setvec(ATAvec0, ataintr, 0); | |
| 1995/0215 | dp = ata; if(equip & 0xf0){ | |
| 1995/0728/sys/src/9/pc/devata.c:290,297 – 1995/0818/sys/src/9/pc/devata.c:293,301 | ||
| 1995/0213 | } void | |
| 1995/0726 |
| |
| 1995/0818 | atacreate(Chan *c, char *name, int omode, ulong perm) | |
| 1995/0213 | { | |
| 1995/0818 | USED(c, name, omode, perm); | |
| 1995/0213 | error(Eperm); } | |
| 1995/0728/sys/src/9/pc/devata.c:505,510 – 1995/0818/sys/src/9/pc/devata.c:509,525 | ||
| 1995/0213 | } } | |
| 1995/0818 | static void atasleep(Controller *cp) { tsleep(&cp->r, cmddone, cp, Hardtimeout); if(cp->cmd && cp->cmd != Cident2){ DPRINT("hard drive timeout\n"); error("ata drive timeout"); } } | |
| 1995/0213 | /* * transfer a number of sectors. ataintr will perform all the iterative * parts. | |
| 1995/0728/sys/src/9/pc/devata.c:548,553 – 1995/0818/sys/src/9/pc/devata.c:563,570 | ||
| 1995/0213 | head = ((lblk/dp->sectors) % dp->heads); } | |
| 1995/0818 | /*print("ataxfer cyl %d sec %d head %d\n", cyl, sec, head);/**/ | |
| 1995/0213 | cp = dp->cp; qlock(cp); if(waserror()){ | |
| 1995/0728/sys/src/9/pc/devata.c:604,610 – 1995/0818/sys/src/9/pc/devata.c:621,627 | ||
| 1995/0213 | nexterror(); } } | |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | dp->state = Sspinning; dp->usetime = m->ticks; poperror(); | |
| 1995/0728/sys/src/9/pc/devata.c:650,656 – 1995/0818/sys/src/9/pc/devata.c:667,673 | ||
| 1995/0213 | outb(cp->pbase+Pcmd, Csetbuf); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 |
| |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | /* if(cp->status & Serr) DPRINT("hd%d setbuf err: status %lux, err %lux\n", | |
| 1995/0728/sys/src/9/pc/devata.c:713,718 – 1995/0818/sys/src/9/pc/devata.c:730,736 | ||
| 1995/0213 | char *buf; Ident *ip; char id[21]; | |
| 1995/0818 | ulong lbasecs; | |
| 1995/0213 | cp = dp->cp; buf = smalloc(Maxxfer); | |
| 1995/0728/sys/src/9/pc/devata.c:734,740 – 1995/0818/sys/src/9/pc/devata.c:752,759 | ||
| 1995/0213 | outb(cp->pbase+Pcmd, Cident); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 |
| |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | if(cp->status & Serr){ DPRINT("bad disk ident status\n"); error(Eio); | |
| 1995/0728/sys/src/9/pc/devata.c:749,762 – 1995/0818/sys/src/9/pc/devata.c:768,782 | ||
| 1995/0213 | * causing a panic and much confusion. */ if (cp->cmd == Cident2) | |
| 1995/0818 | tsleep(&cp->r, return0, 0, Hardtimeout); | |
| 1995/0213 | memmove(id, ip->model, sizeof(id)-1); id[sizeof(id)-1] = 0; | |
| 1995/0818 | lbasecs = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){ | |
| 1995/0213 | dp->lba = 1; | |
| 1995/0818 | dp->sectors = lbasecs; | |
| 1995/0213 | dp->cap = dp->bytes * dp->sectors; | |
| 1995/0222 | /*print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors);/**/ | |
| 1995/0213 | } else { | |
| 1995/0728/sys/src/9/pc/devata.c:823,829 – 1995/0818/sys/src/9/pc/devata.c:843,849 | ||
| 1995/0213 | outb(cp->pbase+Pcmd, Cread); | |
| 1995/0214 | iunlock(&cp->reglock); | |
| 1995/0213 |
| |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | if(cp->status & Serr) rv = -1; | |
| 1995/0728/sys/src/9/pc/devata.c:864,870 – 1995/0818/sys/src/9/pc/devata.c:884,889 | ||
| 1995/0213 | * the drive lied, determine parameters by seeing which ones * work to read sectors. */ | |
| 1995/0215 |
| |
| 1995/0213 | dp->lba = 0; for(i = 0; i < 32; i++) if(ataprobe(dp, 0, 0, i) < 0) | |
| 1995/0728/sys/src/9/pc/devata.c:1036,1042 – 1995/0818/sys/src/9/pc/devata.c:1055,1061 | ||
| 1995/0213 | ||
| 1995/0215 | enum { | |
| 1995/0818 | Maxloop= 1000000, | |
| 1995/0215 | }; | |
| 1995/0213 | /* | |
| 1995/0728/sys/src/9/pc/devata.c:1063,1073 – 1995/0818/sys/src/9/pc/devata.c:1082,1090 | ||
| 1995/0213 | loop = 0; while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){ | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0818 | if(++loop > Maxloop) panic("ataintr: wait busy cmd=%lux status=%lux", | |
| 1995/0213 | cp->cmd, inb(cp->pbase+Pstatus)); | |
| 1995/0728/sys/src/9/pc/devata.c:1083,1093 – 1995/0818/sys/src/9/pc/devata.c:1100,1108 | ||
| 1995/0213 | if(cp->sofar < cp->nsecs){ loop = 0; while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0) | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0818 | if(++loop > Maxloop) panic("ataintr: write cmd=%lux status=%lux\n", | |
| 1995/0213 | cp->cmd, inb(cp->pbase+Pstatus)); | |
| 1995/0728/sys/src/9/pc/devata.c:1103,1112 – 1995/0818/sys/src/9/pc/devata.c:1118,1128 | ||
| 1995/0213 | case Cident: loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0818 | if(++loop > Maxloop){ print("ataintr: read/ident cmd=%lux status=%lux\n", | |
| 1995/0213 | cp->cmd, inb(cp->pbase+Pstatus)); | |
| 1995/0818 | cp->status |= Serr; break; | |
| 1995/0213 | } cp->status = inb(cp->pbase+Pstatus); } | |
| 1995/0728/sys/src/9/pc/devata.c:1121,1130 – 1995/0818/sys/src/9/pc/devata.c:1137,1142 | ||
| 1995/0213 | if(addr){ addr += cp->sofar*dp->bytes; inss(cp->pbase+Pdata, addr, dp->bytes/2); | |
| 1995/0728 |
| |
| 1995/0213 | } cp->sofar++; if(cp->sofar > cp->nsecs) | |
| 1995/0818/sys/src/9/pc/devata.c:885,895 – 1995/0908/sys/src/9/pc/devata.c:885,895 (short | long) | ||
|
HW bug fix: probe for fewer heads, sectors per track.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1995/0213 | * work to read sectors. */ dp->lba = 0; | |
| 1995/0908 | for(i = 0; i < 16; i++) | |
| 1995/0213 | if(ataprobe(dp, 0, 0, i) < 0) break; dp->heads = i; | |
| 1995/0908 | for(i = 0; i < 64; i++) | |
| 1995/0213 | if(ataprobe(dp, 0, i, 0) < 0) break; dp->sectors = i; | |
| 1995/0908/sys/src/9/pc/devata.c:1,3 – 1995/1206/sys/src/9/pc/devata.c:1,7 (short | long) | ||
| 1995/1206 | /* * This has gotten a bit messy with the addition of multiple controller * and ATAPI support; needs a rewrite before adding any 'ctl' functions. */ | |
| 1995/0213 | #include "u.h" #include "../port/lib.h" #include "mem.h" | |
| 1995/0908/sys/src/9/pc/devata.c:9,14 – 1995/1206/sys/src/9/pc/devata.c:13,21 | ||
| 1995/0213 | #include "devtab.h" | |
| 1995/0215 | #define DPRINT if(0)print | |
| 1995/1206 | #define XPRINT if(0)print #define ILOCK(x) #define IUNLOCK(x) | |
| 1995/0213 | typedef struct Drive Drive; typedef struct Ident Ident; | |
| 1995/0908/sys/src/9/pc/devata.c:19,73 – 1995/1206/sys/src/9/pc/devata.c:26,87 | ||
| 1995/0213 | enum { /* ports */ | |
| 1995/0818 |
| |
| 1995/1206 | Pbase0= 0x1F0, /* primary */ Pbase1= 0x170, /* secondary */ Pbase2= 0x1E8, /* tertiary */ Pbase3= 0x168, /* quaternary */ | |
| 1995/0213 | Pdata= 0, /* data port (16 bits) */ Perror= 1, /* error port (read) */ | |
| 1995/1206 | Eabort= (1<<2), Pfeature= 1, /* buffer mode port (write) */ | |
| 1995/0213 | 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 */ | |
| 1995/1206 | DHmagic= 0xA0, DHslave= 0x10, | |
| 1995/0213 | Pstatus= 7, /* status port (read) */ Sbusy= (1<<7), Sready= (1<<6), | |
| 1995/1206 | Sdf= (1<<5), | |
| 1995/0213 | Sdrq= (1<<3), Serr= (1<<0), Pcmd= 7, /* cmd port (write) */ /* commands */ | |
| 1995/1206 | Cfirst= 0xFF, /* pseudo command for initialisation */ | |
| 1995/0213 | Cread= 0x20, Cwrite= 0x30, | |
| 1995/1206 | Cedd= 0x90, /* execute device diagnostics */ | |
| 1995/0213 | Cident= 0xEC, | |
| 1995/1206 | Cident2= 0xFE, /* pseudo command for post Cident interrupt */ Cfeature= 0xEF, | |
| 1995/0213 |
| |
| 1995/1206 | Cpktcmd= 0xA0, Cidentd= 0xA1, Ccapacity= 0x25, Cread2= 0x28, | |
| 1995/0213 | /* disk states */ Sspinning, Sstandby, | |
| 1995/0215 |
| |
| 1995/0213 | /* file types */ Qdir= 0, Maxxfer= BY2PG, /* maximum transfer size/cmd */ | |
| 1995/1206 | Npart= 20+2, /* 8 sub partitions, disk, and partition */ | |
| 1995/0213 | Nrepl= 64, /* maximum replacement blocks */ | |
| 1995/0818 |
| |
| 1995/1206 | Hardtimeout= 30000, /* disk access timeout (ms) */ NCtlr= 4, NDrive= NCtlr*2, | |
| 1995/0213 | }; | |
| 1995/1206 | ||
| 1995/0213 | #define PART(x) ((x)&0xF) #define DRIVE(x) (((x)>>4)&0x7) #define MKQID(d,p) (((d)<<4) | (p)) | |
| 1995/0908/sys/src/9/pc/devata.c:97,106 – 1995/1206/sys/src/9/pc/devata.c:111,123 | ||
| 1995/0213 | QLock; Controller *cp; | |
| 1995/1206 | uchar driveno; uchar dh; /* DHmagic|Am-I-A-Slave */ uchar atapi; uchar online; | |
| 1995/0213 | int npart; /* number of real partitions */ | |
| 1995/1206 | int partok; | |
| 1995/0213 | Partition p[Npart]; Repl repl; ulong usetime; | |
| 1995/0908/sys/src/9/pc/devata.c:112,120 – 1995/1206/sys/src/9/pc/devata.c:129,142 | ||
| 1995/0213 | int sectors; /* sectors/track */ int heads; /* heads/cyl */ long cyl; /* cylinders/drive */ | |
| 1995/1206 | ulong lbasecs; | |
| 1995/0213 |
| |
| 1995/1206 | 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; | |
| 1995/0213 | }; /* | |
| 1995/0908/sys/src/9/pc/devata.c:122,162 – 1995/1206/sys/src/9/pc/devata.c:144,204 | ||
| 1995/0213 | */ struct Controller { | |
| 1995/1206 | QLock* ctlrlock; /* exclusive access to the controller */ | |
| 1995/0213 | ||
| 1995/0214 | Lock reglock; /* exclusive access to the registers */ | |
| 1995/0213 |
| |
| 1995/1206 | uchar ctlrno; uchar noatapi; | |
| 1995/0213 | /* * current operation */ | |
| 1995/1206 | 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 */ | |
| 1995/0213 | int nsecs; /* length of transfer (sectors) */ int sofar; /* sectors transferred so far */ | |
| 1995/1206 | Drive* dp; /* drive being accessed */ | |
| 1995/0213 | }; | |
| 1995/1206 | 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, }; | |
| 1995/0213 | static void ataintr(Ureg*, void*); | |
| 1995/1206 | static long ataxfer(Drive*, Partition*, int, long, long, uchar*); | |
| 1995/0213 | static void ataident(Drive*); | |
| 1995/1206 | static void atafeature(Drive*, uchar); | |
| 1995/0213 | static void ataparams(Drive*); static void atapart(Drive*); static int ataprobe(Drive*, int, int, int); | |
| 1995/1206 | static void atasleep(Controller*); | |
| 1995/0213 | ||
| 1995/1206 | static int isatapi(Drive*); static long atapirwio(Chan*, char*, ulong, ulong); static void atapipart(Drive*); static void atapiintr(Controller*); | |
| 1995/0213 | static int | |
| 1995/1206 | atagen(Chan *c, Dirtab*, long, long s, Dir *dirp) | |
| 1995/0213 | { Qid qid; int drive; | |
| 1995/0908/sys/src/9/pc/devata.c:165,177 – 1995/1206/sys/src/9/pc/devata.c:207,221 | ||
| 1995/0213 | Partition *pp; ulong l; | |
| 1995/1206 | if(drive >= NDrive) | |
| 1995/0213 | return -1; | |
| 1995/1206 | if(atadrive[drive] == 0) return 0; dp = atadrive[drive]; | |
| 1995/0213 | ||
| 1995/0215 | if(dp->online == 0 || s >= dp->npart) | |
| 1995/0213 | return 0; | |
| 1995/0908/sys/src/9/pc/devata.c:185,232 – 1995/1206/sys/src/9/pc/devata.c:229,525 | ||
| 1995/0213 | return 1; } | |
| 1995/1206 | static void cmd640b(void) | |
| 1995/0213 | { | |
| 1995/1206 | PCIcfg* pcicfg; uchar r50[12]; int devno; extern void pcicfgw8(int, int, int, int, void*, int); | |
| 1995/0213 |
| |
| 1995/0215 |
| |
| 1995/1206 | /* * 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); } | |
| 1995/0213 | ||
| 1995/0215 |
| |
| 1995/1206 | static void rz1000(void) { PCIcfg* pcicfg; ulong r40; int devno; | |
| 1995/0215 |
| |
| 1995/0818 |
| |
| 1995/1206 | /* * 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); } | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0215 |
| |
| 1995/1206 | 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; | |
| 1995/0213 | } | |
| 1995/0215 |
| |
| 1995/1206 | 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) drive->atapi = 1; atadrive[driveno] = drive; } static int atactlrprobe(int ctlrno, int irq) { Controller *ctlr; int atapi, mask, port; uchar error, status; /* * 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; | |
| 1995/0215 | } | |
| 1995/1206 | 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. * 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 Edd (Micronics M54Li + Sanyo CDR-XXX) so let's check for the * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ 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()){ xfree(ctlr); return -1; } setvec(irq, ataintr, ctlr); ctlr->cmd = Cedd; outb(port+Pcmd, Cedd); atasleep(ctlr); 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 && inb(port+Pcylmsb) == 0xEB && inb(port+Pcyllsb) == 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; | |
| 1995/0213 |
| |
| 1995/1206 | 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<<driveno); DPRINT("ata%d: opt spindownmask %ux\n", ctlrno, spindownmask); } else if(strcmp(isa.opt[i], "noatapi") == 0) atactlr[ctlrno]->noatapi = 1; } } | |
| 1995/0213 | } void | |
| 1995/1206 | atareset(void) { } void | |
| 1995/0213 | atainit(void) { } | |
| 1995/0908/sys/src/9/pc/devata.c:238,246 – 1995/1206/sys/src/9/pc/devata.c:531,551 | ||
| 1995/0213 | Chan* ataattach(char *spec) { | |
| 1995/1206 | int driveno; | |
| 1995/0213 | Drive *dp; | |
| 1995/1206 | 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; | |
| 1995/0213 | if(waserror()){ dp->online = 0; qunlock(dp); | |
| 1995/0908/sys/src/9/pc/devata.c:248,267 – 1995/1206/sys/src/9/pc/devata.c:553,572 | ||
| 1995/0213 | } qlock(dp); if(!dp->online){ | |
| 1995/1206 | atafeature(dp, 0xAA); /* read look ahead */ | |
| 1995/0213 | } /* * read Plan 9 partition table */ | |
| 1995/1206 | if(dp->partok == 0){ if(dp->atapi) atapipart(dp); else atapart(dp); } | |
| 1995/0213 | qunlock(dp); poperror(); } | |
| 1995/0908/sys/src/9/pc/devata.c:293,301 – 1995/1206/sys/src/9/pc/devata.c:598,605 | ||
| 1995/0213 | } void | |
| 1995/0818 |
| |
| 1995/1206 | atacreate(Chan*, char*, int, ulong) | |
| 1995/0213 | { | |
| 1995/0818 |
| |
| 1995/0213 | error(Eperm); } | |
| 1995/0908/sys/src/9/pc/devata.c:302,339 – 1995/1206/sys/src/9/pc/devata.c:606,642 | ||
| 1995/0213 | void ataclose(Chan *c) { | |
| 1995/1206 | Drive *dp; | |
| 1995/0213 | Partition *p; if(c->mode != OWRITE && c->mode != ORDWR) return; | |
| 1995/1206 | dp = atadrive[DRIVE(c->qid.path)]; p = &dp->p[PART(c->qid.path)]; | |
| 1995/0213 | if(strcmp(p->name, "partition") != 0) return; if(waserror()){ | |
| 1995/1206 | qunlock(dp); | |
| 1995/0213 | nexterror(); } | |
| 1995/1206 | qlock(dp); dp->partok = 0; atapart(dp); qunlock(dp); | |
| 1995/0213 | poperror(); } void | |
| 1995/1206 | ataremove(Chan*) | |
| 1995/0213 | { | |
| 1995/1206 | atawstat(Chan*, char*) | |
| 1995/0213 | { | |
| 1995/0908/sys/src/9/pc/devata.c:345,355 – 1995/1206/sys/src/9/pc/devata.c:648,675 | ||
| 1995/0213 | int skip; uchar *aa = a; Partition *pp; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 | if(c->qid.path == CHDIR) return devdirread(c, a, n, 0, 0, atagen); | |
| 1995/1206 | 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)]; | |
| 1995/0213 | buf = smalloc(Maxxfer); if(waserror()){ free(buf); | |
| 1995/0908/sys/src/9/pc/devata.c:356,364 – 1995/1206/sys/src/9/pc/devata.c:676,681 | ||
| 1995/0213 | nexterror(); } | |
| 1995/0908/sys/src/9/pc/devata.c:390,402 – 1995/1206/sys/src/9/pc/devata.c:707,722 | ||
| 1995/0213 | long rv, i, partial; uchar *aa = a; Partition *pp; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 | if(c->qid.path == CHDIR) error(Eisdir); | |
| 1995/1206 | dp = atadrive[DRIVE(c->qid.path)]; if(dp->atapi) error(Eperm); | |
| 1995/0213 | pp = &dp->p[PART(c->qid.path)]; | |
| 1995/1206 | ||
| 1995/0213 | buf = smalloc(Maxxfer); if(waserror()){ free(buf); | |
| 1995/0908/sys/src/9/pc/devata.c:472,499 – 1995/1206/sys/src/9/pc/devata.c:792,817 | ||
| 1995/0213 | /* * Wait for the controller to be ready to accept a command. | |
| 1995/1206 | static int | |
| 1995/0213 | cmdreadywait(Drive *dp) { | |
| 1995/1206 | ulong ticks; uchar ready; | |
| 1995/0213 | /* give it 2 seconds to spin down and up */ | |
| 1995/1206 | dp->usetime = m->ticks; | |
| 1995/0213 | if(dp->state == Sspinning) | |
| 1995/1206 | ticks = MS2TK(10); | |
| 1995/0213 | else | |
| 1995/1206 | ticks = MS2TK(2000); | |
| 1995/0213 |
| |
| 1995/1206 | if(dp->atapi) ready = 0; else ready = Sready; return atactlrwait(dp->cp, dp->dh, ready, ticks); | |
| 1995/0213 | } static void | |
| 1995/0908/sys/src/9/pc/devata.c:505,511 – 1995/1206/sys/src/9/pc/devata.c:823,829 | ||
| 1995/0213 | return; for(i = 0; i < dp->repl.nrepl; i++){ if(dp->repl.blk[i] == bblk) | |
| 1995/1206 | DPRINT("%s: found bblk %ld at offset %ld\n", dp->vol, bblk, i); | |
| 1995/0213 | } } | |
| 1995/0908/sys/src/9/pc/devata.c:514,520 – 1995/1206/sys/src/9/pc/devata.c:832,838 | ||
| 1995/0818 | { tsleep(&cp->r, cmddone, cp, Hardtimeout); if(cp->cmd && cp->cmd != Cident2){ | |
| 1995/1206 | DPRINT("ata%d: cmd 0x%uX timeout\n", cp->ctlrno, cp->cmd); | |
| 1995/0818 | error("ata drive timeout"); } } | |
| 1995/0908/sys/src/9/pc/devata.c:525,531 – 1995/1206/sys/src/9/pc/devata.c:843,849 | ||
| 1995/0213 | * parts. */ static long | |
| 1995/1206 | ataxfer(Drive *dp, Partition *pp, int cmd, long start, long len, uchar *buf) | |
| 1995/0213 | { Controller *cp; long lblk; | |
| 1995/0908/sys/src/9/pc/devata.c:563,586 – 1995/1206/sys/src/9/pc/devata.c:881,902 | ||
| 1995/0213 | head = ((lblk/dp->sectors) % dp->heads); } | |
| 1995/0818 |
| |
| 1995/1206 | XPRINT("%s: ataxfer cyl %d sec %d head %d len %d\n", dp->vol, cyl, sec, head, len); | |
| 1995/0818 | ||
| 1995/0213 | cp = dp->cp; | |
| 1995/1206 | qlock(cp->ctlrlock); | |
| 1995/0213 | if(waserror()){ | |
| 1995/1206 | cp->dp = 0; | |
| 1995/0213 | cp->buf = 0; | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | nexterror(); } | |
| 1995/1206 | if(cmdreadywait(dp)){ error(Eio); } | |
| 1995/0213 | ||
| 1995/0214 |
| |
| 1995/1206 | ILOCK(&cp->reglock); | |
| 1995/0213 | cp->sofar = 0; cp->buf = buf; cp->nsecs = len; | |
| 1995/0908/sys/src/9/pc/devata.c:590,596 – 1995/1206/sys/src/9/pc/devata.c:906,912 | ||
| 1995/0213 | outb(cp->pbase+Pcount, cp->nsecs); outb(cp->pbase+Psector, sec); | |
| 1995/0215 |
| |
| 1995/1206 | outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head); | |
| 1995/0213 | outb(cp->pbase+Pcyllsb, cyl); outb(cp->pbase+Pcylmsb, cyl>>8); outb(cp->pbase+Pcmd, cmd); | |
| 1995/0908/sys/src/9/pc/devata.c:597,609 – 1995/1206/sys/src/9/pc/devata.c:913,926 | ||
| 1995/0213 | if(cmd == Cwrite){ loop = 0; | |
| 1995/1206 | microdelay(1); | |
| 1995/0213 | while((stat = inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0) if(++loop > 10000) | |
| 1995/1206 | panic("%s: ataxfer", dp->vol); | |
| 1995/0213 | outss(cp->pbase+Pdata, cp->buf, dp->bytes/2); } else stat = 0; | |
| 1995/0214 |
| |
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | if(stat & Serr) error(Eio); | |
| 1995/0908/sys/src/9/pc/devata.c:615,644 – 1995/1206/sys/src/9/pc/devata.c:932,962 | ||
| 1995/0213 | */ loop = 0; while(waserror()){ | |
| 1995/1206 | DPRINT("%s: interrupted ataxfer\n", dp->vol); | |
| 1995/0213 | if(loop++ > 10){ | |
| 1995/1206 | print("%s: disk error\n", dp->vol); | |
| 1995/0213 | nexterror(); } } | |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 |
| |
| 1995/1206 | dp->state = Sspinning; | |
| 1995/0213 | poperror(); if(loop) nexterror(); if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s err: lblk %ld status %lux, err %lux\n", dp->vol, lblk, cp->status, cp->error); | |
| 1995/0213 | DPRINT("\tcyl %d, sec %d, head %d\n", cyl, sec, head); DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar); atarepl(dp, lblk+cp->sofar); error(Eio); } | |
| 1995/1206 | cp->dp = 0; | |
| 1995/0213 | cp->buf = 0; len = cp->sofar*dp->bytes; | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | poperror(); return len; | |
| 1995/0908/sys/src/9/pc/devata.c:648,680 – 1995/1206/sys/src/9/pc/devata.c:966,1006 | ||
| 1995/0213 | * set read ahead mode */ static void | |
| 1995/1206 | atafeature(Drive *dp, uchar arg) | |
| 1995/0213 | { Controller *cp = dp->cp; | |
| 1995/1206 | if(dp->atapi) return; qlock(cp->ctlrlock); | |
| 1995/0213 | if(waserror()){ | |
| 1995/1206 | cp->dp = 0; qunlock(cp->ctlrlock); | |
| 1995/0213 | nexterror(); } | |
| 1995/1206 | if(cmdreadywait(dp)){ error(Eio); } | |
| 1995/0213 | ||
| 1995/0214 |
| |
| 1995/0213 |
| |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0214 |
| |
| 1995/1206 | 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); | |
| 1995/0213 | ||
| 1995/0818 | atasleep(cp); | |
| 1995/0213 |
| |
| 1995/1206 | if(cp->status & Serr) DPRINT("%s: setbuf err: status %lux, err %lux\n", dp->vol, cp->status, cp->error); | |
| 1995/0213 | ||
| 1995/1206 | cp->dp = 0; | |
| 1995/0213 | poperror(); | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | } /* | |
| 1995/0908/sys/src/9/pc/devata.c:727,761 – 1995/1206/sys/src/9/pc/devata.c:1053,1108 | ||
| 1995/0213 | ataident(Drive *dp) { Controller *cp; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 | Ident *ip; char id[21]; | |
| 1995/0818 | ulong lbasecs; | |
| 1995/1206 | uchar cmd; | |
| 1995/0213 | cp = dp->cp; buf = smalloc(Maxxfer); | |
| 1995/1206 | qlock(cp->ctlrlock); | |
| 1995/0213 | if(waserror()){ | |
| 1995/1206 | cp->dp = 0; free(buf); qunlock(cp->ctlrlock); | |
| 1995/0213 | nexterror(); } | |
| 1995/1206 | if(dp->atapi || isatapi(dp)) cmd = Cidentd; else{ cmd = Cident; if(cmdreadywait(dp)){ dp->atapi = 1; if(isatapi(dp) == 0) error(Eio); cmd = Cidentd; } } | |
| 1995/0213 | ||
| 1995/0214 |
| |
| 1995/1206 | retryatapi: ILOCK(&cp->reglock); | |
| 1995/0213 | cp->nsecs = 1; cp->sofar = 0; | |
| 1995/1206 | cp->cmd = cmd; | |
| 1995/0213 | cp->dp = dp; cp->buf = buf; | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0214 |
| |
| 1995/1206 | outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, cmd); IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s: bad disk ident status\n", dp->vol); if(dp->atapi == 0 && (cp->error & Eabort)){ dp->atapi = 1; if(isatapi(dp)){ cmd = Cidentd; goto retryatapi; } } | |
| 1995/0213 | error(Eio); } ip = (Ident*)buf; | |
| 1995/0908/sys/src/9/pc/devata.c:773,809 – 1995/1206/sys/src/9/pc/devata.c:1120,1173 | ||
| 1995/0213 | memmove(id, ip->model, sizeof(id)-1); id[sizeof(id)-1] = 0; | |
| 1995/1206 | DPRINT("%s: config 0x%uX capabilities 0x%uX\n", dp->vol, ip->config, ip->capabilities); if(dp->atapi){ dp->bytes = 2048; if((ip->config & 0x0060) == 0x0020) dp->drqintr = 1; } if(dp->spindown && (ip->capabilities & (1<<13))) dp->spindown /= 5; /* use default (unformatted) settings */ dp->cyl = ip->cyls; dp->heads = ip->heads; dp->sectors = ip->s2t; DPRINT("%s: %s %d/%d/%d CHS %d bytes\n", dp->vol, id, dp->cyl, dp->heads, dp->sectors, dp->cap); if(ip->cvalid&(1<<0)){ /* use current settings */ dp->cyl = ip->ccyls; dp->heads = ip->cheads; dp->sectors = ip->cs2t; DPRINT("%s: changed to %d cyl %d head %d sec\n", dp->vol, dp->cyl, dp->heads, dp->sectors); } | |
| 1995/0818 | lbasecs = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){ | |
| 1995/0213 | dp->lba = 1; | |
| 1995/0818 |
| |
| 1995/0213 |
| |
| 1995/0222 |
| |
| 1995/1206 | dp->lbasecs = lbasecs; dp->cap = dp->bytes * dp->lbasecs; DPRINT("%s: LBA: %s %d sectors %d bytes\n", dp->vol, id, dp->lbasecs, dp->cap); | |
| 1995/0213 | } else { dp->lba = 0; | |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/0215 |
| |
| 1995/0213 |
| |
| 1995/1206 | dp->lbasecs = 0; | |
| 1995/0213 | dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors; } | |
| 1995/1206 | if(cp->cmd){ cp->lastcmd = cp->cmd; cp->cmd = 0; } cp->dp = 0; | |
| 1995/0213 | cp->buf = 0; free(buf); poperror(); | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | } /* | |
| 1995/0908/sys/src/9/pc/devata.c:813,833 – 1995/1206/sys/src/9/pc/devata.c:1177,1200 | ||
| 1995/0213 | ataprobe(Drive *dp, int cyl, int sec, int head) { Controller *cp; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 | int rv; cp = dp->cp; buf = smalloc(Maxxfer); | |
| 1995/1206 | qlock(cp->ctlrlock); | |
| 1995/0213 | if(waserror()){ | |
| 1995/1206 | cp->dp = 0; | |
| 1995/0213 | free(buf); | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | nexterror(); } | |
| 1995/1206 | if(cmdreadywait(dp)){ error(Eio); } | |
| 1995/0213 | ||
| 1995/0214 |
| |
| 1995/1206 | ILOCK(&cp->reglock); | |
| 1995/0213 | cp->cmd = Cread; cp->dp = dp; cp->status = 0; | |
| 1995/0908/sys/src/9/pc/devata.c:837,859 – 1995/1206/sys/src/9/pc/devata.c:1204,1230 | ||
| 1995/0213 | outb(cp->pbase+Pcount, 1); outb(cp->pbase+Psector, sec+1); | |
| 1995/0215 |
| |
| 1995/1206 | outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head); | |
| 1995/0213 | outb(cp->pbase+Pcyllsb, cyl); outb(cp->pbase+Pcylmsb, cyl>>8); outb(cp->pbase+Pcmd, Cread); | |
| 1995/0214 |
| |
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0818 | atasleep(cp); | |
| 1995/0213 |
| |
| 1995/1206 | if(cp->status & Serr){ DPRINT("%s: probe err: status %lux, err %lux\n", dp->vol, cp->status, cp->error); | |
| 1995/0213 | rv = -1; | |
| 1995/1206 | } | |
| 1995/0213 | else rv = 0; | |
| 1995/1206 | cp->dp = 0; | |
| 1995/0213 | cp->buf = 0; free(buf); poperror(); | |
| 1995/1206 | qunlock(cp->ctlrlock); | |
| 1995/0213 | return rv; } | |
| 1995/0908/sys/src/9/pc/devata.c:871,878 – 1995/1206/sys/src/9/pc/devata.c:1242,1251 | ||
| 1995/0213 | */ dp->bytes = 512; ataident(dp); | |
| 1995/1206 | if(dp->atapi) return; | |
| 1995/0213 | if(dp->lba){ | |
| 1995/1206 | i = dp->lbasecs - 1; | |
| 1995/0215 | if(ataprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0) | |
| 1995/0213 | return; } else { | |
| 1995/0908/sys/src/9/pc/devata.c:907,912 – 1995/1206/sys/src/9/pc/devata.c:1280,1289 | ||
| 1995/0213 | } dp->cyl = lo + 1; dp->cap = dp->bytes * dp->cyl * dp->heads * dp->sectors; | |
| 1995/1206 | 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); | |
| 1995/0213 | } /* | |
| 1995/0908/sys/src/9/pc/devata.c:920,926 – 1995/1206/sys/src/9/pc/devata.c:1297,1303 | ||
| 1995/0213 | char *field[1]; ulong n; int i; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 | /* * check the partition is big enough | |
| 1995/0908/sys/src/9/pc/devata.c:945,951 – 1995/1206/sys/src/9/pc/devata.c:1322,1328 | ||
| 1995/0213 | /* * parse replacement table. */ | |
| 1995/1206 | n = getfields((char*)buf, line, Nrepl+1, "\n"); | |
| 1995/0213 | if(strncmp(line[0], REPLMAGIC, sizeof(REPLMAGIC)-1)){ dp->repl.p = 0; } else { | |
| 1995/0908/sys/src/9/pc/devata.c:969,981 – 1995/1206/sys/src/9/pc/devata.c:1346,1361 | ||
| 1995/0213 | { Partition *pp; char *line[Npart+1]; | |
| 1995/1206 | char *field[3], namebuf[NAMELEN], *p; | |
| 1995/0213 | ulong n; int i; | |
| 1995/1206 | uchar *buf; | |
| 1995/0213 |
| |
| 1995/1206 | DPRINT("%s: partok %d\n", dp->vol, dp->partok); | |
| 1995/0213 | ||
| 1995/1206 | if(dp->partok) return; | |
| 1995/0213 | /* * we always have a partition for the whole disk * and one for the partition table | |
| 1995/0908/sys/src/9/pc/devata.c:988,993 – 1995/1206/sys/src/9/pc/devata.c:1368,1374 | ||
| 1995/0213 | strcpy(pp->name, "partition"); pp->start = dp->p[0].end - 1; pp->end = dp->p[0].end; | |
| 1995/1206 | pp++; | |
| 1995/0213 | dp->npart = 2; /* | |
| 1995/0908/sys/src/9/pc/devata.c:997,1054 – 1995/1206/sys/src/9/pc/devata.c:1378,1447 | ||
| 1995/0213 | buf = smalloc(Maxxfer); if(waserror()){ | |
| 1995/1206 | DPRINT("%s: atapart error\n", dp->vol); | |
| 1995/0213 | free(buf); nexterror(); } | |
| 1995/1206 | ||
| 1995/0213 | /* | |
| 1995/1206 | * Check if the partitions are described in plan9.ini. * If not, read the disc. | |
| 1995/0213 | */ | |
| 1995/1206 | sprint(namebuf, "%spartition", dp->vol); if((p = getconf(namebuf)) == 0){ /* * read last sector from disk, null terminate. This used * to be the sector we used for the partition tables. * However, this sector is special on some PC's so we've * started to use the second last sector as the partition * table instead. To avoid reconfiguring all our old systems * we first look to see if there is a valid partition * table in the last sector. If so, we use it. Otherwise * we switch to the second last. */ ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); | |
| 1995/0213 | buf[dp->bytes-1] = 0; | |
| 1995/1206 | n = getfields((char*)buf, line, Npart+1, "\n"); if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)){ dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); } | |
| 1995/0213 | } | |
| 1995/1206 | else{ strcpy((char*)buf, p); n = getfields((char*)buf, line, Npart+1, "\n"); } | |
| 1995/0213 | /* * parse partition table. */ | |
| 1995/1206 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ | |
| 1995/0213 | for(i = 1; i < n; i++){ | |
| 1995/1206 | 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; | |
| 1995/0213 | pp++; | |
| 1995/1206 | dp->npart = pp - dp->p; | |
| 1995/0213 | free(buf); poperror(); | |
| 1995/1206 | dp->partok = 1; | |
| 1995/0213 | if(dp->repl.p) atareplinit(dp); } | |
| 1995/0908/sys/src/9/pc/devata.c:1062,1090 – 1995/1206/sys/src/9/pc/devata.c:1455,1480 | ||
| 1995/0213 | * we get an interrupt for every sector transferred */ static void | |
| 1995/1206 | ataintr(Ureg*, void* arg) | |
| 1995/0213 | { Controller *cp; Drive *dp; | |
| 1995/1206 | int loop; uchar *addr; | |
| 1995/0213 |
| |
| 1995/1206 | cp = arg; if((dp = cp->dp) == 0 && cp->cmd != Cedd) return; | |
| 1995/0213 |
| |
| 1995/1206 | ILOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0214 |
| |
| 1995/0213 |
| |
| 1995/0818 |
| |
| 1995/0213 |
| |
| 1995/1206 | 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); } | |
| 1995/0213 | } switch(cp->cmd){ | |
| 1995/0908/sys/src/9/pc/devata.c:1101,1108 – 1995/1206/sys/src/9/pc/devata.c:1491,1498 | ||
| 1995/0213 | loop = 0; while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0) | |
| 1995/0818 | if(++loop > Maxloop) | |
| 1995/0213 |
| |
| 1995/1206 | panic("%s: write cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); | |
| 1995/0213 | addr = cp->buf; if(addr){ addr += cp->sofar*dp->bytes; | |
| 1995/0908/sys/src/9/pc/devata.c:1116,1126 – 1995/1206/sys/src/9/pc/devata.c:1506,1517 | ||
| 1995/0213 | break; case Cread: case Cident: | |
| 1995/1206 | case Cidentd: | |
| 1995/0213 | loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ | |
| 1995/0818 | if(++loop > Maxloop){ | |
| 1995/0213 |
| |
| 1995/1206 | print("%s: read/ident cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); | |
| 1995/0818 | cp->status |= Serr; break; | |
| 1995/0213 | } | |
| 1995/0908/sys/src/9/pc/devata.c:1140,1160 – 1995/1206/sys/src/9/pc/devata.c:1531,1554 | ||
| 1995/0213 | } cp->sofar++; if(cp->sofar > cp->nsecs) | |
| 1995/1206 | print("%s: intr %d %d\n", dp->vol, cp->sofar, cp->nsecs); | |
| 1995/0213 | if(cp->sofar >= cp->nsecs){ cp->lastcmd = cp->cmd; | |
| 1995/1206 | if(cp->cmd == Cidentd) | |
| 1995/0213 | cp->cmd = Cident2; | |
| 1995/1206 | else if(cp->cmd == Cident && (cp->status & Sready) == 0) cp->cmd = Cident2; else cp->cmd = 0; inb(cp->pbase+Pstatus); DPRINT("status %uX, alt %uX\n", inb(cp->pbase+Pstatus), inb(cp->pbase+0x206)); | |
| 1995/0213 | wakeup(&cp->r); } break; | |
| 1995/1206 | case Cfeature: | |
| 1995/0213 | case Cstandby: | |
| 1995/1206 | case Cedd: | |
| 1995/0213 | cp->lastcmd = cp->cmd; cp->cmd = 0; wakeup(&cp->r); | |
| 1995/0908/sys/src/9/pc/devata.c:1163,1201 – 1995/1206/sys/src/9/pc/devata.c:1557,1923 | ||
| 1995/0213 | cp->lastcmd = cp->cmd; cp->cmd = 0; break; | |
| 1995/1206 | case Cpktcmd: atapiintr(cp); break; | |
| 1995/0213 | default: | |
| 1995/1206 | 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)); | |
| 1995/0213 | break; } | |
| 1995/0214 |
| |
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | } void hardclock(void) { | |
| 1995/1206 | int driveno, mask; | |
| 1995/0213 | Drive *dp; Controller *cp; int diff; | |
| 1995/1206 | if((mask = spindownmask) == 0) | |
| 1995/0213 | return; | |
| 1995/1206 | for(driveno = 0; driveno < NDrive && mask; driveno++){ mask &= ~(1<<driveno); if((dp = atadrive[driveno]) == 0) continue; | |
| 1995/0213 | cp = dp->cp; diff = TK2SEC(m->ticks - dp->usetime); | |
| 1995/0214 |
| |
| 1995/1206 | if((dp->state == Sspinning) && (diff >= dp->spindown)){ DPRINT("%s: spindown\n", dp->vol); ILOCK(&cp->reglock); | |
| 1995/0213 | cp->cmd = Cstandby; outb(cp->pbase+Pcount, 0); | |
| 1995/0215 |
| |
| 1995/1206 | outb(cp->pbase+Pdh, dp->dh); | |
| 1995/0213 | outb(cp->pbase+Pcmd, cp->cmd); | |
| 1995/0214 |
| |
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | dp->state = Sstandby; } | |
| 1995/1206 | } } static int isatapi(Drive *dp) { Controller *cp; cp = dp->cp; outb(cp->pbase+Pdh, dp->dh); DPRINT("%s: isatapi %d\n", dp->vol, dp->atapi); if(dp->atapi){ outb(cp->pbase+Pcmd, 0x08); delay(20); } dp->atapi = 0; dp->bytes = 512; microdelay(1); if(inb(cp->pbase+Pstatus)){ DPRINT("%s: isatapi status %ux\n", dp->vol, inb(cp->pbase+Pstatus)); return 0; } if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14){ DPRINT("%s: isatapi cyl %ux %ux\n", dp->vol, inb(cp->pbase+Pcylmsb), inb(cp->pbase+Pcyllsb)); return 0; } dp->atapi = 1; sprint(dp->vol, "atapi%d", dp->driveno); dp->spindown = 0; spindownmask &= ~(1<<dp->driveno); return 1; } static void atapiexec(Drive *dp) { Controller *cp; int loop; cp = dp->cp; if(cmdreadywait(dp)){ error(Eio); } ILOCK(&cp->reglock); cp->nsecs = 1; cp->sofar = 0; cp->error = 0; cp->cmd = Cpktcmd; outb(cp->pbase+Pcount, 0); outb(cp->pbase+Psector, 0); outb(cp->pbase+Pfeature, 0); outb(cp->pbase+Pcyllsb, cp->len); outb(cp->pbase+Pcylmsb, cp->len>>8); outb(cp->pbase+Pdh, dp->dh); outb(cp->pbase+Pcmd, cp->cmd); if(dp->drqintr == 0){ microdelay(1); for(loop = 0; (inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0; loop++){ if(loop < 10000) continue; panic("%s: cmddrqwait: cmd=%lux status=%lux\n", dp->vol, cp->cmd, inb(cp->pbase+Pstatus)); } outss(cp->pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); } IUNLOCK(&cp->reglock); loop = 0; while(waserror()){ DPRINT("%s: interrupted atapiexec\n", dp->vol); if(loop++ > 10){ print("%s: disk error\n", dp->vol); nexterror(); } } atasleep(cp); poperror(); if(loop) nexterror(); if(cp->status & Serr){ DPRINT("%s: Bad packet command %ux\n", dp->vol, cp->error); error(Eio); } } static long atapiio(Drive *dp, char *a, ulong len, ulong offset) { ulong bn, n, o, m; Controller *cp; uchar *buf; int retrycount; cp = dp->cp; buf = smalloc(Maxxfer); qlock(cp->ctlrlock); retrycount = 1; retry: if(waserror()){ dp->partok = 0; if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ dp->vers++; if(retrycount){ retrycount--; goto retry; } } cp->dp = 0; free(buf); qunlock(cp->ctlrlock); nexterror(); } cp->buf = buf; cp->dp = dp; cp->len = dp->bytes; n = len; while(n > 0){ bn = offset / dp->bytes; if(offset > dp->cap-dp->bytes) break; o = offset % dp->bytes; m = dp->bytes - o; if(m > n) m = n; memset(cp->cmdblk, 0, 12); cp->cmdblk[0] = Cread2; cp->cmdblk[2] = bn >> 24; cp->cmdblk[3] = bn >> 16; cp->cmdblk[4] = bn >> 8; cp->cmdblk[5] = bn; cp->cmdblk[7] = 0; cp->cmdblk[8] = 1; atapiexec(dp); if(cp->count != dp->bytes){ print("short read\n"); break; } memmove(a, cp->buf + o, m); n -= m; offset += m; a += m; } poperror(); free(buf); cp->dp = 0; qunlock(cp->ctlrlock); return len-n; } static long atapirwio(Chan *c, char *a, ulong len, ulong offset) { Drive *dp; ulong vers; long rv; dp = atadrive[DRIVE(c->qid.path)]; qlock(dp); if(waserror()){ qunlock(dp); nexterror(); } vers = c->qid.vers; c->qid.vers = dp->vers; if(vers && vers != dp->vers) error(Eio); rv = atapiio(dp, a, len, offset); poperror(); qunlock(dp); return rv; } static void atapipart(Drive *dp) { Controller *cp; uchar *buf, err; Partition *pp; int retrycount; cp = dp->cp; pp = &dp->p[0]; strcpy(pp->name, "disk"); pp->start = 0; pp->end = 0; dp->npart = 1; buf = smalloc(Maxxfer); qlock(cp->ctlrlock); retrycount = 1; retry: if(waserror()){ if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ dp->vers++; if(retrycount){ retrycount--; goto retry; } } cp->dp = 0; free(buf); if((cp->status & Serr) && (cp->error & 0xF0) == 0x20) err = cp->error; else err = 0; qunlock(cp->ctlrlock); if(err == 0x20) return; nexterror(); } cp->buf = buf; cp->dp = dp; cp->len = 8; cp->count = 0; memset(cp->cmdblk, 0, sizeof(cp->cmdblk)); cp->cmdblk[0] = Ccapacity; atapiexec(dp); if(cp->count != 8){ print("cmd=%2.2uX, lastcmd=%2.2uX ", cp->cmd, cp->lastcmd); print("cdsize count %d, status 0x%2.2uX, error 0x%2.2uX\n", cp->count, cp->status, cp->error); error(Eio); } dp->lbasecs = (cp->buf[0]<<24)|(cp->buf[1]<<16)|(cp->buf[2]<<8)|cp->buf[3]; dp->cap = dp->lbasecs*dp->bytes; cp->dp = 0; free(cp->buf); poperror(); qunlock(cp->ctlrlock); pp->end = dp->cap / dp->bytes; dp->partok = 1; } static void atapiintr(Controller *cp) { uchar cause; int count, loop, pbase; uchar *addr; pbase = cp->pbase; cause = inb(pbase+Pcount) & 0x03; DPRINT("%s: atapiintr %uX\n", cp->dp->vol, cause); switch(cause){ case 0: /* data out */ cp->status |= Serr; /*FALLTHROUGH*/ case 1: /* command */ if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(pbase+Perror); wakeup(&cp->r); break; } outss(pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); break; case 2: /* data in */ addr = cp->buf; if(addr == 0){ cp->lastcmd = cp->cmd; cp->cmd = 0; if(cp->status & Serr) cp->error = inb(pbase+Perror); wakeup(&cp->r); break; } loop = 0; while((cp->status & (Serr|Sdrq)) == 0){ if(++loop > Maxloop){ cp->status |= Serr; break; } cp->status = inb(pbase+Pstatus); } if(cp->status & Serr){ cp->lastcmd = cp->cmd; cp->cmd = 0; cp->error = inb(pbase+Perror); print("%s: Cpktcmd status=%uX, error=%uX\n", cp->dp->vol, cp->status, cp->error); wakeup(&cp->r); break; } count = inb(pbase+Pcyllsb)|(inb(pbase+Pcylmsb)<<8); if (count > Maxxfer) count = Maxxfer; inss(pbase+Pdata, addr, count/2); cp->count = count; cp->lastcmd = cp->cmd; break; case 3: /* status */ cp->lastcmd = cp->cmd; cp->cmd = 0; if(cp->status & Serr) cp->error = inb(cp->pbase+Perror); wakeup(&cp->r); break; | |
| 1995/0213 | } } | |
| 1995/1206/sys/src/9/pc/devata.c:76,82 – 1995/1208/sys/src/9/pc/devata.c:76,82 (short | long) | ||
| 1995/1206 | Npart= 20+2, /* 8 sub partitions, disk, and partition */ | |
| 1995/0213 | Nrepl= 64, /* maximum replacement blocks */ | |
| 1995/0818 | ||
| 1995/1206 |
| |
| 1995/1208 | Hardtimeout= 6000, /* disk access timeout (ms) */ | |
| 1995/1206 | NCtlr= 4, NDrive= NCtlr*2, | |
| 1995/1206/sys/src/9/pc/devata.c:339,346 – 1995/1208/sys/src/9/pc/devata.c:339,348 | ||
| 1995/1206 | if(driveno & 0x01) drive->dh |= DHslave; drive->vers = 1; | |
| 1995/1208 | if(atapi){ sprint(drive->vol, "atapi%d", drive->driveno); | |
| 1995/1206 | drive->atapi = 1; | |
| 1995/1208 | } | |
| 1995/1206 | atadrive[driveno] = drive; } | |
| 1995/1206/sys/src/9/pc/devata.c:384,390 – 1995/1208/sys/src/9/pc/devata.c:386,392 | ||
| 1995/1206 | * 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 | |
| 1995/1208 | * to the Cedd (Micronics M54Li + Sanyo CRD-254P) so let's check for the | |
| 1995/1206 | * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ | |
| 1995/1206/sys/src/9/pc/devata.c:401,406 – 1995/1208/sys/src/9/pc/devata.c:403,410 | ||
| 1995/1206 | goto skipedd; } if(atactlrwait(ctlr, DHmagic, 0, MS2TK(1)) || waserror()){ | |
| 1995/1208 | DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); | |
| 1995/1206 | xfree(ctlr); return -1; } | |
| 1995/1206/sys/src/9/pc/devata.c:1069,1086 – 1995/1208/sys/src/9/pc/devata.c:1073,1079 | ||
| 1995/0213 | nexterror(); } | |
| 1995/1206 |
| |
| 1995/0213 | ||
| 1995/1208 | cmd = Cident; | |
| 1995/1206 | retryatapi: ILOCK(&cp->reglock); | |
| 1995/0213 | cp->nsecs = 1; | |
| 1995/1206/sys/src/9/pc/devata.c:1092,1103 – 1995/1208/sys/src/9/pc/devata.c:1085,1096 | ||
| 1995/1206 | outb(cp->pbase+Pcmd, cmd); IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/1208 | DPRINT("%s: ident command %ux sent\n", dp->vol, cmd); | |
| 1995/0818 | atasleep(cp); | |
| 1995/0213 | if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s: bad disk ident status\n", dp->vol); | |
| 1995/1208 | if(cp->error & Eabort){ | |
| 1995/1206 | if(isatapi(dp)){ cmd = Cidentd; goto retryatapi; | |
| 1995/1206/sys/src/9/pc/devata.c:1134,1140 – 1995/1208/sys/src/9/pc/devata.c:1127,1133 | ||
| 1995/1206 | dp->cyl = ip->cyls; dp->heads = ip->heads; dp->sectors = ip->s2t; | |
| 1995/1208 | XPRINT("%s: %s %d/%d/%d CHS %d bytes\n", | |
| 1995/1206 | dp->vol, id, dp->cyl, dp->heads, dp->sectors, dp->cap); if(ip->cvalid&(1<<0)){ | |
| 1995/1206/sys/src/9/pc/devata.c:1142,1148 – 1995/1208/sys/src/9/pc/devata.c:1135,1141 | ||
| 1995/1206 | dp->cyl = ip->ccyls; dp->heads = ip->cheads; dp->sectors = ip->cs2t; | |
| 1995/1208 | XPRINT("%s: changed to %d cyl %d head %d sec\n", | |
| 1995/1206 | dp->vol, dp->cyl, dp->heads, dp->sectors); } | |
| 1995/1206/sys/src/9/pc/devata.c:1151,1157 – 1995/1208/sys/src/9/pc/devata.c:1144,1150 | ||
| 1995/0213 | dp->lba = 1; | |
| 1995/1206 | dp->lbasecs = lbasecs; dp->cap = dp->bytes * dp->lbasecs; | |
| 1995/1208 | XPRINT("%s: LBA: %s %d sectors %d bytes\n", | |
| 1995/1206 | dp->vol, id, dp->lbasecs, dp->cap); | |
| 1995/0213 | } else { dp->lba = 0; | |
| 1995/1206/sys/src/9/pc/devata.c:1534,1548 – 1995/1208/sys/src/9/pc/devata.c:1527,1544 | ||
| 1995/1206 | print("%s: intr %d %d\n", dp->vol, cp->sofar, cp->nsecs); | |
| 1995/0213 | if(cp->sofar >= cp->nsecs){ cp->lastcmd = cp->cmd; | |
| 1995/1208 | #ifdef notdef | |
| 1995/1206 | if(cp->cmd == Cidentd) | |
| 1995/0213 | cp->cmd = Cident2; | |
| 1995/1206 | else if(cp->cmd == Cident && (cp->status & Sready) == 0) cp->cmd = Cident2; | |
| 1995/1208 | #else if(cp->cmd != Cread && (cp->status & (Sbusy|Sready)) != Sready) cp->cmd = Cident2; #endif /* notdef */ | |
| 1995/1206 | else cp->cmd = 0; inb(cp->pbase+Pstatus); | |
| 1995/0213 | wakeup(&cp->r); } break; | |
| 1995/1206/sys/src/9/pc/devata.c:1614,1622 – 1995/1208/sys/src/9/pc/devata.c:1610,1619 | ||
| 1995/1206 | cp = dp->cp; outb(cp->pbase+Pdh, dp->dh); DPRINT("%s: isatapi %d\n", dp->vol, dp->atapi); | |
| 1995/1208 | 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; | |
| 1995/1206 | } dp->atapi = 0; dp->bytes = 512; | |
| 1995/1206/sys/src/9/pc/devata.c:1688,1694 – 1995/1208/sys/src/9/pc/devata.c:1685,1691 | ||
| 1995/1206 | nexterror(); if(cp->status & Serr){ | |
| 1995/1208 | DPRINT("%s: Bad packet command %ux, error %ux\n", dp->vol, cp->cmdblk[0], cp->error); | |
| 1995/1206 | error(Eio); } } | |
| 1995/1206/sys/src/9/pc/devata.c:1705,1711 – 1995/1208/sys/src/9/pc/devata.c:1702,1708 | ||
| 1995/1206 | buf = smalloc(Maxxfer); qlock(cp->ctlrlock); | |
| 1995/1208 | retrycount = 2; | |
| 1995/1206 | retry: if(waserror()){ dp->partok = 0; | |
| 1995/1206/sys/src/9/pc/devata.c:1804,1810 – 1995/1208/sys/src/9/pc/devata.c:1801,1807 | ||
| 1995/1206 | buf = smalloc(Maxxfer); qlock(cp->ctlrlock); | |
| 1995/1208 | retrycount = 2; | |
| 1995/1206 | retry: if(waserror()){ if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ | |
| 1995/1206/sys/src/9/pc/devata.c:1817,1823 – 1995/1208/sys/src/9/pc/devata.c:1814,1820 | ||
| 1995/1206 | cp->dp = 0; free(buf); if((cp->status & Serr) && (cp->error & 0xF0) == 0x20) | |
| 1995/1208 | err = cp->error & 0xF0; | |
| 1995/1206 | else err = 0; qunlock(cp->ctlrlock); | |
| 1995/1208/sys/src/9/pc/devata.c:190,196 – 1995/1209/sys/src/9/pc/devata.c:190,196 (short | long) | ||
| 1995/0213 | static void ataparams(Drive*); static void atapart(Drive*); static int ataprobe(Drive*, int, int, int); | |
| 1995/1206 |
| |
| 1995/1209 | static void atasleep(Controller*, int); | |
| 1995/0213 | ||
| 1995/1206 | static int isatapi(Drive*); static long atapirwio(Chan*, char*, ulong, ulong); | |
| 1995/1208/sys/src/9/pc/devata.c:411,417 – 1995/1209/sys/src/9/pc/devata.c:411,417 | ||
| 1995/1206 | setvec(irq, ataintr, ctlr); ctlr->cmd = Cedd; outb(port+Pcmd, Cedd); | |
| 1995/1209 | atasleep(ctlr, Hardtimeout); | |
| 1995/1206 | poperror(); /* | |
| 1995/1208/sys/src/9/pc/devata.c:832,840 – 1995/1209/sys/src/9/pc/devata.c:832,840 | ||
| 1995/0213 | } | |
| 1995/0818 | static void | |
| 1995/1209 | atasleep(Controller *cp, int ms) | |
| 1995/0818 | { | |
| 1995/1209 | tsleep(&cp->r, cmddone, cp, ms); | |
| 1995/0818 | if(cp->cmd && cp->cmd != Cident2){ | |
| 1995/1206 | DPRINT("ata%d: cmd 0x%uX timeout\n", cp->ctlrno, cp->cmd); | |
| 1995/0818 | error("ata drive timeout"); | |
| 1995/1208/sys/src/9/pc/devata.c:942,948 – 1995/1209/sys/src/9/pc/devata.c:942,948 | ||
| 1995/0213 | nexterror(); } } | |
| 1995/0818 |
| |
| 1995/1209 | atasleep(cp, Hardtimeout); | |
| 1995/0213 | dp->usetime = m->ticks; | |
| 1995/1206 | dp->state = Sspinning; | |
| 1995/0213 | poperror(); | |
| 1995/1208/sys/src/9/pc/devata.c:996,1002 – 1995/1209/sys/src/9/pc/devata.c:996,1002 | ||
| 1995/1206 | outb(cp->pbase+Pcmd, Cfeature); IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0818 |
| |
| 1995/1209 | atasleep(cp, Hardtimeout); | |
| 1995/0213 | ||
| 1995/1206 | if(cp->status & Serr) DPRINT("%s: setbuf err: status %lux, err %lux\n", | |
| 1995/1208/sys/src/9/pc/devata.c:1086,1092 – 1995/1209/sys/src/9/pc/devata.c:1086,1092 | ||
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/1208 | DPRINT("%s: ident command %ux sent\n", dp->vol, cmd); | |
| 1995/0818 |
| |
| 1995/1209 | atasleep(cp, 1000); | |
| 1995/0818 | ||
| 1995/0213 | if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s: bad disk ident status\n", dp->vol); | |
| 1995/1208/sys/src/9/pc/devata.c:1203,1209 – 1995/1209/sys/src/9/pc/devata.c:1203,1209 | ||
| 1995/0213 | outb(cp->pbase+Pcmd, Cread); | |
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/0818 |
| |
| 1995/1209 | atasleep(cp, Hardtimeout); | |
| 1995/0213 | ||
| 1995/1206 | if(cp->status & Serr){ DPRINT("%s: probe err: status %lux, err %lux\n", | |
| 1995/1208/sys/src/9/pc/devata.c:1527,1541 – 1995/1209/sys/src/9/pc/devata.c:1527,1534 | ||
| 1995/1206 | print("%s: intr %d %d\n", dp->vol, cp->sofar, cp->nsecs); | |
| 1995/0213 | if(cp->sofar >= cp->nsecs){ cp->lastcmd = cp->cmd; | |
| 1995/1208 |
| |
| 1995/1206 |
| |
| 1995/1209 | if(cp->cmd != Cread) | |
| 1995/0213 | cp->cmd = Cident2; | |
| 1995/1206 |
| |
| 1995/1208 |
| |
| 1995/1206 | else cp->cmd = 0; inb(cp->pbase+Pstatus); | |
| 1995/1208/sys/src/9/pc/devata.c:1679,1685 – 1995/1209/sys/src/9/pc/devata.c:1672,1678 | ||
| 1995/1206 | nexterror(); } } | |
| 1995/1209 | atasleep(cp, Hardtimeout); | |
| 1995/1206 | poperror(); if(loop) nexterror(); | |
| 1995/1209/sys/src/9/pc/devata.c:1384,1408 – 1995/1218/sys/src/9/pc/devata.c:1384,1414 (short | long) | ||
| 1995/1206 | sprint(namebuf, "%spartition", dp->vol); if((p = getconf(namebuf)) == 0){ /* | |
| 1995/1218 | * Read second last sector from disk, null terminate. * The last sector used to hold the partition tables. | |
| 1995/1206 | * 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 | |
| 1995/1218 | * we still check if there is a valid partition table in * the last sector if none is found in the second last. | |
| 1995/1206 | */ | |
| 1995/1218 | ataxfer(dp, &dp->p[0], Cread, dp->p[0].end-1, dp->bytes, buf); | |
| 1995/0213 | buf[dp->bytes-1] = 0; | |
| 1995/1206 | n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ | |
| 1995/1206 | dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; | |
| 1995/1218 | } else{ | |
| 1995/1206 | ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218 | if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)){ dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; } | |
| 1995/1206 | } | |
| 1995/0213 | } | |
| 1995/1206 | else{ | |
| 1995/1218/sys/src/9/pc/devata.c:1392,1398 – 1995/1219/sys/src/9/pc/devata.c:1392,1399 (short | long) | ||
| 1995/1218 | * we still check if there is a valid partition table in * the last sector if none is found in the second last. | |
| 1995/1206 | */ | |
| 1995/1218 |
| |
| 1995/1219 | print("R%d|", dp->p[0].end-2); ataxfer(dp, &dp->p[0], Cread, dp->p[0].end-2, dp->bytes, buf); | |
| 1995/0213 | buf[dp->bytes-1] = 0; | |
| 1995/1206 | n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ | |
| 1995/1218/sys/src/9/pc/devata.c:1399,1406 – 1995/1219/sys/src/9/pc/devata.c:1400,1409 | ||
| 1995/1206 | dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; | |
| 1995/1219 | print("OK%d|", dp->p[1].start); | |
| 1995/1218 | } else{ | |
| 1995/1219 | print("r%d|", dp->p[1].start); | |
| 1995/1206 | ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218/sys/src/9/pc/devata.c:1408,1414 – 1995/1219/sys/src/9/pc/devata.c:1411,1419 | ||
| 1995/1218 | dp->p[0].end--; dp->p[1].start--; dp->p[1].end--; | |
| 1995/1219 | print("nok%d|", dp->p[1].start); | |
| 1995/1218 | } | |
| 1995/1219 | else print("ok%d|", dp->p[1].start); | |
| 1995/1206 | } | |
| 1995/0213 | } | |
| 1995/1206 | else{ | |
| 1995/1219/sys/src/9/pc/devata.c:1392,1419 – 1995/1221/sys/src/9/pc/devata.c:1392,1414 (short | long) | ||
| 1995/1218 | * we still check if there is a valid partition table in * the last sector if none is found in the second last. | |
| 1995/1206 | */ | |
| 1995/1219 |
| |
| 1995/1221 | i = 0; ataxfer(dp, &dp->p[0], Cread, (dp->p[0].end-2)*dp->bytes, dp->bytes, buf); | |
| 1995/0213 | buf[dp->bytes-1] = 0; | |
| 1995/1206 | n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218 |
| |
| 1995/1206 |
| |
| 1995/1219 |
| |
| 1995/1218 |
| |
| 1995/1221 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0) i = 1; | |
| 1995/1218 | else{ | |
| 1995/1219 |
| |
| 1995/1206 | ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; n = getfields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1218 |
| |
| 1995/1219 |
| |
| 1995/1218 |
| |
| 1995/1219 |
| |
| 1995/1221 | 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--; | |
| 1995/1206 | } | |
| 1995/0213 | } | |
| 1995/1206 | else{ | |
| 1995/1221/sys/src/9/pc/devata.c:62,67 – 1996/0112/sys/src/9/pc/devata.c:62,69 (short | long) | ||
| 1995/0213 | ||
| 1995/1206 | Cpktcmd= 0xA0, Cidentd= 0xA1, | |
| 1996/0112 | Ctur= 0x00, Creqsense= 0x03, | |
| 1995/1206 | Ccapacity= 0x25, Cread2= 0x28, | |
| 1995/1221/sys/src/9/pc/devata.c:1073,1079 – 1996/0112/sys/src/9/pc/devata.c:1075,1084 | ||
| 1995/0213 | nexterror(); } | |
| 1995/1208 |
| |
| 1996/0112 | if(dp->atapi) cmd = Cidentd; else cmd = Cident; | |
| 1995/1206 | retryatapi: ILOCK(&cp->reglock); | |
| 1995/0213 | cp->nsecs = 1; | |
| 1995/1221/sys/src/9/pc/devata.c:1803,1808 – 1996/0112/sys/src/9/pc/devata.c:1808,1814 | ||
| 1995/1208 | retrycount = 2; | |
| 1995/1206 | retry: if(waserror()){ | |
| 1996/0112 | DPRINT("atapipart: cmd %uX error %uX\n", cp->cmd, cp->error); | |
| 1995/1206 | if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ dp->vers++; if(retrycount){ | |
| 1995/1221/sys/src/9/pc/devata.c:1824,1829 – 1996/0112/sys/src/9/pc/devata.c:1830,1848 | ||
| 1995/1206 | cp->buf = buf; cp->dp = dp; | |
| 1996/0112 | 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); } | |
| 1995/1206 | cp->len = 8; cp->count = 0; | |
| 1996/0112/sys/src/9/pc/devata.c:49,54 – 1996/0210/sys/src/9/pc/devata.c:49,58 (short | long) | ||
| 1995/0213 | Serr= (1<<0), Pcmd= 7, /* cmd port (write) */ | |
| 1996/0210 | Pctrl= 0x206, /* device control, alternate status */ nIEN= (1<<1), Srst= (1<<2), | |
| 1995/0213 | /* commands */ | |
| 1995/1206 | Cfirst= 0xFF, /* pseudo command for initialisation */ | |
| 1995/0213 | Cread= 0x20, | |
| 1996/0112/sys/src/9/pc/devata.c:152,158 – 1996/0210/sys/src/9/pc/devata.c:156,162 | ||
| 1995/0213 | int pbase; /* base port */ | |
| 1995/1206 | uchar ctlrno; | |
| 1996/0210 | uchar resetok; | |
| 1995/0213 | /* * current operation | |
| 1996/0112/sys/src/9/pc/devata.c:354,360 – 1996/0210/sys/src/9/pc/devata.c:358,364 | ||
| 1995/1206 | { Controller *ctlr; int atapi, mask, port; | |
| 1996/0210 | uchar error, status, msb, lsb; | |
| 1995/1206 | /* * Check the existence of a controller by verifying a sensible | |
| 1996/0112/sys/src/9/pc/devata.c:377,388 – 1996/0210/sys/src/9/pc/devata.c:381,393 | ||
| 1995/1206 | ctlr->ctlrno = ctlrno; ctlr->lastcmd = 0xFF; | |
| 1996/0210 | ||
| 1995/1206 | /* * 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 | |
| 1996/0210 | * seem to implement the control-block registers; do it if requested. | |
| 1995/1206 | * 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 | |
| 1996/0112/sys/src/9/pc/devata.c:392,397 – 1996/0210/sys/src/9/pc/devata.c:397,413 | ||
| 1995/1206 | * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ | |
| 1996/0210 | if(ctlr->resetok){ outb(port+Pctrl, Srst|nIEN); microdelay(1); outb(port+Pctrl, 0); if(atactlrwait(ctlr, DHmagic, 0, 100)){ DPRINT("ata%d: Srst status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); } } | |
| 1995/1206 | atapi = 0; mask = 0; status = inb(port+Pstatus); | |
| 1996/0112/sys/src/9/pc/devata.c:405,412 – 1996/0210/sys/src/9/pc/devata.c:421,428 | ||
| 1995/1206 | goto skipedd; } if(atactlrwait(ctlr, DHmagic, 0, MS2TK(1)) || waserror()){ | |
| 1995/1208 |
| |
| 1996/0210 | DPRINT("ata%d: Cedd status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); | |
| 1995/1206 | xfree(ctlr); return -1; } | |
| 1996/0112/sys/src/9/pc/devata.c:447,455 – 1996/0210/sys/src/9/pc/devata.c:463,477 | ||
| 1995/1206 | 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; | |
| 1996/0210 | 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; } | |
| 1995/1206 | } skipedd: | |
| 1996/0112/sys/src/9/pc/devata.c:514,521 – 1996/0210/sys/src/9/pc/devata.c:536,543 | ||
| 1995/1206 | DPRINT("ata%d: opt spindownmask %ux\n", ctlrno, spindownmask); } | |
| 1996/0210 | else if(strcmp(isa.opt[i], "reset") == 0) atactlr[ctlrno]->resetok = 1; | |
| 1995/1206 | } } | |
| 1995/0213 | } | |
| 1996/0112/sys/src/9/pc/devata.c:1091,1097 – 1996/0210/sys/src/9/pc/devata.c:1113,1122 | ||
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | ||
| 1995/1208 | DPRINT("%s: ident command %ux sent\n", dp->vol, cmd); | |
| 1995/1209 |
| |
| 1996/0210 | if(cmd == Cident) atasleep(cp, 3000); else atasleep(cp, 30000); | |
| 1995/0818 | ||
| 1995/0213 | if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s: bad disk ident status\n", dp->vol); | |
| 1996/0210/sys/src/9/pc/devata.c:399,407 – 1996/0215/sys/src/9/pc/devata.c:399,407 (short | long) | ||
| 1995/1206 | */ | |
| 1996/0210 | if(ctlr->resetok){ outb(port+Pctrl, Srst|nIEN); | |
| 1996/0215 | delay(10); | |
| 1996/0210 | outb(port+Pctrl, 0); | |
| 1996/0215 | if(atactlrwait(ctlr, DHmagic, 0, MS2TK(20)){ | |
| 1996/0210 | DPRINT("ata%d: Srst status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); | |
| 1996/0210/sys/src/9/pc/devata.c:1116,1122 – 1996/0215/sys/src/9/pc/devata.c:1116,1122 | ||
| 1996/0210 | if(cmd == Cident) atasleep(cp, 3000); else | |
| 1996/0215 | atasleep(cp, 10000); | |
| 1995/0818 | ||
| 1995/0213 | if(cp->status & Serr){ | |
| 1995/1206 | DPRINT("%s: bad disk ident status\n", dp->vol); | |
| 1996/0215/sys/src/9/pc/devata.c:401,407 – 1996/0216/sys/src/9/pc/devata.c:401,407 (short | long) | ||
| 1996/0210 | outb(port+Pctrl, Srst|nIEN); | |
| 1996/0215 | delay(10); | |
| 1996/0210 | outb(port+Pctrl, 0); | |
| 1996/0215 |
| |
| 1996/0216 | if(atactlrwait(ctlr, DHmagic, 0, MS2TK(20))){ | |
| 1996/0210 | DPRINT("ata%d: Srst status %ux/%ux/%ux\n", ctlrno, inb(port+Pstatus), inb(port+Pcylmsb), inb(port+Pcyllsb)); xfree(ctlr); | |
| 1996/0216/sys/src/9/pc/devata.c:10,16 – 1996/0223/sys/src/9/pc/devata.c:10,15 (short | long) | ||
| 1995/0213 | #include "io.h" #include "../port/error.h" | |
| 1995/0215 | #define DPRINT if(0)print | |
| 1995/1206 | #define XPRINT if(0)print | |
| 1996/0223/sys/src/9/pc/devata.c:1344,1355 – 1996/0315/sys/src/9/pc/devata.c:1344,1355 (short | long) | ||
| 1995/0213 | /* * parse replacement table. */ | |
| 1995/1206 |
| |
| 1996/0315 | n = parsefields((char*)buf, line, Nrepl+1, "\n"); | |
| 1995/0213 | if(strncmp(line[0], REPLMAGIC, sizeof(REPLMAGIC)-1)){ dp->repl.p = 0; } else { for(dp->repl.nrepl = 0, i = 1; i < n; i++, dp->repl.nrepl++){ | |
| 1996/0315 | if(parsefields(line[i], field, 1, " ") != 1) | |
| 1995/0213 | break; dp->repl.blk[dp->repl.nrepl] = strtoul(field[0], 0, 0); if(dp->repl.blk[dp->repl.nrepl] <= 0) | |
| 1996/0223/sys/src/9/pc/devata.c:1424,1436 – 1996/0315/sys/src/9/pc/devata.c:1424,1436 | ||
| 1995/1221 | i = 0; ataxfer(dp, &dp->p[0], Cread, (dp->p[0].end-2)*dp->bytes, dp->bytes, buf); | |
| 1995/0213 | buf[dp->bytes-1] = 0; | |
| 1995/1206 |
| |
| 1996/0315 | n = parsefields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1221 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0) i = 1; | |
| 1995/1218 | else{ | |
| 1995/1206 | ataxfer(dp, &dp->p[1], Cread, 0, dp->bytes, buf); buf[dp->bytes-1] = 0; | |
| 1996/0315 | n = parsefields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1221 | if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)) i = 1; } | |
| 1996/0223/sys/src/9/pc/devata.c:1442,1448 – 1996/0315/sys/src/9/pc/devata.c:1442,1448 | ||
| 1995/0213 | } | |
| 1995/1206 | else{ strcpy((char*)buf, p); | |
| 1996/0315 | n = parsefields((char*)buf, line, Npart+1, "\n"); | |
| 1995/1206 | } | |
| 1995/0213 | /* | |
| 1996/0223/sys/src/9/pc/devata.c:1450,1456 – 1996/0315/sys/src/9/pc/devata.c:1450,1456 | ||
| 1995/0213 | */ | |
| 1995/1206 | if(n > 0 && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){ | |
| 1995/0213 | for(i = 1; i < n; i++){ | |
| 1995/1206 |
| |
| 1996/0315 | if(parsefields(line[i], field, 3, " ") != 3) | |
| 1995/1206 | break; if(pp >= &dp->p[Npart]) break; | |
| 1996/0315/sys/src/9/pc/devata.c:640,645 – 1996/0803/sys/src/9/pc/devata.c:640,647 (short | long) | ||
| 1995/0213 | return; | |
| 1995/1206 | dp = atadrive[DRIVE(c->qid.path)]; | |
| 1996/0803 | if(dp == 0) return; | |
| 1995/1206 | p = &dp->p[PART(c->qid.path)]; | |
| 1995/0213 | if(strcmp(p->name, "partition") != 0) return; | |
| 1996/0803/sys/src/9/pc/devata.c:203,209 – 1996/1225/sys/src/9/pc/devata.c:203,209 (short | long) | ||
| 1995/1206 | static void atapiintr(Controller*); | |
| 1995/0213 | static int | |
| 1995/1206 |
| |
| 1996/1225 | atagen(Chan *c, Dirtab*, int, int s, Dir *dirp) | |
| 1995/0213 | { Qid qid; int drive; | |
| 1996/1225/sys/src/9/pc/devata.c:155,160 – 1997/0327/sys/src/9/pc/devata.c:155,161 (short | long) | ||
| 1995/0213 | int pbase; /* base port */ | |
| 1995/1206 | uchar ctlrno; | |
| 1997/0327 | int tbdf; | |
| 1996/0210 | uchar resetok; | |
| 1995/0213 | /* | |
| 1996/1225/sys/src/9/pc/devata.c:180,186 – 1997/0327/sys/src/9/pc/devata.c:181,187 | ||
| 1995/1206 | static QLock atactlrlock[NCtlr]; static Drive *atadrive[NDrive]; static int spindownmask; | |
| 1997/0327 | static int have640b; | |
| 1995/1206 | static int pbase[NCtlr] = { Pbase0, Pbase1, Pbase2, Pbase3, }; | |
| 1996/1225/sys/src/9/pc/devata.c:196,201 – 1997/0327/sys/src/9/pc/devata.c:197,203 | ||
| 1995/0213 | static void atapart(Drive*); static int ataprobe(Drive*, int, int, int); | |
| 1995/1209 | static void atasleep(Controller*, int); | |
| 1997/0327 | static void ataclock(void); | |
| 1995/0213 | ||
| 1995/1206 | static int isatapi(Drive*); static long atapirwio(Chan*, char*, ulong, ulong); | |
| 1996/1225/sys/src/9/pc/devata.c:203,209 – 1997/0327/sys/src/9/pc/devata.c:205,211 | ||
| 1995/1206 | static void atapiintr(Controller*); | |
| 1995/0213 | static int | |
| 1996/1225 |
| |
| 1997/0327 | atagen(Chan* c, Dirtab*, int, int s, Dir* dirp) | |
| 1995/0213 | { Qid qid; int drive; | |
| 1996/1225/sys/src/9/pc/devata.c:237,246 – 1997/0327/sys/src/9/pc/devata.c:239,246 | ||
| 1995/1206 | static void cmd640b(void) | |
| 1995/0213 | { | |
| 1995/1206 |
| |
| 1997/0327 | Pcidev *p; int r; | |
| 1995/0213 | ||
| 1995/1206 | /* * Look for CMD640B dual PCI controllers. Amongst other | |
| 1996/1225/sys/src/9/pc/devata.c:249,260 – 1997/0327/sys/src/9/pc/devata.c:249,257 | ||
| 1995/1206 | * controllers this is, so if one is found then all controller * pairs are synchronised. */ | |
| 1997/0327 | p = 0; while(p = pcimatch(p, 0x1095, 0x0640)){ have640b++; | |
| 1995/1206 | /* * If one is found, make sure read-ahead is disabled on all * drives and that the 2nd controller is enabled: | |
| 1996/1225/sys/src/9/pc/devata.c:263,303 – 1997/0327/sys/src/9/pc/devata.c:260,293 | ||
| 1995/1206 | * bit 3 - 2nd controller enable * reg 0x57: bit 3 - drive 1 read ahead disable * bit 2 - drive 0 read ahead disable | |
| 1997/0327 | r = pcicfgr8(p, 0x51); r |= 0xC8; pcicfgw8(p, 0x51, r); r = pcicfgr8(p, 0x57); r |= 0x0C; pcicfgw8(p, 0x57, r); | |
| 1995/1206 | } | |
| 1995/0213 | ||
| 1995/1206 | static void rz1000(void) { | |
| 1997/0327 | Pcidev *p; ulong r; | |
| 1995/0215 | ||
| 1995/1206 | /* * Look for PC-Tech RZ1000 controllers and turn off prefetch. * This is overkill, but cheap. */ | |
| 1997/0327 | p = 0; while(p = pcimatch(p, 0x1042, 0)){ if(p->did != 0x1000 && p->did != 0x1001) | |
| 1995/1206 | continue; | |
| 1997/0327 | r = pcicfgr32(p, 0x40); r &= ~0x2000; pcicfgw32(p, 0x40, r); | |
| 1995/1206 | } | |
| 1995/0215 | ||
| 1995/1206 | static int | |
| 1996/1225/sys/src/9/pc/devata.c:378,383 – 1997/0327/sys/src/9/pc/devata.c:368,374 | ||
| 1995/1206 | return -1; ctlr->pbase = port; ctlr->ctlrno = ctlrno; | |
| 1997/0327 | ctlr->tbdf = BUSUNKNOWN; | |
| 1995/1206 | ctlr->lastcmd = 0xFF; | |
| 1996/0210 | ||
| 1996/1225/sys/src/9/pc/devata.c:414,420 – 1997/0327/sys/src/9/pc/devata.c:405,411 | ||
| 1995/1206 | inb(port+Pcylmsb), inb(port+Pcyllsb)); if(status == 0 && inb(port+Pcylmsb) == 0xEB && inb(port+Pcyllsb) == 0x14){ DPRINT("ata%d: ATAPI ok\n", ctlrno); | |
| 1997/0327 | intrenable(irq, ataintr, ctlr, ctlr->tbdf); | |
| 1995/1206 | atapi |= 0x01; mask |= 0x01; goto skipedd; | |
| 1996/1225/sys/src/9/pc/devata.c:425,431 – 1997/0327/sys/src/9/pc/devata.c:416,422 | ||
| 1995/1206 | xfree(ctlr); return -1; } | |
| 1997/0327 | intrenable(irq, ataintr, ctlr, ctlr->tbdf); | |
| 1995/1206 | ctlr->cmd = Cedd; outb(port+Pcmd, Cedd); | |
| 1995/1209 | atasleep(ctlr, Hardtimeout); | |
| 1996/1225/sys/src/9/pc/devata.c:480,486 – 1997/0327/sys/src/9/pc/devata.c:471,477 | ||
| 1995/1206 | } atactlr[ctlrno] = ctlr; | |
| 1997/0327 | if(have640b && (ctlrno & 0x01)) | |
| 1995/1206 | ctlr->ctlrlock = &atactlrlock[ctlrno-1]; else ctlr->ctlrlock = &atactlrlock[ctlrno]; | |
| 1996/1225/sys/src/9/pc/devata.c:493,499 – 1997/0327/sys/src/9/pc/devata.c:484,490 | ||
| 1995/1206 | return 0; } | |
| 1997/0327 | static void | |
| 1995/1206 | atactlrreset(void) { int ctlrno, driveno, i, slave, spindown; | |
| 1996/1225/sys/src/9/pc/devata.c:509,515 – 1997/0327/sys/src/9/pc/devata.c:500,506 | ||
| 1995/1206 | if(isa.irq == 0 && (isa.irq = defirq[ctlrno]) == 0) continue; | |
| 1997/0327 | if(atactlrprobe(ctlrno, VectorPIC+isa.irq)) | |
| 1995/1206 | continue; | |
| 1995/0213 | ||
| 1995/1206 | for(i = 0; i < isa.nopt; i++){ | |
| 1996/1225/sys/src/9/pc/devata.c:539,562 – 1997/0327/sys/src/9/pc/devata.c:530,546 | ||
| 1996/0210 | atactlr[ctlrno]->resetok = 1; | |
| 1995/1206 | } } | |
| 1995/0213 |
| |
| 1995/1206 |
| |
| 1997/0327 | if(spindownmask) addclock0link(ataclock); | |
| 1995/1206 | } | |
| 1995/0213 |
| |
| 1997/0327 | static Chan* ataattach(char* spec) | |
| 1995/0213 | { | |
| 1995/1206 | int driveno; | |
| 1995/0213 | Drive *dp; | |
| 1996/1225/sys/src/9/pc/devata.c:600,638 – 1997/0327/sys/src/9/pc/devata.c:584,610 | ||
| 1995/0213 | return devattach('H', spec); } | |
| 1997/0327 | static int atawalk(Chan* c, char* name) | |
| 1995/0213 | { | |
| 1997/0327 | static void atastat(Chan* c, char* dp) | |
| 1995/0213 | { devstat(c, dp, 0, 0, atagen); } | |
| 1997/0327 | static Chan* ataopen(Chan* c, int omode) | |
| 1995/0213 | { return devopen(c, omode, 0, 0, atagen); } void | |
| 1995/1206 |
| |
| 1997/0327 | ataclose(Chan* c) | |
| 1995/0213 | { | |
| 1995/1206 | Drive *dp; | |
| 1995/0213 | Partition *p; | |
| 1996/1225/sys/src/9/pc/devata.c:657,677 – 1997/0327/sys/src/9/pc/devata.c:629,637 | ||
| 1995/0213 | poperror(); } | |
| 1995/1206 |
| |
| 1997/0327 | static long ataread(Chan* c, void* a, long n, ulong offset) | |
| 1995/0213 | { | |
| 1995/1206 |
| |
| 1995/0213 |
| |
| 1996/1225/sys/src/9/pc/devata.c:723,735 – 1997/0327/sys/src/9/pc/devata.c:683,689 | ||
| 1995/0213 | return rv; } | |
| 1997/0327 | static long | |
| 1995/0213 | atawrite(Chan *c, void *a, long n, ulong offset) { Drive *dp; | |
| 1996/1225/sys/src/9/pc/devata.c:802,813 – 1997/0327/sys/src/9/pc/devata.c:756,761 | ||
| 1995/0213 | return rv; } | |
| 1996/1225/sys/src/9/pc/devata.c:1601,1608 – 1997/0327/sys/src/9/pc/devata.c:1549,1556 | ||
| 1995/1206 | IUNLOCK(&cp->reglock); | |
| 1995/0213 | } | |
| 1997/0327 | static void ataclock(void) | |
| 1995/0213 | { | |
| 1995/1206 | int driveno, mask; | |
| 1995/0213 | Drive *dp; | |
| 1996/1225/sys/src/9/pc/devata.c:1962,1964 – 1997/0327/sys/src/9/pc/devata.c:1910,1930 | ||
| 1995/1206 | break; | |
| 1995/0213 | } } | |
| 1997/0327 | Dev atadevtab = { devreset, devinit, ataattach, devclone, atawalk, atastat, ataopen, devcreate, ataclose, ataread, devbread, atawrite, devbwrite, devremove, devwstat, }; | |
| 1997/0327/sys/src/9/pc/devata.c:1912,1917 – 1997/0408/sys/src/9/pc/devata.c:1912,1920 (short | long) | ||
| 1995/0213 | } | |
| 1997/0327 | Dev atadevtab = { | |
| 1997/0408 | 'H', "ata", | |
| 1997/0327 | devreset, devinit, ataattach, | |
| 1997/0408/sys/src/9/pc/devata.c:190,196 – 1997/0812/sys/src/9/pc/devata.c:190,196 (short | long) | ||
| 1995/1206 | }; | |
| 1995/0213 | static void ataintr(Ureg*, void*); | |
| 1995/1206 |
| |
| 1997/0812 | static long ataxfer(Drive*, Partition*, int, ulong, long, uchar*); | |
| 1995/0213 | static void ataident(Drive*); | |
| 1995/1206 | static void atafeature(Drive*, uchar); | |
| 1995/0213 | static void ataparams(Drive*); | |
| 1997/0408/sys/src/9/pc/devata.c:820,826 – 1997/0812/sys/src/9/pc/devata.c:820,826 | ||
| 1995/0213 | * parts. */ static long | |
| 1995/1206 |
| |
| 1997/0812 | ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len, uchar *buf) | |
| 1995/0213 | { Controller *cp; long lblk; | |
| 1997/0812/sys/src/9/pc/devata.c:11,17 – 1997/0815/sys/src/9/pc/devata.c:11,17 (short | long) | ||
| 1995/0213 | #include "../port/error.h" | |
| 1995/0215 |
| |
| 1997/0815 | #define DPRINT if(1)print | |
| 1995/1206 | #define XPRINT if(0)print #define ILOCK(x) #define IUNLOCK(x) | |
| 1997/0812/sys/src/9/pc/devata.c:156,162 – 1997/0815/sys/src/9/pc/devata.c:156,161 | ||
| 1995/0213 | int pbase; /* base port */ | |
| 1995/1206 | uchar ctlrno; | |
| 1997/0327 | int tbdf; | |
| 1996/0210 |
| |
| 1995/0213 | /* * current operation | |
| 1997/0812/sys/src/9/pc/devata.c:343,349 – 1997/0815/sys/src/9/pc/devata.c:342,348 | ||
| 1995/1206 | } static int | |
| 1997/0815 | atactlrprobe(int ctlrno, int irq, int resetok) | |
| 1995/1206 | { Controller *ctlr; int atapi, mask, port; | |
| 1997/0812/sys/src/9/pc/devata.c:359,366 – 1997/0815/sys/src/9/pc/devata.c:358,366 | ||
| 1995/1206 | port = pbase[ctlrno]; outb(port+Pdh, DHmagic); microdelay(1); | |
| 1997/0815 | status = inb(port+Pdh) & 0xFF; if(status != DHmagic){ DPRINT("ata%d: DHmagic not ok == %ux\n", ctlrno, status); | |
| 1995/1206 | return -1; | |
| 1995/0215 | } | |
| 1995/1206 | DPRINT("ata%d: DHmagic ok\n", ctlrno); | |
| 1997/0812/sys/src/9/pc/devata.c:387,393 – 1997/0815/sys/src/9/pc/devata.c:387,393 | ||
| 1995/1206 | * ATAPI signature straight off. If we find it there will be no probe * done for a slave. Tough. */ | |
| 1996/0210 |
| |
| 1997/0815 | if(resetok){ | |
| 1996/0210 | outb(port+Pctrl, Srst|nIEN); | |
| 1996/0215 | delay(10); | |
| 1996/0210 | outb(port+Pctrl, 0); | |
| 1997/0812/sys/src/9/pc/devata.c:487,493 – 1997/0815/sys/src/9/pc/devata.c:487,493 | ||
| 1997/0327 | static void | |
| 1995/1206 | atactlrreset(void) { | |
| 1997/0815 | int ctlrno, driveno, i, resetok, slave, spindown; | |
| 1995/1206 | ISAConf isa; cmd640b(); | |
| 1997/0812/sys/src/9/pc/devata.c:500,508 – 1997/0815/sys/src/9/pc/devata.c:500,506 | ||
| 1995/1206 | if(isa.irq == 0 && (isa.irq = defirq[ctlrno]) == 0) continue; | |
| 1997/0327 |
| |
| 1995/1206 |
| |
| 1995/0213 | ||
| 1997/0815 | driveno = resetok = spindown = 0; | |
| 1995/1206 | 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){ | |
| 1997/0812/sys/src/9/pc/devata.c:514,534 – 1997/0815/sys/src/9/pc/devata.c:512,535 | ||
| 1995/1206 | slave = 1; else continue; | |
| 1997/0815 | driveno = ctlrno*2+slave; | |
| 1995/1206 | } | |
| 1996/0210 | else if(strcmp(isa.opt[i], "reset") == 0) | |
| 1997/0815 | resetok = 1; | |
| 1995/1206 | } | |
| 1997/0815 | if(atactlrprobe(ctlrno, VectorPIC+isa.irq, resetok)) continue; if(spindown == 0 || atadrive[driveno] == 0) continue; atadrive[driveno]->spindown = spindown; spindownmask |= (1<<driveno); DPRINT("ata%d: opt spindownmask %ux\n", ctlrno, spindownmask); | |
| 1995/1206 | } | |
| 1995/0213 | ||
| 1997/0327 | if(spindownmask) | |
| Too many diffs (26 > 25). Stopping. | ||