small changes needed to get atapi devices working. Notes: Wed Jun 6 16:00:42 EDT 2007 geoff I converted the style to more closely match the kernel. I think I fixed a locking bug (grep shurely). Reference: /n/sources/patch/applied/sd63xxesb-atapi Date: Fri Jun 1 17:56:08 CES 2007 Signed-off-by: quanstro@quanstro.net Reviewed-by: geoff --- /sys/src/9/pc/sd63xxesb.c Fri Jun 1 17:55:20 2007 +++ /sys/src/9/pc/sd63xxesb.c Fri Jun 1 17:55:08 2007 @@ -1,7 +1,5 @@ -/* - * intel 63[12]?esb ahci sata controller - * copyright © 2007 coraid, inc. - */ +// intel 63[12]xesb ahci sata controller +// copyright © 2007 coraid, inc. #include "u.h" #include "../port/lib.h" @@ -19,14 +17,14 @@ enum{ NCtlr = 4, - NCtlrdrv= 32, + NCtlrdrv = 32, NDrive = NCtlr*NCtlrdrv, Read = 0, - Write, + Write }; -/* pci space configurtion */ +// pci space configurtion enum{ Pmap = 0x90, Ppcs = 0x91, @@ -42,7 +40,7 @@ Dreset, Doffline, Dportreset, - Dlast, + Dlast }; static char *diskstates[Dlast] = { @@ -88,7 +86,7 @@ char name[10]; Aport *port; Aportm portm; - Aportc portc; /* redundant ptr to port and portm. */ + Aportc portc; // redundant ptr to port and portm. uchar mediachange; uchar state; @@ -97,7 +95,7 @@ uvlong sectors; ulong intick; int wait; - uchar mode; /* DMautoneg, satai or sataii. */ + uchar mode; // DMautoneg, satai or sataii. uchar active; char serial[20+1]; @@ -106,9 +104,8 @@ ushort info[0x200]; - int driveno; /* ctlr*NCtlrdrv + unit */ - /* ctlr port # != driveno when not all ports are enabled */ - int portno; + int driveno; // ctlr*NCtlrdrv + unit + int portno; // controller port number != driveno when not all ports are enabled. }Drive; struct Ctlr{ @@ -138,7 +135,7 @@ static int debug; static int prid = 1; -static int datapi = 1; +static int datapi = 0; static char stab[] = { [0] 'i', 'm', @@ -152,22 +149,22 @@ int i; e -= 3; - for(i = 0; i < nelem(stab) && s < e; i++) - if((r & (1<task, p->cmd, - p->ci, p->isr); + dprint("%stask=%ux; cmd=%ux; ci=%ux; is=%ux\n", s, p->task, p->cmd, p->ci, p->isr); } static void @@ -207,7 +203,7 @@ Asleep *s; s = v; - return (s->p->ci & s->i) == 0; + return (s->p->ci&s->i) == 0; } static void @@ -239,9 +235,9 @@ static int nop(Aportc *pc) { - uchar *c; Actab *t; Alist *l; + uchar *c; if((pc->m->feat&Dnop) == 0) return -1; @@ -253,23 +249,23 @@ c[0] = 0x27; c[1] = 0x80; c[2] = 0x00; - c[7] = 0xa0; /* obsolete device bits */ + c[7] = 0xa0; // obsolete device bits. l = pc->m->list; l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - + return ahciwait(pc, 3*1000); } static int setfeatures(Aportc *pc, uchar f) { - uchar *c; Actab *t; Alist *l; + uchar *c; t = pc->m->ctab; c = t->cfis; @@ -279,23 +275,23 @@ c[1] = 0x80; c[2] = 0xef; c[3] = f; - c[7] = 0xa0; /* obsolete device bits */ + c[7] = 0xa0; // obsolete device bits. l = pc->m->list; l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - + return ahciwait(pc, 3*1000); } static int setudmamode(Aportc *pc, uchar f) { - uchar *c; Actab *t; Alist *l; + uchar *c; t = pc->m->ctab; c = t->cfis; @@ -304,28 +300,29 @@ c[0] = 0x27; c[1] = 0x80; c[2] = 0xef; - c[3] = 3; /* set transfer mode */ - c[7] = 0xa0; /* obsolete device bits */ - c[12] = 0x40|f; /* sector count */ + c[3] = 3; // set transfer mode. + c[7] = 0xa0; // obsolete device bits. + c[12] = 0x40|f; // sector count. l = pc->m->list; l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - + return ahciwait(pc, 3*1000); } static void asleep(int ms) { - if(up == nil) + if(up == 0){ delay(ms); - else - esleep(ms); + return; + } + esleep(ms); } - + static int ahciportreset(Aportc *c) { @@ -336,12 +333,11 @@ cmd = &p->cmd; *cmd &= ~(Afre|Ast); for(i = 0; i < 500; i += 25){ - if((*cmd & Acr) == 0) + if((*cmd&Acr) == 0) break; asleep(25); } - - p->sctl = 1 | (p->sctl & ~7); + p->sctl = 1|(p->sctl&~7); delay(1); p->sctl &= ~7; return 0; @@ -350,9 +346,9 @@ static int smart(Aportc *pc, int n) { - uchar *c; Actab *t; Alist *l; + uchar *c; if((pc->m->feat&Dsmart) == 0) return -1; @@ -364,18 +360,18 @@ c[0] = 0x27; c[1] = 0x80; c[2] = 0xb0; - c[3] = 0xd8+n; /* able smart */ + c[3] = 0xd8+n; // able smart c[5] = 0x4f; c[6] = 0xc2; c[7] = 0xa0; l = pc->m->list; - l->flags = Lwrite | 0x5; + l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - - if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){ + + if(ahciwait(pc, 1000) == -1 || (pc->p->task&(1|32))){ dprint("smart fail %ux\n", pc->p->task); // preg(pc->m->fis.r, 20); return -1; @@ -388,9 +384,9 @@ static int smartrs(Aportc *pc) { - uchar *c; Actab *t; Alist *l; + uchar *c; t = pc->m->ctab; c = t->cfis; @@ -399,19 +395,19 @@ c[0] = 0x27; c[1] = 0x80; c[2] = 0xb0; - c[3] = 0xda; /* return smart status */ + c[3] = 0xda; // return smart status. c[5] = 0x4f; c[6] = 0xc2; c[7] = 0xa0; l = pc->m->list; - l->flags = Lwrite | 0x5; + l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - + c = pc->m->fis.r; - if(ahciwait(pc, 1000) == -1 || pc->p->task & (1|32)){ + if(ahciwait(pc, 1000) == -1 || (pc->p->task&(1|32))){ dprint("smart fail %ux\n", pc->p->task); preg(c, 20); return -1; @@ -424,12 +420,12 @@ static int flushcache(Aportc *pc) { - uchar *c, llba; Actab *t; Alist *l; + uchar *c, llba; static uchar tab[2] = {0xe7, 0xea}; - llba = pc->m->feat & Dllba? 1: 0; + llba = pc->m->feat&Dllba ? 1 : 0; t = pc->m->ctab; c = t->cfis; @@ -440,12 +436,12 @@ c[7] = 0xa0; l = pc->m->list; - l->flags = Lwrite | 0x5; + l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; - - if(ahciwait(pc, 60000) == -1 || pc->p->task & (1|32)){ + + if(ahciwait(pc, 60000) == -1 || (pc->p->task&(1|32))){ dprint("flushcache fail %ux\n", pc->p->task); // preg( pc->m->fis.r, 20); return -1; @@ -456,11 +452,11 @@ static ushort gbit16(void *a) { - ushort j; uchar *i; + ushort j; i = a; - j = i[1] << 8; + j = i[1]<<8; j |= i[0]; return j; } @@ -472,9 +468,9 @@ u32int j; i = a; - j = i[3] << 24; - j |= i[2] << 16; - j |= i[1] << 8; + j = i[3]<<24; + j |= i[2]<<16; + j |= i[1]<<8; j |= i[0]; return j; } @@ -485,16 +481,16 @@ uchar *i; i = a; - return (uvlong)gbit32(i+4) << 32 | gbit32(a); + return ((uvlong) gbit32(i+4)<<32)|gbit32(a); } static int ahciidentify0(Aportc *pc, void *id, int atapi) { - uchar *c; Actab *t; Alist *l; Aprdt *p; + uchar *c; static uchar tab[] = {0xec, 0xa1}; t = pc->m->ctab; @@ -504,10 +500,10 @@ c[0] = 0x27; c[1] = 0x80; c[2] = tab[atapi]; - c[7] = 0xa0; /* obsolete device bits */ + c[7] = 0xa0; // obsolete device bits. l = pc->m->list; - l->flags = 1<<16 | 0x5; + l->flags = (1<<16)|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; @@ -516,7 +512,7 @@ p = &t->prdt; p->dba = PCIWADDR(id); p->dbahi = 0; - p->count = 1<<31 | (0x200-2) | 1; + p->count = (1<<31)|(0x200-2)|1; return ahciwait(pc, 3*1000); } @@ -524,24 +520,24 @@ static vlong ahciidentify(Aportc *pc, ushort *id) { + Aportm *m; int i, sig; vlong s; - Aportm *m; m = pc->m; m->feat = 0; m->smart = 0; i = 0; - sig = pc->p->sig >> 16; - if(sig == 0xeb14 || sig == 0x9669){ + sig = pc->p->sig>>16; + if(sig == 0xeb14){ m->feat |= Datapi; i = 1; } if(ahciidentify0(pc, id, i) == -1) return -1; - i = gbit16(id+83) | gbit16(id+86); - if(i & (1<<10)){ + i = gbit16(id+83)|gbit16(id+86); + if(i&(1<<10)){ m->feat |= Dllba; s = gbit64(id+100); }else @@ -554,15 +550,16 @@ } i = gbit16(id+83); - if((i>>14) == 1) { - if(i & (1<<3)) - m->feat |= Dpower; - i = gbit16(id+82); - if(i & 1) - m->feat |= Dsmart; - if(i & (1<<14)) - m->feat |= Dnop; - } + if(i>>14 != 1) + goto done; + if(i&(1<<3)) + m->feat |= Dpower; + i = gbit16(id+82); + if(i&1) + m->feat |= Dsmart; + if(i&(1<<14)) + m->feat |= Dnop; +done: return s; } @@ -574,28 +571,28 @@ p = &a->cmd; *p &= ~Ast; for(i = 0; i < 500; i += 50){ - if((*p & Acr) == 0) + if((*p&Acr) == 0) goto stop; asleep(50); } return -1; stop: - if((a->task & (ASdrq|ASbsy)) == 0){ + if((a->task&(ASdrq|ASbsy)) == 0){ *p |= Ast; return 0; } *p |= Aclo; for(i = 0; i < 500; i += 50){ - if((*p & Aclo) == 0) + if((*p&Aclo) == 0) goto stop1; asleep(50); } return -1; stop1: - /* extra check */ + // extra check dprint("clo clear %x\n", a->task); - if(a->task & ASbsy) + if(a->task&ASbsy) return -1; *p |= Ast; return 0; @@ -622,11 +619,11 @@ memset(c, 0, 0x20); c[0] = 0x27; c[1] = 0x00; - c[7] = 0xa0; /* obsolete device bits */ - c[15] = 1<<2; /* srst */ + c[7] = 0xa0; // obsolete device bits. + c[15] = 1<<2; // srst l = pc->m->list; - l->flags = Lclear | Lreset | 0x5; + l->flags = Lclear|Lreset|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; @@ -641,10 +638,10 @@ memset(c, 0, 0x20); c[0] = 0x27; c[1] = 0x00; - c[7] = 0xa0; /* obsolete device bits */ + c[7] = 0xa0; // obsolete device bits. l = pc->m->list; - l->flags = Lwrite | 0x5; + l->flags = Lwrite|0x5; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; @@ -668,28 +665,26 @@ *p &= ~Ast; r = 0; for(i = 0; i < 500; i += 25){ - if((*p & Acr) == 0) + if((*p&Acr) == 0) goto stop; asleep(25); } r = -1; stop: - if((*p & Afre) == 0) + if((*p&Afre) == 0) return r; *p &= ~Afre; for(i = 0; i < 500; i += 25){ - if((*p & Afre) == 0) + if((*p&Afre) == 0) return 0; asleep(25); } return -1; } -/* - * § 6.2.2.1 first part; comreset handled by reset disk. - * - remainder is handled by configdisk. - * - ahcirecover is a quick recovery from a failed command. - */ +// § 6.2.2.1 first part; comreset handled by reset disk. +// - remainder is handled by configdisk. +// - ahcirecover is a quick recovery from a failed command. int ahciswreset(Aportc *pc) { @@ -699,7 +694,7 @@ pc->p->cmd |= Afre; if(i == -1) return -1; - if(pc->p->task & (ASdrq|ASbsy)) + if(pc->p->task&(ASdrq|ASbsy)) return -1; return 0; } @@ -728,11 +723,11 @@ setupfis(Afis *f) { f->base = malign(0x100, 0x100); - f->d = f->base + 0; - f->p = f->base + 0x20; - f->r = f->base + 0x40; - f->u = f->base + 0x60; - f->devicebits = (u32int*)(f->base + 0x58); + f->d = f->base+0; + f->p = f->base+0x20; + f->r = f->base+0x40; + f->u = f->base+0x60; + f->devicebits = (u32int*)(f->base+0x58); } static int @@ -750,9 +745,9 @@ m->ctab = malign(sizeof *m->ctab, 128); } - if(p->sstatus & 3 && h->cap & Hsss){ + if(p->sstatus&3 && h->cap&Hsss){ dprint("configdrive: spinning up ... [%ux]\n", p->sstatus); - p->cmd |= Apod | Asud; + p->cmd |= Apod|Asud; asleep(1400); } @@ -762,13 +757,14 @@ p->listhi = 0; p->fis = PCIWADDR(m->fis.base); p->fishi = 0; - p->cmd |= Afre | Ast; - - /* disable power managment sequence from book. */ - p->sctl = (3*Aipm) | (mode*Aspd) | 0*Adet; + p->cmd |= Afre|Ast; + + // disable power managment sequence from book. + p->sctl = (3*Aipm)|(mode*Aspd)|0*Adet; p->cmd &= ~Aalpe; p->ie = IEM; + return 0; } @@ -793,7 +789,7 @@ n = 0; for(i = 0; i < 32; i++) - if(u & (1<ghc |= Hae; print("ahci hba sss %d; ncs %d; coal %d; mports %d; led %d; clo %d; ems %d;\n", - (u>>27) & 1, (u>>8) & 0x1f, (u>>7) & 1, u & 0x1f, (u>>25) & 1, - (u>>24) & 1, (u>>6) & 1); + (u>>27)&1, (u>>8)&0x1f, (u>>7)&1, u&0x1f, (u>>25)&1, + (u>>24)&1, (u>>6)&1); return countbits(h->pi); } @@ -833,12 +829,12 @@ static void idmove(char *p, ushort *a, int n) { - int i; char *op, *e; - + int i; + op = p; for(i = 0; i < n/2; i++){ - *p++ = a[i] >> 8; + *p++ = a[i]>>8; *p++ = a[i]; } *p = 0; @@ -848,16 +844,16 @@ p = op; while(*p == ' ') p++; - memmove(op, p, n - (e - p)); + memmove(op, p, n-(e-p)); } static int identify(Drive *d) { + SDunit *u; + uchar oserial[21]; u16int *id; vlong osectors, s; - uchar oserial[21]; - SDunit *u; id = d->info; s = ahciidentify(&d->portc, id); @@ -871,9 +867,9 @@ d->sectors = s; d->smartrs = 0; - idmove(d->serial, id + 10, 20); - idmove(d->firmware, id + 23, 8); - idmove(d->model, id + 27, 40); + idmove(d->serial, id+10, 20); + idmove(d->firmware, id+23, 8); + idmove(d->model, id+27, 40); u = d->unit; memset(u->inquiry, 0, sizeof u->inquiry); @@ -882,21 +878,21 @@ u->inquiry[4] = sizeof u->inquiry-4; memmove(u->inquiry+8, d->model, 40); - if ((osectors == 0 || osectors != s) && - memcmp(oserial, d->serial, sizeof oserial) != 0){ + if((osectors == 0 || osectors != s) && memcmp(oserial, d->serial, sizeof oserial) != 0){ d->mediachange = 1; u->sectors = 0; } + return 0; } static void clearci(Aport *p) { - if((p->cmd & Ast) == 0) + if((p->cmd&Ast) == 0) return; p->cmd &= ~Ast; - p->cmd |= Ast; + p->cmd |= Ast; } static void @@ -929,22 +925,20 @@ } if(cause&Adhrs){ if(p->task&33){ - dprint("Adhrs cause = %ux; serr = %ux; task=%ux\n", - cause, serr, p->task); + dprint("Adhrs cause = %ux; serr = %ux; task=%ux\n", cause, serr, p->task); d->portm.flag |= Ferror; ewake = 1; } pr = 0; } -// if(p->task & 1 && last != cause) -// dprint("err ca %ux serr %ux task %ux sstat %ux\n", -// cause, serr, p->task, p->sstatus); +// if(p->task&1 && last != cause) +// dprint("err ca %ux serr %ux task %ux sstat %ux\n", cause, serr, p->task, p->sstatus); if(pr) dprint("%s: upd %ux ta %ux\n", name, cause, p->task); - if(cause & (Aprcs|Aifs)){ + if(cause&(Aprcs|Aifs)){ s0 = d->state; - switch(p->sstatus & 7){ + switch(p->sstatus&7){ case 0: d->state = Dmissing; break; @@ -953,16 +947,17 @@ break; case 3: /* power mgnt crap for suprise removal */ - p->ie |= Aprcs | Apcs; /* is this required? */ + p->ie |= Aprcs|Apcs; // is this required? d->state = Dreset; break; case 4: d->state = Doffline; break; } - dprint("%s: %s → %s [Apcrs] %ux\n", name, diskstates[s0], - diskstates[d->state], p->sstatus); - /* print pulled message here. */ + dprint("%s: %s → %s [Apcrs] %ux\n", name, diskstates[s0], diskstates[d->state], p->sstatus); + // print pulled message here. + if(s0 == Dready && d->state != Dready) + idprint("%s: pulled\n", name); if(d->state != Dready) d->portm.flag |= Ferror; ewake = 1; @@ -978,17 +973,14 @@ static void pstatus(Drive *d, ulong s) { - /* - * bogus code because the first interrupt is currently dropped. - * likely my fault. serror is may be cleared at the wrong time. - */ + // bogus code because the first interrupt is currently dropped. + // likely my fault. serror is may be cleared at the wrong time. switch(s){ case 0: d->state = Dmissing; break; - case 2: /* should this be missing? need testcase. */ + case 2: // should this be missing? need testcase. dprint("pstatus 2\n"); - /* FALLTHROUGH */ case 3: d->wait = 0; d->state = Dnew; @@ -1005,7 +997,7 @@ if(ahciconfigdrive(d->ctlr->hba, &d->portc, d->mode) == -1) return -1; ilock(d); - pstatus(d, d->port->sstatus & 7); + pstatus(d, d->port->sstatus&7); iunlock(d); return 0; } @@ -1017,9 +1009,9 @@ Aport *p; p = d->port; - det = p->sctl & 7; - stat = p->sstatus & 7; - state = (p->cmd >> 28) & 0xf; + det = p->sctl&7; + stat = p->sstatus&7; + state = (p->cmd>>28)&0xf; dprint("resetdisk: icc %ux det %d sdet %d\n", state, det, stat); if(stat != 3){ ilock(d); @@ -1031,23 +1023,25 @@ state = d->state; if(d->state != Dready || d->state != Dnew) d->portm.flag |= Ferror; - clearci(p); /* satisfy sleep condition */ + clearci(p); // satify sleep condition. wakeup(&d->portm); iunlock(d); qlock(&d->portm); - if(p->cmd & Ast && ahciswreset(&d->portc) == -1){ - ilock(d); - d->state = Dportreset; /* get a bigger stick */ - iunlock(d); - } else { + if(p->cmd&Ast && ahciswreset(&d->portc) == -1){ ilock(d); - d->state = Dmissing; + d->state = Dportreset; // get a bigger stick. iunlock(d); - - configdrive(d); + goto out; } + + ilock(d); + d->state = Dmissing; + iunlock(d); + + configdrive(d); +out: dprint("resetdisk: %s → %s\n", diskstates[state], diskstates[d->state]); qunlock(&d->portm); } @@ -1077,7 +1071,8 @@ dprint("%s: identify failure\n", name); goto loose; } - if(m->feat &Dpower && setfeatures(c, 0x85) == -1){ + if(m->feat&Dpower) + if(setfeatures(c, 0x85) == -1){ m->feat &= ~Dpower; if(ahcirecover(c) == -1) goto loose; @@ -1090,12 +1085,13 @@ qunlock(c->m); s = ""; - if(m->feat & Dllba) - s = "L"; + if(m->feat&Dllba) + s="L"; idprint("%s: %sLBA %,lld sectors\n", d->unit->name, s, d->sectors); - idprint(" %s %s %s %s\n", d->model, d->firmware, d->serial, - d->mediachange?"[mediachange]":""); + idprint(" %s %s %s %s\n", d->model, d->firmware, d->serial, d->mediachange?"[mediachange]":""); + return 0; + loose: qunlock(&d->portm); return -1; @@ -1103,18 +1099,17 @@ enum{ Nms = 256, - Mphywait = 2*1024/Nms - 1, - Midwait = 16*1024/Nms - 1, - Mcomrwait = 64*1024/Nms - 1, + Mphywait = 2*1024/Nms-1, + Midwait = 16*1024/Nms-1, + Mcomrwait = 64*1024/Nms-1, }; static void westerndigitalhung(Drive *d) { - if ((d->portm.feat & Datapi) == 0 && d->active && - TK2MS(MACHP(0)->ticks-d->intick) > 5000){ - dprint("%s: drive hung; resetting [%ux] ci=%x\n", - d->unit->name, d->port->task, d->port->ci); + if((d->portm.feat&Datapi) == 0) + if(d->active && TK2MS(MACHP(0)->ticks-d->intick) > 5000){ + dprint("%s: drive hung; resetting [%ux] ci=%x\n", d->unit->name, d->port->task, d->port->ci); d->state = Dreset; } } @@ -1133,8 +1128,7 @@ else i = 0; qunlock(&d->portm); - dprint("portreset → %s [task %ux]\n", diskstates[d->state], - d->port->task); + dprint("portreset → %s [task %ux]\n", diskstates[d->state], d->port->task); return i; } @@ -1148,8 +1142,7 @@ name = d->unit->name; s = d->port->sstatus; if(s != olds[i]){ - dprint("%s: status: %04ux -> %04ux: %s\n", name, olds[i], s, - diskstates[d->state]); + dprint("%s: status: %04ux -> %04ux: %s\n", name, olds[i], s, diskstates[d->state]); olds[i] = s; d->wait = 0; } @@ -1159,36 +1152,33 @@ break; case Dmissing: case Dnew: - switch(s & 0x107){ + switch(s&0x107){ case 0: case 1: break; default: dprint("%s: unknown status %04ux\n", name, s); case 0x100: - if(++d->wait & Mphywait) + if(++d->wait&Mphywait) break; -reset: - if(++d->mode > DMsataii) + reset: if(++d->mode > DMsataii) d->mode = 0; - if(d->mode == DMsatai){ /* we tried everything */ + if(d->mode == DMsatai){ // we tried everything d->state = Dportreset; goto portreset; } - dprint("%s: reset; new mode %s\n", name, - modename[d->mode]); + dprint("%s: reset; new mode %s\n", name, modename[d->mode]); iunlock(d); resetdisk(d); ilock(d); break; case 0x103: - if((++d->wait & Midwait) == 0){ - dprint("%s: slow reset %04ux task=%ux; %d\n", - name, s, d->port->task, d->wait); + if((++d->wait&Midwait) == 0){ + dprint("%s: slow reset %04ux task=%ux; %d\n", name, s, d->port->task, d->wait); goto reset; } - s = d->port->task & 0xff; - if(s == 0x7f || (s & ~0x17) != (1<<6)) + s = d->port->task&0xff; + if(s == 0x7f || ((d->port->sig>>16) != 0xeb14 && (s&~0x17) != (1<<6))) break; iunlock(d); newdrive(d); @@ -1198,24 +1188,25 @@ case Dready: break; case Doffline: - if(d->wait++ & Mcomrwait) + if(d->wait++&Mcomrwait) break; case Derror: case Dreset: - dprint("%s: reset [%s]: mode %d; status %04ux\n", name, - diskstates[d->state], d->mode, s); + dprint("%s: reset [%s]: mode %d; status %04ux\n", name, diskstates[d->state], d->mode, s); iunlock(d); resetdisk(d); ilock(d); break; case Dportreset: -portreset: - dprint("%s: portreset [%s]: mode %d; status %04ux\n", name, - diskstates[d->state], d->mode, s); + portreset: + if(d->wait++&0xff) + if((s&0x100) == 0) + break; + dprint("%s: portreset [%s]: mode %d; status %04ux\n", name, diskstates[d->state], d->mode, s); d->portm.flag |= Ferror; clearci(d->port); wakeup(&d->portm); - if((s & 7) == 0){ + if((s&7) == 0){ d->state = Dmissing; break; } @@ -1233,7 +1224,7 @@ int i; memset(olds, 0xff, sizeof olds); - for (; ; ){ + for(;;){ tsleep(&up->sleep, return0, 0, Nms); for(i = 0; i < niadrive; i++) checkdrive(iadrive[i], i); @@ -1243,21 +1234,22 @@ static void iainterrupt(Ureg*, void *a) { - int i; - ulong cause, m; Ctlr *c; Drive *d; + ulong cause, m; + int i; c = a; ilock(c); cause = c->hba->isr; for(i = 0; i < c->ndrive; i++){ m = 1<rawdrive+i; ilock(d); - if(d->port->isr && c->hba->pi & m) + if(d->port->isr) + if(c->hba->pi&m) updatedrive(d); c->hba->isr = m; iunlock(d); @@ -1285,20 +1277,21 @@ iaenable(SDev *s) { char name[32]; - Ctlr *c; static int once; + Ctlr *c; c = s->ctlr; ilock(c); - if(!c->enabled) { - if(once++ == 0) - kproc("iasata", satakproc, 0); - pcisetbme(c->pci); - snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name); - intrenable(c->irq, iainterrupt, c, c->tbdf, name); - /* supposed to squelch leftover interrupts here. */ - ahcienable(c->hba); - } + if(c->enabled) + goto done; + if(once++ == 0) + kproc("iasata", satakproc, 0); + pcisetbme(c->pci); + snprint(name, sizeof name, "%s (%s)", s->name, s->ifc->name); + intrenable(c->irq, iainterrupt, c, c->tbdf, name); + // supposed to squelch leftover interrupts here. + ahcienable(c->hba); +done: c->enabled = 1; iunlock(c); return 1; @@ -1323,15 +1316,15 @@ static int iaonline(SDunit *unit) { - ulong r; Ctlr *c; Drive *d; + int r; c = unit->dev->ctlr; d = c->drive[unit->subno]; r = 0; - - if((d->portm.feat & Datapi) && d->mediachange){ + + if((d->portm.feat&Datapi) && d->mediachange){ r = scsionline(unit); if(r > 0) d->mediachange = 0; @@ -1342,7 +1335,7 @@ if(d->mediachange){ r = 2; d->mediachange = 0; - /* devsd resets this after online is called; why? */ + // devsd rests this after online is called; why? unit->sectors = d->sectors; unit->secsize = 512; } else if(d->state == Dready) @@ -1356,16 +1349,15 @@ static Alist* ahcibuild(Aportm *m, uchar *cmd, void *data, int n, vlong lba) { - uchar *c, acmd, dir, llba; - Actab *t; Alist *l; + Actab *t; Aprdt *p; + uchar *c, acmd, dir, llba; static uchar tab[2][2] = {0xc8, 0x25, 0xca, 0x35}; dir = *cmd != 0x28; - llba = m->feat & Dllba? 1: 0; + llba = m->feat&Dllba ? 1 : 0; acmd = tab[dir][llba]; - qlock(m); l = m->list; t = m->ctab; @@ -1376,26 +1368,26 @@ c[2] = acmd; c[3] = 0; - c[4] = lba; /* sector lba low 7:0 */ - c[5] = lba >> 8; /* cylinder low lba mid 15:8 */ - c[6] = lba >> 16; /* cylinder hi lba hi 23:16 */ - c[7] = 0xa0 | 0x40; /* obsolete device bits + lba */ + c[4] = lba; // sector lba low 7:0 + c[5] = lba>>8; // cylinder low lba mid 15:8 + c[6] = lba>>16; // cylinder hi lba hi 23:16 + c[7] = 0xa0|0x40; // obsolete device bits + lba if(llba == 0) - c[7] |= (lba >> 24) & 7; + c[7] |= lba>>24&7; - c[8] = lba >> 24; /* sector (exp) lba 31:24 */ - c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */ - c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */ - c[11] = 0; /* features (exp); */ + c[8] = lba>>24; // sector (exp) lba 31:24 + c[9] = lba>>32; // cylinder low (exp) lba 39:32 + c[10] = lba>>48; // cylinder hi (exp) lba 48:40 + c[11] = 0; // features (exp); - c[12] = n; /* sector count */ - c[13] = n >> 8; /* sector count (exp) */ - c[14] = 0; /* r */ - c[15] = 0; /* control */ + c[12] = n; // sector count + c[13] = n>>8; // sector count (exp) + c[14] = 0; // r + c[15] = 0; // control - *(ulong*)(c + 16) = 0; + *(ulong*)(c+16) = 0; - l->flags = 1<<16 | Lpref | 0x5; /* Lpref ?? */ + l->flags = (1<<16)|Lpref|0x5; // Lpref ?? if(dir == Write) l->flags |= Lwrite; l->len = 0; @@ -1405,7 +1397,7 @@ p = &t->prdt; p->dba = PCIWADDR(data); p->dbahi = 0; - p->count = 1<<31 | (512*n - 2) | 1; + p->count = (1<<31)|(512*n-2)|1; return l; } @@ -1413,18 +1405,18 @@ static Alist* ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n) { - int fill, len; - uchar *c; - Actab *t; Alist *l; + Actab *t; Aprdt *p; + uchar *c; + int fill, len; qlock(m); l = m->list; t = m->ctab; c = t->cfis; - fill = m->feat & Datapi16? 16: 12; + fill = m->feat&Datapi16 ? 16 : 12; if((len = r->clen) > fill) len = fill; memmove(t->atapi, r->cmd, len); @@ -1434,35 +1426,33 @@ c[1] = 0x80; c[2] = 0xa0; if(n != 0) - c[3] = 1; /* dma */ + c[3] = 1; // dma else - c[3] = 0; /* features (exp); */ - - c[4] = 0; /* sector lba low 7:0 */ - c[5] = n; /* cylinder low lba mid 15:8 */ - c[6] = n >> 8; /* cylinder hi lba hi 23:16 */ - c[7] = 0xa0; /* obsolete device bits */ - - *(ulong*)(c + 8) = 0; -// c[8] = lba >> 24; /* sector (exp) lba 31:24 */ -// c[9] = lba >> 32; /* cylinder low (exp) lba 39:32 */ -// c[10] = lba >> 48; /* cylinder hi (exp) lba 48:40 */ -// c[11] = 0; + c[3] = 0; // features (exp); - *(ulong*)(c + 12) = 0; - *(ulong*)(c + 16) = 0; + c[4] = 0; // sector lba low 7:0 + c[5] = n; // cylinder low lba mid 15:8 + c[6] = n>>8; // cylinder hi lba hi 23:16 + c[7] = 0xa0; // obsolete device bits + + *(ulong*)(c+8) = 0; + *(ulong*)(c+12) = 0; + *(ulong*)(c+16) = 0; - l->flags = 1<<16 | Lpref | Latapi | 0x5; - if(r->write != 0) + l->flags = (1<<16)|Lpref|Latapi|0x5; + if(r->write != 0 && data) l->flags |= Lwrite; l->len = 0; l->ctab = PCIWADDR(t); l->ctabhi = 0; + if(data == 0) + return l; + p = &t->prdt; p->dba = PCIWADDR(data); p->dbahi = 0; - p->count = 1<<31 | (n-2) | 1; + p->count = (1<<31)|(n-2)|1; return l; } @@ -1477,13 +1467,13 @@ s = d->port->sstatus; t = d->port->task; iunlock(d); - if((s & 0x100) == 0) + if((s&0x100) == 0) return -1; - if(d->state == Dready && (s & 7) == 3) + if(d->state == Dready) + if((s&7) == 3) return 0; - if((i+1) % 30 == 0) - print("%s: waitready: [%s] task=%ux sstat=%ux\n", - d->unit->name, diskstates[d->state], t, s); + if((i+1)%30 == 0) + print("%s: waitready: [%s] task=%ux sstat=%ux\n", d->unit->name, diskstates[d->state], t, s); esleep(1000); } print("%s: not responding; offline\n", d->unit->name); @@ -1497,8 +1487,8 @@ iariopkt(SDreq *r, Drive *d) { int n, count, try, max, flag, task; - char *name; uchar *cmd, *data; + char *name; Aport *p; Asleep as; @@ -1506,8 +1496,8 @@ name = d->unit->name; p = d->port; - aprint("%02ux %02ux\n", cmd[0], cmd[2]); - if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f) + aprint("%02ux %02ux %c %d %p\n", cmd[0], cmd[2], "rw"[r->write], r->dlen, r->data); + if(cmd[0] == 0x5a && (cmd[2]&0x3f) == 0x3f) return sdmodesense(r, cmd, d->info, sizeof d->info); r->rlen = 0; count = r->dlen; @@ -1542,8 +1532,10 @@ task = d->port->task; iunlock(d); - if(task & (Efatal<<8) || task & (ASbsy|ASdrq) && d->state == Dready){ - d->port->ci = 0; /* @? */ + if(task&(Efatal<<8) || + task&(ASbsy|ASdrq) + && d->state == Dready){ + d->port->ci = 0; // @? ahcirecover(&d->portc); task = d->port->task; } @@ -1551,7 +1543,7 @@ qunlock(&d->portm); if(flag == 0){ if(++try == 10){ - print("%s: bad disk\n", name); + print("%s: bad disk\n", name); r->status = SDcheck; return SDcheck; } @@ -1567,7 +1559,7 @@ data += n; - r->rlen = data - (uchar*)r->data; + r->rlen = data-(uchar*)r->data; r->status = SDok; return SDok; } @@ -1576,25 +1568,25 @@ iario(SDreq *r) { int i, n, count, try, max, flag, task; - vlong lba; - char *name; + SDunit *unit; + Ctlr *c; + Drive *d; uchar *cmd, *data; + char *name; + vlong lba; Aport *p; Asleep as; - Ctlr *c; - Drive *d; - SDunit *unit; unit = r->unit; c = unit->dev->ctlr; d = c->drive[unit->subno]; - if(d->portm.feat & Datapi) + if(d->portm.feat&Datapi) return iariopkt(r, d); cmd = r->cmd; name = d->unit->name; p = d->port; - if(r->cmd[0] == 0x35){ + if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){ qlock(&d->portm); i = flushcache(&d->portc); qunlock(&d->portm); @@ -1614,8 +1606,8 @@ return SDcheck; } - lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5]; - count = cmd[7]<<8 | cmd[8]; + lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5]; + count = (cmd[7]<<8)|cmd[8]; if(r->data == nil) return SDok; if(r->dlen < count*unit->secsize) @@ -1652,9 +1644,10 @@ task = d->port->task; iunlock(d); - if (task & (Efatal<<8) || task & (ASbsy|ASdrq) && - d->state == Dready){ - d->port->ci = 0; /* @? */ + if(task&(Efatal<<8) || + task&(ASbsy|ASdrq) + && d->state == Dready){ + d->port->ci = 0; // @? ahcirecover(&d->portc); task = d->port->task; } @@ -1662,7 +1655,7 @@ qunlock(&d->portm); if(flag == 0){ if(++try == 10){ - print("%s: bad disk\n", name); + print("%s: bad disk\n", name); r->status = SDeio; return SDeio; } @@ -1670,7 +1663,7 @@ esleep(1000); goto retry; } - if(flag & Ferror){ + if(flag&Ferror){ iprint("%s: i/o error %ux @%,lld\n", name, task, lba); r->status = SDeio; return SDeio; @@ -1678,9 +1671,9 @@ count -= n; lba += n; - data += n * unit->secsize; + data += n*unit->secsize; } - r->rlen = data - (uchar*)r->data; + r->rlen = data-(uchar*)r->data; r->status = SDok; return SDok; } @@ -1691,10 +1684,9 @@ static int iaahcimode(Pcidev *p) { - dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91), pcicfgr8(p, 92), - pcicfgr8(p, 93)); - pcicfgw16(p, 0x92, pcicfgr32(p, 0x92) | 0xf); /* ports 0-3 */ -// pcicfgw8(p, 0x93, pcicfgr32(p, 9x93) | 3); /* ports 4-5 */ + dprint("iaahcimode %ux %ux %ux\n", pcicfgr8(p, 0x91), pcicfgr8(p, 92), pcicfgr8(p, 93)); + pcicfgw16(p, 0x92, pcicfgr32(p, 0x92)|0xf); // ports 0-3 +// pcicfgw8(p, 0x93, pcicfgr32(p, 9x93)|3); // ports 4-5 return 0; } @@ -1702,16 +1694,17 @@ static void iasetupahci(Ctlr *c) { - /* disable cmd block decoding. */ - pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40) & ~(1<<15)); - pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42) & ~(1<<15)); + // disable cmd block decoding. + pcicfgw16(c->pci, 0x40, pcicfgr16(c->pci, 0x40)&~(1<<15)); + pcicfgw16(c->pci, 0x42, pcicfgr16(c->pci, 0x42)&~(1<<15)); - c->lmmio[0x4/4] |= 1<<31; /* enable ahci mode (ghc register) */ - c->lmmio[0xc/4] = (1<<6)-1; /* 5 ports (supposedly ro pi reg) */ + c->lmmio[0x4/4] |= 1<<31; // enable ahci mode (ghc register) + c->lmmio[0xc/4] = (1<<6)-1; // five ports. (supposedly ro pi register) - /* enable ahci mode. */ + // enable ahci mode. // pcicfgw8(c->pci, 0x90, 0x40); - pcicfgw16(c->pci, 0x90, 1<<6 | 1<<5); /* pedanticly proper for ich9 */ +// pcicfgw16(c->pci, 0x90, (1<<6)|(1<<5)); //pedanticly proper for ich9. + pcicfgw8(c->pci, 0x90, (1<<6)|(1<<5)); //pedanticly proper for ich9. } static SDev* @@ -1720,9 +1713,9 @@ int i, n, nunit; ulong io; Ctlr *c; - Drive *d; Pcidev *p; SDev *head, *tail, *s; + Drive *d; static int done; if(done++) @@ -1733,22 +1726,21 @@ tail = nil; loop: while((p = pcimatch(p, 0x8086, 0)) != nil){ - if ((p->did&0xfffc) != 0x2680 && /* esb */ - (p->did&0xfffe) != 0x27c4) /* 82801g[bh]m */ + if((p->did&0xfffc) != 0x2680) // esb + if((p->did&0xfffe) != 0x27c4) // 82801g[bh]m continue; if(niactlr == NCtlr){ print("iapnp: too many controllers\n"); break; } - c = iactlr + niactlr; - s = sdevs + niactlr; + c = iactlr+niactlr; + s = sdevs+niactlr; memset(c, 0, sizeof *c); memset(s, 0, sizeof *s); io = p->mem[Abar].bar & ~0xf; c->mmio = vmap(io, p->mem[0].size); if(c->mmio == 0){ - print("iapnp: address 0x%luX in use did=%x\n", io, - p->did); + print("iapnp: address 0x%luX in use did=%x\n", io, p->did); continue; } c->lmmio = (ulong*)c->mmio; @@ -1756,16 +1748,15 @@ if(p->did != 0x2681) iasetupahci(c); nunit = ahciconf(c); - /* ahcihbareset((Ahba*)c->mmio); */ + //ahcihbareset((Ahba*)c->mmio); if(iaahcimode(p) == -1) break; if(nunit < 1){ vunmap(c->mmio, p->mem[0].size); continue; } - i = (c->hba->cap >> 21) & 1; - print("intel 63[12]xesb: sata-%s ports with %d ports\n", - "I\0II" + i*2, nunit); + i = (c->hba->cap>>21)&1; + print("intel 63[12]xesb: sata-%s ports with %d ports\n", "I\0II"+i*2, nunit); s->ifc = &sd63xxesbifc; s->ctlr = c; s->nunit = nunit; @@ -1775,7 +1766,7 @@ c->tbdf = p->tbdf; c->ndrive = nunit; - /* map the drives -- they don't all need to be enabled. */ + // map the drives -- they don't all need to be enabled. memset(c->rawdrive, 0, sizeof c->rawdrive); n = 0; for(i = 0; i < NCtlrdrv; i++) { @@ -1784,9 +1775,9 @@ d->driveno = -1; d->sectors = 0; d->ctlr = c; - if((c->hba->pi & (1 << i)) == 0) + if((c->hba->pi&(1<port = (Aport*)(c->mmio + 0x80*i + 0x100); + d->port = (Aport*)(c->mmio+0x80*i+0x100); d->portc.p = d->port; d->portc.m = &d->portm; d->driveno = n++; @@ -1795,8 +1786,7 @@ } for(i = 0; i < n; i++) if(ahciidle(c->drive[i]->port) == -1){ - dprint("intel 63[12]xesb: port %d wedged; abort\n", - i); + dprint("intel 63[12]xesb: port %d wedged; abort\n", i); goto loop; } for(i = 0; i < n; i++){ @@ -1827,8 +1817,8 @@ uchar i, m; for(i = 0; i < 8; i++){ - m = 1 << i; - if(f & m) + m = 1<dev->ctlr) == nil) return 0; @@ -1851,23 +1841,21 @@ e = p+l; op = p; if(d->state == Dready){ - p = seprint(p, e, "model\t%s\n", d->model); - p = seprint(p, e, "serial\t%s\n", d->serial); - p = seprint(p, e, "firm\t%s\n", d->firmware); + p = seprint(p, e, "model %s\n", d->model); + p = seprint(p, e, "serial %s\n", d->serial); + p = seprint(p, e, "firm %s\n", d->firmware); if(d->smartrs == 0xff) - p = seprint(p, e, "smart\tenable error\n"); + p = seprint(p, e, "smart enable error\n"); else if(d->smartrs == 0) - p = seprint(p, e, "smart\tdisabled\n"); + p = seprint(p, e, "smart disabled\n"); else - p = seprint(p, e, "smart\t%s\n", - smarttab[d->portm.smart]); - p = seprint(p, e, "flag\t"); + p = seprint(p, e, "smart %s\n", smarttab[d->portm.smart]); + p = seprint(p, e, "flag "); p = pflag(p, e, d->portm.feat); }else p = seprint(p, e, "no disk present [%s]\n", diskstates[d->state]); - serrstr(o->serror, buf, buf + sizeof buf - 1); - p = seprint(p, e, "reg\ttask %ux cmd %ux serr %ux %s ci %ux is %ux; sig %ux\n", - o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig); + serrstr(o->serror, buf, buf+sizeof buf-1); + p = seprint(p, e, "reg task %ux cmd %ux serr %ux %s ci %ux is %ux; sig %ux sstatus %04x\n", o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig, o->sstatus); p = seprint(p, e, "geometry %llud 512\n", d->sectors); return p-op; @@ -1882,7 +1870,7 @@ qlock(&d->portm); flushcache(&d->portc); qunlock(&d->portm); - dprint("flush in %ldms\n", TK2MS(MACHP(0)->ticks - t0)); + dprint("flush in %ldms\n", TK2MS(MACHP(0)->ticks-t0)); } static void @@ -1929,17 +1917,18 @@ d->state = i; if(i == Dnull){ d->mediachange = 1; - d->unit->sectors = 0; /* force disk to disappear */ + d->unit->sectors = 0; // force disk to disappear. } iunlock(d); } + static int iawctl(SDunit *u, Cmdbuf *cmd) { - char **f; Ctlr *c; Drive *d; + char **f; c = u->dev->ctlr; d = c->drive[u->subno]; @@ -1949,15 +1938,14 @@ runflushcache(d); else if(strcmp(f[0], "identify") == 0){ uint i; - - i = strtoul(f[1]? f[1]: "0", 0, 0); + i = strtoul(f[1] ? f[1] : "0", 0, 0); if(i > 0xff) i = 0; dprint("%04d %ux\n", i, d->info[i]); }else if(strcmp(f[0], "mode") == 0) - forcemode(d, f[1]? f[1]: "satai"); + forcemode(d, f[1] ? f[1] : "satai"); else if(strcmp(f[0], "nop") == 0){ - if((d->portm.feat & Dnop) == 0){ + if((d->portm.feat&Dnop) == 0){ cmderror(cmd, "nop command not supported"); return -1; } @@ -1982,7 +1970,7 @@ nexterror(); } qlock(&d->portm); - d->portm.smart = 2 + smartrs(&d->portc); + d->portm.smart = 2+smartrs(&d->portc); qunlock(&d->portm); poperror(); }else if(strcmp(f[0], "smartdisable") == 0) @@ -1990,7 +1978,7 @@ else if(strcmp(f[0], "smartenable") == 0) runsmartable(d, 0); else if(strcmp(f[0], "state") == 0) - forcestate(d, f[1]? f[1]: "null"); + forcestate(d, f[1] ? f[1] : "null"); else{ cmderror(cmd, Ebadctl); return -1; @@ -2006,9 +1994,9 @@ p[0] = 0; a = -1; for(i = 0; i < 32; i++){ - if((x & (1 << i)) == 0){ - if(a != -1 && i - 1 != a) - p = seprint(p, e, "-%d", i - 1); + if((x&(1<ctlr; @@ -2055,12 +2042,10 @@ has(Hsxs, "sxs "); p = seprint(p, e, "\n"); - p = seprint(p, e, "%s iss %d ncs %d np %d\n", name, (u >> 20) & 0xf, - (u >> 8) & 0x1f, 1 + (u & 0x1f)); + p = seprint(p, e, "%s iss %d ncs %d np %d\n", name, (u>>20)&0xf, (u>>8)&0x1f, 1+(u&0x1f)); h = c->hba; portr(pr, pr+sizeof pr, h->pi); - p = seprint(p, e, "%s ghc %ux isr %ux pi %ux %s ver %ux\n", - name, h->ghc, h->isr, h->pi, pr, h->ver); + p = seprint(p, e, "%s ghc %ux isr %ux pi %ux %s ver %ux\n", name, h->ghc, h->isr, h->pi, pr, h->ver); return p; } @@ -2118,3 +2103,4 @@ iartopctl, iawtopctl, }; + --- /sys/src/9/pc/ahci.h Fri Jun 1 17:55:32 2007 +++ /sys/src/9/pc/ahci.h Fri Jun 1 17:55:29 2007 @@ -1,176 +1,171 @@ -/* - * advanced host controller interface (sata) - * © 2007 coraid, inc - */ - -/* ata errors */ -enum{ - Emed = 1<<0, /* media error */ - Enm = 1<<1, /* no media */ - Eabrt = 1<<2, /* abort */ - Emcr = 1<<3, /* media change request */ - Eidnf = 1<<4, /* no user-accessible address */ - Emc = 1<<5, /* media change */ - Eunc = 1<<6, /* data error */ - Ewp = 1<<6, /* write protect */ - Eicrc = 1<<7, /* interface crc error */ - - Efatal = Eidnf|Eicrc, /* must sw reset. */ -}; - -/* ata status */ -enum{ - ASerr = 1<<0, /* error */ - ASdrq = 1<<3, /* request */ - ASdf = 1<<5, /* fault */ - ASdrdy = 1<<6, /* ready */ - ASbsy = 1<<7, /* busy */ +// ahci generic +// © 2007 coraid, inc + +// ata errors +enum{ + Emed = 1<<0, // media error + Enm = 1<<1, // no media + Eabrt = 1<<2, // abort + Emcr = 1<<3, // media change request + Eidnf = 1<<4, // no user-accessible address + Emc = 1<<5, // media change + Eunc = 1<<6, // data error + Ewp = 1<<6, // write protect + Eicrc = 1<<7, // interface crc error + + Efatal = Eidnf|Eicrc, // must sw reset. +}; + +// ata status +enum{ + ASerr = 1<<0, // error + ASdrq = 1<<3, // request + ASdf = 1<<5, // fault + ASdrdy = 1<<6, // ready + ASbsy = 1<<7, // busy ASobs = 1<<1|1<<2|1<<4, }; -/* pci configuration */ +// pci configuration enum{ Abar = 5, }; -/* - * ahci memory configuration - * - * 0000-0023 generic host control - * 0024-009f reserved - * 00a0-00ff vendor specific. - * 0100-017f port 0 - * ... - * 1080-1100 port 31 - */ - -/* cap bits: supported features */ -enum{ - Hs64a = 1<<31, /* 64-bit addressing */ - Hsncq = 1<<30, /* ncq */ - Hssntf = 1<<29, /* snotification reg. */ - Hsmps = 1<<28, /* mech pres switch */ - Hsss = 1<<27, /* staggered spinup */ - Hsalp = 1<<26, /* aggressive link pm */ - Hsal = 1<<25, /* activity led */ - Hsclo = 1<<24, /* command-list override */ - Hiss = 1<<20, /* for interface speed. */ +/* ahci memory configuration + +0000-0023 generic host control +0024-009f reserved +00a0-00ff vendor specific. +0100-017f port 0 +... +1080-1100 port 31 +*/ + +// cap bits +enum{ + Hs64a = 1<<31, // supports 64-bit addressing + Hsncq = 1<<30, // " ncq + Hssntf = 1<<29, // " snotification reg. + Hsmps = 1<<28, // " mech pres switch + Hsss = 1<<27, // " staggered spinup + Hsalp = 1<<26, // " agressive link pm + Hsal = 1<<25, // " activity led + Hsclo = 1<<24, // " command-list override + Hiss = 1<<20, // " for interface speed. // Hsnzo = 1<<19, - Hsam = 1<<18, /* ahci-mode only */ - Hspm = 1<<17, /* port multiplier */ + Hsam = 1<<18, // " ahci-mode only + Hspm = 1<<17, // " port multiplier // Hfbss = 1<<16, - Hpmb = 1<<15, /* multiple-block pio */ - Hssc = 1<<14, /* slumber state */ - Hpsc = 1<<13, /* partial-slumber state */ - Hncs = 1<<8, /* n command slots */ - Hcccs = 1<<7, /* coal */ - Hems = 1<<6, /* enclosure mgmt. */ - Hsxs = 1<<5, /* external sata. */ - Hnp = 1<<0, /* n ports */ + Hpmb = 1<<15, // " mutiple-block pio + Hssc = 1<<14, // " slumber state + Hpsc = 1<<13, // " partial-slumber state + Hncs = 1<<8, // " n command slots + Hcccs = 1<<7, // " coal + Hems = 1<<6, // " enclosure mgmt. + Hsxs = 1<<5, // " external sata. + Hnp = 1<<0, // " n ports }; -/* ghc bits */ -enum{ - Hae = 1<<31, /* enable ahci */ - Hie = 1<<1, /* " interrupts */ - Hhr = 1<<0, /* hba reset */ +// ghc bits +enum{ + Hae = 1<<31, // enable ahci + Hie = 1<<1, // " interrupts + Hhr = 1<<0, // hba reset }; typedef struct{ u32int cap; u32int ghc; u32int isr; - u32int pi; /* ports implemented */ + u32int pi; // ports implemented u32int ver; - u32int ccc; /* coaleasing control */ + u32int ccc; // coaleasing control u32int cccports; u32int emloc; u32int emctl; } Ahba; enum{ - Acpds = 1<<31, /* cold port detect status */ - Atfes = 1<<30, /* task file error status */ - Ahbfs = 1<<29, /* hba fatal */ - Ahbds = 1<<28, /* hba error (parity error) */ - Aifs = 1<<27, /* interface fatal §6.1.2 */ - Ainfs = 1<<26, /* interface error (recovered) */ - Aofs = 1<<24, /* too many bytes from disk. */ - Aipms = 1<<23, /* incorrect prt mul status */ - Aprcs = 1<<22, /* PhyRdy change status Pxserr.diag.n */ - Adpms = 1<<7, /* mechanical presence status */ - Apcs = 1<<6, /* port connect diag.x */ - Adps = 1<<5, /* descriptor processed */ - Aufs = 1<<4, /* unknown fis diag.f */ - Asdbs = 1<<3, /* set device bits fis received w/ i bit set */ - Adss = 1<<2, /* dma setup */ - Apio = 1<<1, /* pio setup fis */ - Adhrs = 1<<0, /* device to host register fis. */ + Acpds = 1<<31, // cold port detect status + Atfes = 1<<30, // task file error status + Ahbfs = 1<<29, // hba fatal + Ahbds = 1<<28, // hba error (parity error) + Aifs = 1<<27, // interface fatal §6.1.2 + Ainfs = 1<<26, // interface error (recovered) + Aofs = 1<<24, // too many bytes from disk. + Aipms = 1<<23, // incorrect prt mul status + Aprcs = 1<<22, // PhyRdy change status Pxserr.diag.n + Adpms = 1<<7, // mechanical presence status + Apcs = 1<<6, // port connect diag.x + Adps = 1<<5, // descriptor processed + Aufs = 1<<4, // unknown fis diag.f + Asdbs = 1<<3, // set device bits fis received with i bit set. + Adss = 1<<2, // dma setup + Apio = 1<<1, // pio setup fis + Adhrs = 1<<0, // device to host register fis. - IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps| - Aufs|Asdbs|Adss|Adhrs, + IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|Aufs|Asdbs|Adss|Adhrs, Ifatal = Atfes|Ahbfs|Ahbds|Aifs, }; -/* serror bits */ +// serror bits. enum{ - SerrX = 1<<26, /* exchanged */ - SerrF = 1<<25, /* unknown fis */ - SerrT = 1<<24, /* transition error */ - SerrS = 1<<23, /* link sequence */ - SerrH = 1<<22, /* handshake */ - SerrC = 1<<21, /* crc */ - SerrD = 1<<20, /* not used by ahci */ - SerrB = 1<<19, /* 10-tp-8 decode */ - SerrW = 1<<18, /* comm wake */ - SerrI = 1<<17, /* phy internal */ - SerrN = 1<<16, /* phyrdy change */ - - ErrE = 1<<11, /* internal */ - ErrP = 1<<10, /* ata protocol violation */ - ErrC = 1<<9, /* communication */ - ErrT = 1<<8, /* transient */ - ErrM = 1<<1, /* recoverd comm */ - ErrI = 1<<0, /* recovered data integrety */ + SerrX = 1<<26, // exchanged + SerrF = 1<<25, // unknown fis + SerrT = 1<<24, // transition error + SerrS = 1<<23, // link sequence + SerrH = 1<<22, // handshake + SerrC = 1<<21, // crc + SerrD = 1<<20, // not used by ahci + SerrB = 1<<19, // 10-tp-8 decode + SerrW = 1<<18, // comm wake + SerrI = 1<<17, // phy internal + SerrN = 1<<16, // phyrdy change + + ErrE = 1<<11, // internal + ErrP = 1<<10, // ata protocol violation + ErrC = 1<<9, // communication + ErrT = 1<<8, // transient + ErrM = 1<<1, // recoverd comm + ErrI = 1<<0, // recovered data integrety ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI, - SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|SerrI| - SerrN|ErrAll, + SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|SerrI|SerrN|ErrAll, SerrBad = 0x7f<<19, }; -/* cmd register bits */ +// cmd register bits enum{ - Aicc = 1<<28, /* interface communcations control. 4 bits */ - Aasp = 1<<27, /* agressive slumber & partial sleep */ - Aalpe = 1<<26, /* agressive link pm enable */ - Adlae = 1<<25, /* drive led on atapi */ - Aatapi = 1<<24, /* device is atapi */ - Aesp = 1<<21, /* external sata port */ - Acpd = 1<<20, /* cold presence detect */ - Ampsp = 1<<19, /* mechanical pres. */ - Ahpcp = 1<<18, /* hot plug capable */ - Apma = 1<<17, /* pm attached */ - Acps = 1<<16, /* cold presence state */ - Acr = 1<<15, /* cmdlist running */ - Afr = 1<<14, /* fis running */ - Ampss = 1<<13, /* mechanical presence switch state */ - Accs = 1<<8, /* current command slot 12:08 */ - Afre = 1<<4, /* fis enable receive. */ - Aclo = 1<<3, /* command list override */ - Apod = 1<<2, /* power on device (needs cold-pres. detect) */ - Asud = 1<<1, /* spin-up device; requires ss capability. */ - Ast = 1<<0, /* start */ + Aicc = 1<<28, // interface communcations control. 4 bits + Aasp = 1<<27, // agressive slumber & partial sleep + Aalpe = 1<<26, // agressive link pm enable + Adlae = 1<<25, // drive led on atapi + Aatapi = 1<<24, // device is atapi + Aesp = 1<<21, // external sata port + Acpd = 1<<20, // cold presence detect + Ampsp = 1<<19, // mechanical pres. + Ahpcp = 1<<18, // hot plug capable + Apma = 1<<17, // pm attached + Acps = 1<<16, // cold presence state + Acr = 1<<15, // cmdlist running + Afr = 1<<14, // fis running + Ampss = 1<<13, // mechanical presence switch state + Accs = 1<<8, // current command slot 12:08 + Afre = 1<<4, // fis enable receive. + Aclo = 1<<3, // command list override + Apod = 1<<2, // power on device (requires cold-pres. detect) + Asud = 1<<1, // spin-up device; requires ss capability. + Ast = 1<<0, // start Arun = Ast|Acr|Afre|Afr, }; -/* ctl register bits */ +// ctl register bits enum{ - Aipm = 1<<8, /* interface power mgmt. 3=off */ - Aspd = 1<<4, - Adet = 1<<0, /* device detcection. */ + Aipm = 1<<8, // interface power mgmt. 3=off + Aspd = 1<<4, + Adet = 1<<0, // device detcection. }; #define sstatus scr0 @@ -179,12 +174,12 @@ #define sactive scr3 typedef struct{ - u32int list; /* PxCLB must be 1kb aligned. */ + u32int list; // PxCLB must be 1kb aligned. u32int listhi; - u32int fis; /* 256-byte aligned. */ + u32int fis; // 256-byte aligned. u32int fishi; u32int isr; - u32int ie; /* interrupt enable */ + u32int ie; // interrupt enable u32int cmd; u32int res1; u32int task; @@ -193,13 +188,13 @@ u32int scr2; u32int scr1; u32int scr3; - u32int ci; /* command issue */ + u32int ci; // command issue u32int ntf; uchar res2[8]; u32int vendor; }Aport; -/* in host's memory; not memory mapped */ +// in hosts memory; not memory mapped typedef struct{ uchar *base; uchar *d; @@ -210,18 +205,18 @@ }Afis; enum{ - Lprdtl = 1<<16, /* physical region descriptor table len */ - Lpmp = 1<<12, /* port multiplier port */ - Lclear = 1<<10, /* clear busy on R_OK */ + Lprdtl = 1<<16, // physical region descriptor table len + Lpmp = 1<<12, // port multiplier port + Lclear = 1<<10, // clear busy on R_OK Lbist = 1<<9, Lreset = 1<<8, - Lpref = 1<<7, /* prefetchable */ + Lpref = 1<<7, // prefetchable Lwrite = 1<<6, Latapi = 1<<5, - Lcfl = 1<<0, /* command fis length in double words */ + Lcfl = 1<<0, // command fis length in double words }; -/* in hosts memory; memory mapped */ +// in hosts memory; memory mapped typedef struct{ u32int flags; u32int len;