accb4cadc4fbc0e813a88feb5a7d219d676ed426
[akaros.git] / kern / drivers / dev / sdiahci.c
1 #define DEBUG
2 /*
3  * This file is part of the UCB release of Plan 9. It is subject to the license
4  * terms in the LICENSE file found in the top-level directory of this
5  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
6  * part of the UCB release of Plan 9, including this file, may be copied,
7  * modified, propagated, or distributed except according to the terms contained
8  * in the LICENSE file.
9  */
10
11 /*
12  * ahci serial ata driver
13  * copyright © 2007-8 coraid, inc.
14  */
15
16 #include <vfs.h>
17
18 #include <assert.h>
19 #include <cpio.h>
20 #include <error.h>
21 #include <ip.h>
22 #include <kfs.h>
23 #include <kmalloc.h>
24 #include <kref.h>
25 #include <pmap.h>
26 #include <sd.h>
27 #include <slab.h>
28 #include <smp.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <ahci.h>
33
34 enum {
35         Vatiamd = 0x1002,
36         Vintel = 0x8086,
37         Vmarvell = 0x1b4b,
38 };
39
40 #define iprintd(...)                                                           \
41         do {                                                                       \
42                 if (prid)                                                              \
43                         printd(__VA_ARGS__);                                               \
44         } while (0)
45 #define aprintd(...)                                                           \
46         do {                                                                       \
47                 if (datapi)                                                            \
48                         printd(__VA_ARGS__);                                               \
49         } while (0)
50 #define Tname(c) tname[(c)->type]
51 #define Intel(x) ((x)->pci->ven_id == Vintel)
52
53 enum {
54         NCtlr = 16,
55         NCtlrdrv = 32,
56         NDrive = NCtlr * NCtlrdrv,
57
58         Read = 0,
59         Write,
60
61         Nms = 256, /* ms. between drive checks */
62         Mphywait = 2 * 1024 / Nms - 1,
63         Midwait = 16 * 1024 / Nms - 1,
64         Mcomrwait = 64 * 1024 / Nms - 1,
65
66         Obs = 0xa0, /* obsolete device bits */
67
68         /*
69      * if we get more than this many interrupts per tick for a drive,
70      * either the hardware is broken or we've got a bug in this driver.
71      */
72         Maxintrspertick = 2000, /* was 1000 */
73 };
74
75 /* pci space configuration */
76 enum {
77         Pmap = 0x90,
78         Ppcs = 0x91,
79         Prev = 0xa8,
80 };
81
82 enum {
83         Tesb,
84         Tich,
85         Tsb600,
86         Tunk,
87 };
88
89 static char *tname[] = {
90     "63xxesb", "ich", "sb600", "unknown",
91 };
92
93 enum {
94         Dnull,
95         Dmissing,
96         Dnew,
97         Dready,
98         Derror,
99         Dreset,
100         Doffline,
101         Dportreset,
102         Dlast,
103 };
104
105 static char *diskstates[Dlast] = {
106     "null", "missing", "new", "ready", "error", "reset", "offline", "portreset",
107 };
108
109 enum {
110         DMautoneg,
111         DMsatai,
112         DMsataii,
113         DMsata3,
114 };
115
116 static char *modename[] = {
117     /* used in control messages */
118     "auto", "satai", "sataii", "sata3",
119 };
120 static char *descmode[] = {
121     /*  only printed */
122     "auto", "sata 1", "sata 2", "sata 3",
123 };
124
125 static char *flagname[] = {
126     "llba", "smart", "power", "nop", "atapi", "atapi16",
127 };
128
129 struct drive {
130         spinlock_t Lock;
131
132         struct ctlr *ctlr;
133         struct sdunit *unit;
134         char name[10];
135         struct aport *port;
136         struct aportm portm;
137         struct aportc portc; /* redundant ptr to port and portm */
138
139         unsigned char mediachange;
140         unsigned char state;
141         unsigned char smartrs;
142
143         uint64_t sectors;
144         uint32_t secsize;
145         uint32_t intick; /* start tick of current transfer */
146         uint32_t lastseen;
147         int wait;
148         unsigned char mode; /* DMautoneg, satai or sataii */
149         unsigned char active;
150
151         char serial[20 + 1];
152         char firmware[8 + 1];
153         char model[40 + 1];
154
155         int infosz;
156         uint16_t *info;
157         uint16_t tinyinfo[2]; /* used iff malloc fails */
158
159         int driveno; /* ctlr*NCtlrdrv + unit */
160         /* controller port # != driveno when not all ports are enabled */
161         int portno;
162
163         uint32_t lastintr0;
164         uint32_t intrs;
165 };
166
167 struct ctlr {
168         spinlock_t Lock;
169
170         int type;
171         int enabled;
172         struct sdev *sdev;
173         struct pci_device *pci;
174         void *vector;
175
176         /* virtual register addresses */
177         uintptr_t mmio;
178         Ahba *hba;
179
180         /* phyical register address */
181         uintptr_t physio;
182
183         struct drive *rawdrive;
184         struct drive *drive[NCtlrdrv];
185         int ndrive;
186         int mport; /* highest drive # (0-origin) on ich9 at least */
187
188         uint32_t lastintr0;
189         uint32_t intrs; /* not attributable to any drive */
190 };
191
192 struct Asleep {
193         struct aport *p;
194         int i;
195 };
196
197 extern struct sdifc sdiahciifc;
198
199 static struct ctlr iactlr[NCtlr];
200 static struct sdev sdevs[NCtlr];
201 static int niactlr;
202
203 static struct drive *iadrive[NDrive];
204 static int niadrive;
205
206 /* these are fiddled in iawtopctl() */
207 static int debug;
208 static int prid = 1;
209 static int datapi;
210
211 // TODO: does this get initialized correctly?
212 static char stab[] = {
213         [0]     = 'i', 'm',
214         [8]     = 't', 'c', 'p', 'e',
215         [16]    = 'N', 'I', 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
216 };
217
218 /* ALL time units in this file are in milliseconds. */
219 static uint32_t ms(void)
220 {
221         return (uint32_t)(epoch_nsec() / 1048576);
222 }
223
224 /* TODO: if we like this, make it useable elsewhere. */
225 static void sdierror(struct cmdbuf *cb, char *fmt, ...)
226 {
227         char *c = kzmalloc(512, MEM_WAIT);
228         va_list ap;
229
230         assert(fmt);
231         va_start(ap, fmt);
232         vsnprintf(c, 512, fmt, ap);
233         va_end(ap);
234         cmderror(cb, c);
235         kfree(c);
236 }
237
238 static void serrstr(uint32_t r, char *s, char *e)
239 {
240         int i;
241
242         e -= 3;
243         for (i = 0; i < ARRAY_SIZE(stab) && s < e; i++)
244                 if (r & (1 << i) && stab[i]) {
245                         *s++ = stab[i];
246                         if (SerrBad & (1 << i))
247                                 *s++ = '*';
248                 }
249         *s = 0;
250 }
251
252 static char ntab[] = "0123456789abcdef";
253
254 static void preg(unsigned char *reg, int n)
255 {
256         int i;
257         char buf[25 * 3 + 1], *e;
258
259         e = buf;
260         for (i = 0; i < n; i++) {
261                 *e++ = ntab[reg[i] >> 4];
262                 *e++ = ntab[reg[i] & 0xf];
263                 *e++ = ' ';
264         }
265         *e++ = '\n';
266         *e = 0;
267         printd(buf);
268 }
269
270 static void dreg(char *s, struct aport *p)
271 {
272         printd("ahci: %stask=%#lx; cmd=%#lx; ci=%#lx; is=%#lx\n", s, p->task,
273                p->cmd, p->ci, p->isr);
274 }
275
276 static void esleep(int ms)
277 {
278         ERRSTACK(2);
279         if (waserror())
280                 return;
281         kthread_usleep(ms * 1000);
282         poperror();
283 }
284
285 static int ahciclear(void *v)
286 {
287         struct Asleep *s;
288
289         s = v;
290         return (s->p->ci & s->i) == 0;
291 }
292
293 static void aesleep(struct aportm *pm, struct Asleep *a, int ms)
294 {
295         ERRSTACK(2);
296         if (waserror())
297                 return;
298         rendez_sleep_timeout(&pm->Rendez, ahciclear, a, ms * 1000);
299         poperror();
300 }
301
302 static int ahciwait(struct aportc *c, int ms)
303 {
304         struct Asleep as;
305         struct aport *p;
306
307         p = c->p;
308         p->ci = 1;
309         as.p = p;
310         as.i = 1;
311         aesleep(c->pm, &as, ms);
312         if ((p->task & 1) == 0 && p->ci == 0)
313                 return 0;
314         dreg("ahciwait timeout ", c->p);
315         return -1;
316 }
317
318 /* fill in cfis boilerplate */
319 static unsigned char *cfissetup(struct aportc *pc)
320 {
321         unsigned char *cfis;
322
323         cfis = pc->pm->ctab->cfis;
324         memset(cfis, 0, 0x20);
325         cfis[0] = 0x27;
326         cfis[1] = 0x80;
327         cfis[7] = Obs;
328         return cfis;
329 }
330
331 /* initialise pc's list */
332 static void listsetup(struct aportc *pc, int flags)
333 {
334         struct alist *list;
335
336         list = pc->pm->list;
337         list->flags = flags | 5;
338         list->len = 0;
339         list->ctab = PCIWADDR(pc->pm->ctab);
340         list->ctabhi = 0;
341 }
342
343 static int nop(struct aportc *pc)
344 {
345         unsigned char *c;
346
347         if ((pc->pm->feat & Dnop) == 0)
348                 return -1;
349         c = cfissetup(pc);
350         c[2] = 0;
351         listsetup(pc, Lwrite);
352         return ahciwait(pc, 3 * 1000);
353 }
354
355 static int setfeatures(struct aportc *pc, unsigned char f)
356 {
357         unsigned char *c;
358
359         c = cfissetup(pc);
360         c[2] = 0xef;
361         c[3] = f;
362         listsetup(pc, Lwrite);
363         return ahciwait(pc, 3 * 1000);
364 }
365
366 static int setudmamode(struct aportc *pc, unsigned char f)
367 {
368         unsigned char *c;
369
370         /* hack */
371         if ((pc->p->sig >> 16) == 0xeb14)
372                 return 0;
373         c = cfissetup(pc);
374         c[2] = 0xef;
375         c[3] = 3;         /* set transfer mode */
376         c[12] = 0x40 | f; /* sector count */
377         listsetup(pc, Lwrite);
378         return ahciwait(pc, 3 * 1000);
379 }
380
381 static void asleep(int ms)
382 {
383         udelay(ms * 1000);
384 }
385
386 static int ahciportreset(struct aportc *c)
387 {
388         uint32_t *cmd, i;
389         struct aport *p;
390
391         p = c->p;
392         cmd = &p->cmd;
393         *cmd &= ~(Afre | Ast);
394         for (i = 0; i < 500; i += 25) {
395                 if ((*cmd & Acr) == 0)
396                         break;
397                 asleep(25);
398         }
399         p->sctl = 1 | (p->sctl & ~7);
400         printk("Sleeping one second\n");
401         udelay(1000 * 1000);
402         p->sctl &= ~7;
403         return 0;
404 }
405
406 static int smart(struct aportc *pc, int n)
407 {
408         unsigned char *c;
409
410         if ((pc->pm->feat & Dsmart) == 0)
411                 return -1;
412         c = cfissetup(pc);
413         c[2] = 0xb0;
414         c[3] = 0xd8 + n; /* able smart */
415         c[5] = 0x4f;
416         c[6] = 0xc2;
417         listsetup(pc, Lwrite);
418         if (ahciwait(pc, 1000) == -1 || pc->p->task & (1 | 32)) {
419                 printd("ahci: smart fail %#lx\n", pc->p->task);
420                 return -1;
421         }
422         if (n)
423                 return 0;
424         return 1;
425 }
426
427 static int smartrs(struct aportc *pc)
428 {
429         unsigned char *c;
430
431         c = cfissetup(pc);
432         c[2] = 0xb0;
433         c[3] = 0xda; /* return smart status */
434         c[5] = 0x4f;
435         c[6] = 0xc2;
436         listsetup(pc, Lwrite);
437
438         c = pc->pm->fis.r;
439         if (ahciwait(pc, 1000) == -1 || pc->p->task & (1 | 32)) {
440                 printd("ahci: smart fail %#lx\n", pc->p->task);
441                 preg(c, 20);
442                 return -1;
443         }
444         if (c[5] == 0x4f && c[6] == 0xc2)
445                 return 1;
446         return 0;
447 }
448
449 static int ahciflushcache(struct aportc *pc)
450 {
451         unsigned char *c;
452
453         c = cfissetup(pc);
454         c[2] = pc->pm->feat & Dllba ? 0xea : 0xe7;
455         listsetup(pc, Lwrite);
456         if (ahciwait(pc, 60000) == -1 || pc->p->task & (1 | 32)) {
457                 printd("ahciflushcache: fail %#lx\n", pc->p->task);
458                 //              preg(pc->m->fis.r, 20);
459                 return -1;
460         }
461         return 0;
462 }
463
464 static uint16_t gbit16(void *a)
465 {
466         unsigned char *i;
467
468         i = a;
469         return i[1] << 8 | i[0];
470 }
471
472 static uint32_t gbit32(void *a)
473 {
474         uint32_t j;
475         unsigned char *i;
476
477         i = a;
478         j = i[3] << 24;
479         j |= i[2] << 16;
480         j |= i[1] << 8;
481         j |= i[0];
482         return j;
483 }
484
485 static uint64_t gbit64(void *a)
486 {
487         unsigned char *i;
488
489         i = a;
490         return (uint64_t)gbit32(i + 4) << 32 | gbit32(a);
491 }
492
493 static int ahciidentify0(struct aportc *pc, void *id, int atapi)
494 {
495         unsigned char *c;
496         struct aprdt *p;
497         static unsigned char tab[] = {
498             0xec, 0xa1,
499         };
500
501         c = cfissetup(pc);
502         c[2] = tab[atapi];
503         listsetup(pc, 1 << 16);
504
505         memset(id, 0, 0x100); /* magic */
506         p = &pc->pm->ctab->prdt;
507         p->dba = PCIWADDR(id);
508         p->dbahi = 0;
509         p->count = 1 << 31 | (0x200 - 2) | 1;
510         return ahciwait(pc, 3 * 1000);
511 }
512
513 static int64_t ahciidentify(struct aportc *pc, uint16_t *id)
514 {
515         int i, sig;
516         int64_t s;
517         struct aportm *pm;
518
519         pm = pc->pm;
520         pm->feat = 0;
521         pm->smart = 0;
522         i = 0;
523         sig = pc->p->sig >> 16;
524         if (sig == 0xeb14) {
525                 pm->feat |= Datapi;
526                 i = 1;
527         }
528         if (ahciidentify0(pc, id, i) == -1)
529                 return -1;
530
531         i = gbit16(id + 83) | gbit16(id + 86);
532         if (i & (1 << 10)) {
533                 pm->feat |= Dllba;
534                 s = gbit64(id + 100);
535         } else
536                 s = gbit32(id + 60);
537
538         if (pm->feat & Datapi) {
539                 i = gbit16(id + 0);
540                 if (i & 1)
541                         pm->feat |= Datapi16;
542         }
543
544         i = gbit16(id + 83);
545         if ((i >> 14) == 1) {
546                 if (i & (1 << 3))
547                         pm->feat |= Dpower;
548                 i = gbit16(id + 82);
549                 if (i & 1)
550                         pm->feat |= Dsmart;
551                 if (i & (1 << 14))
552                         pm->feat |= Dnop;
553         }
554         return s;
555 }
556
557 #if 0
558 static int
559 ahciquiet(Aport *a)
560 {
561         uint32_t *p, i;
562
563         p = &a->cmd;
564         *p &= ~Ast;
565         for(i = 0; i < 500; i += 50){
566                 if((*p & Acr) == 0)
567                         goto stop;
568                 asleep(50);
569         }
570         return -1;
571 stop:
572         if((a->task & (ASdrq|ASbsy)) == 0){
573                 *p |= Ast;
574                 return 0;
575         }
576
577         *p |= Aclo;
578         for(i = 0; i < 500; i += 50){
579                 if((*p & Aclo) == 0)
580                         goto stop1;
581                 asleep(50);
582         }
583         return -1;
584 stop1:
585         /* extra check */
586         printd("ahci: clo clear %#lx\n", a->task);
587         if(a->task & ASbsy)
588                 return -1;
589         *p |= Ast;
590         return 0;
591 }
592 #endif
593
594 #if 0
595 static int
596 ahcicomreset(Aportc *pc)
597 {
598         unsigned char *c;
599
600         printd("ahcicomreset\n");
601         dreg("ahci: comreset ", pc->p);
602         if(ahciquiet(pc->p) == -1){
603                 printd("ahciquiet failed\n");
604                 return -1;
605         }
606         dreg("comreset ", pc->p);
607
608         c = cfissetup(pc);
609         c[1] = 0;
610         c[15] = 1<<2;           /* srst */
611         listsetup(pc, Lclear | Lreset);
612         if(ahciwait(pc, 500) == -1){
613                 printd("ahcicomreset: first command failed\n");
614                 return -1;
615         }
616         microdelay(250);
617         dreg("comreset ", pc->p);
618
619         c = cfissetup(pc);
620         c[1] = 0;
621         listsetup(pc, Lwrite);
622         if (ahciwait(pc, 150) == -1) {
623                 printd("ahcicomreset: second command failed\n");
624                 return -1;
625         }
626         dreg("comreset ", pc->p);
627         return 0;
628 }
629 #endif
630
631 static int ahciidle(struct aport *port)
632 {
633         uint32_t *p, i, r;
634
635         p = &port->cmd;
636         if ((*p & Arun) == 0)
637                 return 0;
638         *p &= ~Ast;
639         r = 0;
640         for (i = 0; i < 500; i += 25) {
641                 if ((*p & Acr) == 0)
642                         goto stop;
643                 asleep(25);
644         }
645         r = -1;
646 stop:
647         if ((*p & Afre) == 0)
648                 return r;
649         *p &= ~Afre;
650         for (i = 0; i < 500; i += 25) {
651                 if ((*p & Afre) == 0)
652                         return 0;
653                 asleep(25);
654         }
655         return -1;
656 }
657
658 /*
659  * § 6.2.2.1  first part; comreset handled by reset disk.
660  *      - remainder is handled by configdisk.
661  *      - ahcirecover is a quick recovery from a failed command.
662  */
663 static int ahciswreset(struct aportc *pc)
664 {
665         int i;
666
667         i = ahciidle(pc->p);
668         pc->p->cmd |= Afre;
669         if (i == -1)
670                 return -1;
671         if (pc->p->task & (ASdrq | ASbsy))
672                 return -1;
673         return 0;
674 }
675
676 static int ahcirecover(struct aportc *pc)
677 {
678         ahciswreset(pc);
679         pc->p->cmd |= Ast;
680         if (setudmamode(pc, 5) == -1)
681                 return -1;
682         return 0;
683 }
684
685 static void *malign(int size, int align)
686 {
687         return kmalloc_align(size, MEM_WAIT, align);
688 }
689
690 static void setupfis(struct afis *f)
691 {
692         f->base = malign(0x100, 0x100); /* magic */
693         f->d = f->base + 0;
694         f->p = f->base + 0x20;
695         f->r = f->base + 0x40;
696         f->u = f->base + 0x60;
697         f->devicebits = (uint32_t *)(f->base + 0x58);
698 }
699
700 static void ahciwakeup(struct aport *p)
701 {
702         uint16_t s;
703
704         s = p->sstatus;
705         if ((s & Intpm) != Intslumber && (s & Intpm) != Intpartpwr)
706                 return;
707         if ((s & Devdet) != Devpresent) { /* not (device, no phy) */
708                 iprint("ahci: slumbering drive unwakable %#x\n", s);
709                 return;
710         }
711         p->sctl = 3 * Aipm | 0 * Aspd | Adet;
712         udelay(1000 * 1000);
713         p->sctl &= ~7;
714         //      iprint("ahci: wake %#x -> %#x\n", s, p->sstatus);
715 }
716
717 static int ahciconfigdrive(struct drive *d)
718 {
719         char *name;
720         Ahba *h;
721         struct aport *p;
722         struct aportm *pm;
723
724         h = d->ctlr->hba;
725         p = d->portc.p;
726         pm = d->portc.pm;
727         if (pm->list == 0) {
728                 setupfis(&pm->fis);
729                 pm->list = malign(sizeof *pm->list, 1024);
730                 pm->ctab = malign(sizeof *pm->ctab, 128);
731         }
732
733         if (d->unit)
734                 name = d->unit->sdperm.name;
735         else
736                 name = NULL;
737         if (p->sstatus & (Devphycomm | Devpresent) && h->cap & Hsss) {
738                 /* device connected & staggered spin-up */
739                 printd("ahci: configdrive: %s: spinning up ... [%#lx]\n", name,
740                        p->sstatus);
741                 p->cmd |= Apod | Asud;
742                 asleep(1400);
743         }
744
745         p->serror = SerrAll;
746
747         p->list = PCIWADDR(pm->list);
748         p->listhi = 0;
749         p->fis = PCIWADDR(pm->fis.base);
750         p->fishi = 0;
751         p->cmd |= Afre | Ast;
752
753         /* drive coming up in slumbering? */
754         if ((p->sstatus & Devdet) == Devpresent &&
755             ((p->sstatus & Intpm) == Intslumber ||
756              (p->sstatus & Intpm) == Intpartpwr))
757                 ahciwakeup(p);
758
759         /* "disable power management" sequence from book. */
760         p->sctl = (3 * Aipm) | (d->mode * Aspd) | (0 * Adet);
761         p->cmd &= ~Aalpe;
762
763         p->ie = IEM;
764
765         return 0;
766 }
767
768 static void ahcienable(Ahba *h)
769 {
770         h->ghc |= Hie;
771 }
772
773 static void ahcidisable(Ahba *h)
774 {
775         h->ghc &= ~Hie;
776 }
777
778 static int countbits(uint32_t u)
779 {
780         int n;
781
782         n = 0;
783         for (; u != 0; u >>= 1)
784                 if (u & 1)
785                         n++;
786         return n;
787 }
788
789 static int ahciconf(struct ctlr *ctlr)
790 {
791         Ahba *h;
792         uint32_t u;
793
794         h = ctlr->hba = (Ahba *)ctlr->mmio;
795         u = h->cap;
796
797         if ((u & Hsam) == 0)
798                 h->ghc |= Hae;
799
800         printd("#S/sd%c: type %s port %#p: sss %ld ncs %ld coal %ld "
801                "%ld ports, led %ld clo %ld ems %ld\n",
802                ctlr->sdev->idno, tname[ctlr->type], h, (u >> 27) & 1,
803                (u >> 8) & 0x1f, (u >> 7) & 1, (u & 0x1f) + 1, (u >> 25) & 1,
804                (u >> 24) & 1, (u >> 6) & 1);
805         return countbits(h->pi);
806 }
807
808 #if 0
809 static int
810 ahcihbareset(Ahba *h)
811 {
812         int wait;
813
814         h->ghc |= 1;
815         for(wait = 0; wait < 1000; wait += 100){
816                 if(h->ghc == 0)
817                         return 0;
818                 delay(100);
819         }
820         return -1;
821 }
822 #endif
823
824 static void idmove(char *p, uint16_t *a, int n)
825 {
826         int i;
827         char *op, *e;
828
829         op = p;
830         for (i = 0; i < n / 2; i++) {
831                 *p++ = a[i] >> 8;
832                 *p++ = a[i];
833         }
834         *p = 0;
835         while (p > op && *--p == ' ')
836                 *p = 0;
837         e = p;
838         for (p = op; *p == ' '; p++)
839                 ;
840         memmove(op, p, n - (e - p));
841 }
842
843 static int identify(struct drive *d)
844 {
845         uint16_t *id;
846         int64_t osectors, s;
847         unsigned char oserial[21];
848         struct sdunit *u;
849
850         if (d->info == NULL) {
851                 d->infosz = 512 * sizeof(uint16_t);
852                 d->info = kzmalloc(d->infosz, 0);
853         }
854         if (d->info == NULL) {
855                 d->info = d->tinyinfo;
856                 d->infosz = sizeof d->tinyinfo;
857         }
858         id = d->info;
859         s = ahciidentify(&d->portc, id);
860         if (s == -1) {
861                 d->state = Derror;
862                 return -1;
863         }
864         osectors = d->sectors;
865         memmove(oserial, d->serial, sizeof d->serial);
866
867         u = d->unit;
868         d->sectors = s;
869         d->secsize = u->secsize;
870         if (d->secsize == 0)
871                 d->secsize = 512; /* default */
872         d->smartrs = 0;
873
874         idmove(d->serial, id + 10, 20);
875         idmove(d->firmware, id + 23, 8);
876         idmove(d->model, id + 27, 40);
877
878         memset(u->inquiry, 0, sizeof u->inquiry);
879         u->inquiry[2] = 2;
880         u->inquiry[3] = 2;
881         u->inquiry[4] = sizeof u->inquiry - 4;
882         memmove(u->inquiry + 8, d->model, 40);
883
884         if (osectors != s || memcmp(oserial, d->serial, sizeof oserial) != 0) {
885                 d->mediachange = 1;
886                 u->sectors = 0;
887         }
888         return 0;
889 }
890
891 static void clearci(struct aport *p)
892 {
893         if (p->cmd & Ast) {
894                 p->cmd &= ~Ast;
895                 p->cmd |= Ast;
896         }
897 }
898
899 static void updatedrive(struct drive *d)
900 {
901         uint32_t cause, serr, s0, pr, ewake;
902         char *name;
903         struct aport *p;
904         static uint32_t last;
905
906         pr = 1;
907         ewake = 0;
908         p = d->port;
909         cause = p->isr;
910         serr = p->serror;
911         p->isr = cause;
912         name = "??";
913         if (d->unit && d->unit->sdperm.name)
914                 name = d->unit->sdperm.name;
915
916         if (p->ci == 0) {
917                 d->portm.flag |= Fdone;
918                 rendez_wakeup(&d->portm.Rendez);
919                 pr = 0;
920         } else if (cause & Adps)
921                 pr = 0;
922         if (cause & Ifatal) {
923                 ewake = 1;
924                 printd("ahci: updatedrive: %s: fatal\n", name);
925         }
926         if (cause & Adhrs) {
927                 if (p->task & (1 << 5 | 1)) {
928                         printd("ahci: %s: Adhrs cause %#lx serr %#lx task %#lx\n", name,
929                                cause, serr, p->task);
930                         d->portm.flag |= Ferror;
931                         ewake = 1;
932                 }
933                 pr = 0;
934         }
935         if (p->task & 1 && last != cause)
936                 printd("%s: err ca %#lx serr %#lx task %#lx sstat %#lx\n", name, cause,
937                        serr, p->task, p->sstatus);
938         if (pr)
939                 printd("%s: upd %#lx ta %#lx\n", name, cause, p->task);
940
941         if (cause & (Aprcs | Aifs)) {
942                 s0 = d->state;
943                 switch (p->sstatus & Devdet) {
944                 case 0: /* no device */
945                         d->state = Dmissing;
946                         break;
947                 case Devpresent: /* device but no phy comm. */
948                         if ((p->sstatus & Intpm) == Intslumber ||
949                             (p->sstatus & Intpm) == Intpartpwr)
950                                 d->state = Dnew; /* slumbering */
951                         else
952                                 d->state = Derror;
953                         break;
954                 case Devpresent | Devphycomm:
955                         /* power mgnt crap for surprise removal */
956                         p->ie |= Aprcs | Apcs; /* is this required? */
957                         d->state = Dreset;
958                         break;
959                 case Devphyoffline:
960                         d->state = Doffline;
961                         break;
962                 }
963                 printd("%s: %s → %s [Apcrs] %#lx\n", name, diskstates[s0],
964                        diskstates[d->state], p->sstatus);
965                 /* print pulled message here. */
966                 if (s0 == Dready && d->state != Dready)
967                         iprintd("%s: pulled\n", name); /* wtf? */
968                 if (d->state != Dready)
969                         d->portm.flag |= Ferror;
970                 ewake = 1;
971         }
972         p->serror = serr;
973         if (ewake) {
974                 clearci(p);
975                 rendez_wakeup(&d->portm.Rendez);
976         }
977         last = cause;
978 }
979
980 static void pstatus(struct drive *d, uint32_t s)
981 {
982         /*
983          * s is masked with Devdet.
984          *
985          * bogus code because the first interrupt is currently dropped.
986          * likely my fault.  serror may be cleared at the wrong time.
987          */
988         switch (s) {
989         case 0: /* no device */
990                 d->state = Dmissing;
991                 break;
992         case Devpresent: /* device but no phy. comm. */
993                 break;
994         case Devphycomm: /* should this be missing?  need testcase. */
995                 printd("ahci: pstatus 2\n");
996         /* fallthrough */
997         case Devpresent | Devphycomm:
998                 d->wait = 0;
999                 d->state = Dnew;
1000                 break;
1001         case Devphyoffline:
1002                 d->state = Doffline;
1003                 break;
1004         case Devphyoffline | Devphycomm: /* does this make sense? */
1005                 d->state = Dnew;
1006                 break;
1007         }
1008 }
1009
1010 static int configdrive(struct drive *d)
1011 {
1012         if (ahciconfigdrive(d) == -1)
1013                 return -1;
1014         spin_lock_irqsave(&d->Lock);
1015         pstatus(d, d->port->sstatus & Devdet);
1016         spin_unlock_irqsave(&d->Lock);
1017         return 0;
1018 }
1019
1020 static void setstate(struct drive *d, int state)
1021 {
1022         spin_lock_irqsave(&d->Lock);
1023         d->state = state;
1024         spin_unlock_irqsave(&d->Lock);
1025 }
1026
1027 static void resetdisk(struct drive *d)
1028 {
1029         unsigned int state, det, stat;
1030         struct aport *p;
1031
1032         p = d->port;
1033         det = p->sctl & 7;
1034         stat = p->sstatus & Devdet;
1035         state = (p->cmd >> 28) & 0xf;
1036         printd("ahci: resetdisk: icc %#x  det %d sdet %d\n", state, det, stat);
1037
1038         spin_lock_irqsave(&d->Lock);
1039         state = d->state;
1040         if (d->state != Dready || d->state != Dnew)
1041                 d->portm.flag |= Ferror;
1042         clearci(p); /* satisfy sleep condition. */
1043         rendez_wakeup(&d->portm.Rendez);
1044         if (stat != (Devpresent | Devphycomm)) {
1045                 /* device absent or phy not communicating */
1046                 d->state = Dportreset;
1047                 spin_unlock_irqsave(&d->Lock);
1048                 return;
1049         }
1050         d->state = Derror;
1051         spin_unlock_irqsave(&d->Lock);
1052
1053         qlock(&d->portm.ql);
1054         if (p->cmd & Ast && ahciswreset(&d->portc) == -1)
1055                 setstate(d, Dportreset); /* get a bigger stick. */
1056         else {
1057                 setstate(d, Dmissing);
1058                 configdrive(d);
1059         }
1060         printd("ahci: %s: resetdisk: %s → %s\n",
1061                (d->unit ? d->unit->sdperm.name : NULL), diskstates[state],
1062                diskstates[d->state]);
1063         qunlock(&d->portm.ql);
1064 }
1065
1066 static int newdrive(struct drive *d)
1067 {
1068         char *name;
1069         struct aportc *c;
1070         struct aportm *pm;
1071
1072         c = &d->portc;
1073         pm = &d->portm;
1074
1075         name = d->unit->sdperm.name;
1076         if (name == 0)
1077                 name = "??";
1078
1079         if (d->port->task == 0x80)
1080                 return -1;
1081         qlock(&c->pm->ql);
1082         if (setudmamode(c, 5) == -1) {
1083                 printd("%s: can't set udma mode\n", name);
1084                 goto lose;
1085         }
1086         if (identify(d) == -1) {
1087                 printd("%s: identify failure\n", name);
1088                 goto lose;
1089         }
1090         if (pm->feat & Dpower && setfeatures(c, 0x85) == -1) {
1091                 pm->feat &= ~Dpower;
1092                 if (ahcirecover(c) == -1)
1093                         goto lose;
1094         }
1095         setstate(d, Dready);
1096         qunlock(&c->pm->ql);
1097
1098         iprintd("%s: %sLBA %llu sectors: %s %s %s %s\n", d->unit->sdperm.name,
1099                 (pm->feat & Dllba ? "L" : ""), d->sectors, d->model, d->firmware,
1100                 d->serial, d->mediachange ? "[mediachange]" : "");
1101         return 0;
1102
1103 lose:
1104         iprintd("%s: can't be initialized\n", d->unit->sdperm.name);
1105         setstate(d, Dnull);
1106         qunlock(&c->pm->ql);
1107         return -1;
1108 }
1109
1110 static void westerndigitalhung(struct drive *d)
1111 {
1112         if ((d->portm.feat & Datapi) == 0 && d->active &&
1113             (ms() - d->intick) > 5000) {
1114                 printd("%s: drive hung; resetting [%#lx] ci %#lx\n",
1115                        d->unit->sdperm.name, d->port->task, d->port->ci);
1116                 d->state = Dreset;
1117         }
1118 }
1119
1120 static uint16_t olds[NCtlr * NCtlrdrv];
1121
1122 static int doportreset(struct drive *d)
1123 {
1124         int i;
1125
1126         i = -1;
1127         qlock(&d->portm.ql);
1128         if (ahciportreset(&d->portc) == -1)
1129                 printd("ahci: doportreset: fails\n");
1130         else
1131                 i = 0;
1132         qunlock(&d->portm.ql);
1133         printd("ahci: doportreset: portreset → %s  [task %#lx]\n",
1134                diskstates[d->state], d->port->task);
1135         return i;
1136 }
1137
1138 /* drive must be locked */
1139 static void statechange(struct drive *d)
1140 {
1141         switch (d->state) {
1142         case Dnull:
1143         case Doffline:
1144                 if (d->unit->sectors != 0) {
1145                         d->sectors = 0;
1146                         d->mediachange = 1;
1147                 }
1148         /* fallthrough */
1149         case Dready:
1150                 d->wait = 0;
1151                 break;
1152         }
1153 }
1154
1155 static void checkdrive(struct drive *d, int i)
1156 {
1157         uint16_t s;
1158         char *name;
1159
1160         if (d == NULL) {
1161                 printd("checkdrive: NULL d\n");
1162                 return;
1163         }
1164         spin_lock_irqsave(&d->Lock);
1165         if (d->unit == NULL || d->port == NULL) {
1166                 if (0)
1167                         printk("checkdrive: nil d->%s\n",
1168                                d->unit == NULL ? "unit" : "port");
1169                 spin_unlock_irqsave(&d->Lock);
1170                 return;
1171         }
1172         name = d->unit->sdperm.name;
1173         s = d->port->sstatus;
1174         if (s)
1175                 d->lastseen = ms();
1176         if (s != olds[i]) {
1177                 printd("%s: status: %06#x -> %06#x: %s\n", name, olds[i], s,
1178                        diskstates[d->state]);
1179                 olds[i] = s;
1180                 d->wait = 0;
1181         }
1182         westerndigitalhung(d);
1183
1184         switch (d->state) {
1185         case Dnull:
1186         case Dready:
1187                 break;
1188         case Dmissing:
1189         case Dnew:
1190                 switch (s & (Intactive | Devdet)) {
1191                 case Devpresent: /* no device (pm), device but no phy. comm. */
1192                         ahciwakeup(d->port);
1193                 /* fall through */
1194                 case 0: /* no device */
1195                         break;
1196                 default:
1197                         printd("%s: unknown status %06#x\n", name, s);
1198                 /* fall through */
1199                 case Intactive: /* active, no device */
1200                         if (++d->wait & Mphywait)
1201                                 break;
1202                 reset:
1203                         if (++d->mode > DMsataii)
1204                                 d->mode = 0;
1205                         if (d->mode == DMsatai) { /* we tried everything */
1206                                 d->state = Dportreset;
1207                                 goto portreset;
1208                         }
1209                         printd("%s: reset; new mode %s\n", name, modename[d->mode]);
1210                         spin_unlock_irqsave(&d->Lock);
1211                         resetdisk(d);
1212                         spin_lock_irqsave(&d->Lock);
1213                         break;
1214                 case Intactive | Devphycomm | Devpresent:
1215                         if ((++d->wait & Midwait) == 0) {
1216                                 printd("%s: slow reset %06#x task=%#lx; %d\n", name, s,
1217                                        d->port->task, d->wait);
1218                                 goto reset;
1219                         }
1220                         s = (unsigned char)d->port->task;
1221                         if (s == 0x7f ||
1222                             ((d->port->sig >> 16) != 0xeb14 && (s & ~0x17) != (1 << 6)))
1223                                 break;
1224                         spin_unlock_irqsave(&d->Lock);
1225                         newdrive(d);
1226                         spin_lock_irqsave(&d->Lock);
1227                         break;
1228                 }
1229                 break;
1230         case Doffline:
1231                 if (d->wait++ & Mcomrwait)
1232                         break;
1233         /* fallthrough */
1234         case Derror:
1235         case Dreset:
1236                 printd("%s: reset [%s]: mode %d; status %06#x\n", name,
1237                        diskstates[d->state], d->mode, s);
1238                 spin_unlock_irqsave(&d->Lock);
1239                 resetdisk(d);
1240                 spin_lock_irqsave(&d->Lock);
1241                 break;
1242         case Dportreset:
1243         portreset:
1244                 if (d->wait++ & 0xff && (s & Intactive) == 0)
1245                         break;
1246                 /* device is active */
1247                 printd("%s: portreset [%s]: mode %d; status %06#x\n", name,
1248                        diskstates[d->state], d->mode, s);
1249                 d->portm.flag |= Ferror;
1250                 clearci(d->port);
1251                 rendez_wakeup(&d->portm.Rendez);
1252                 if ((s & Devdet) == 0) { /* no device */
1253                         d->state = Dmissing;
1254                         break;
1255                 }
1256                 spin_unlock_irqsave(&d->Lock);
1257                 doportreset(d);
1258                 spin_lock_irqsave(&d->Lock);
1259                 break;
1260         }
1261         statechange(d);
1262         spin_unlock_irqsave(&d->Lock);
1263 }
1264
1265 static void satakproc(void *v)
1266 {
1267         int i;
1268         for (;;) {
1269                 kthread_usleep(Nms * 1000);
1270                 for (i = 0; i < niadrive; i++)
1271                         if (iadrive[i] != NULL)
1272                                 checkdrive(iadrive[i], i);
1273         }
1274 }
1275
1276 static void isctlrjabbering(struct ctlr *c, uint32_t cause)
1277 {
1278         uint32_t now;
1279
1280         now = ms();
1281         if (now > c->lastintr0) {
1282                 c->intrs = 0;
1283                 c->lastintr0 = now;
1284         }
1285         if (++c->intrs > Maxintrspertick) {
1286                 iprint("sdiahci: %lu intrs per tick for no serviced "
1287                        "drive; cause %#lx mport %d\n",
1288                        c->intrs, cause, c->mport);
1289                 c->intrs = 0;
1290         }
1291 }
1292
1293 static void isdrivejabbering(struct drive *d)
1294 {
1295         uint32_t now = ms();
1296
1297         if (now > d->lastintr0) {
1298                 d->intrs = 0;
1299                 d->lastintr0 = now;
1300         }
1301         if (++d->intrs > Maxintrspertick) {
1302                 iprint("sdiahci: %lu interrupts per tick for %s\n", d->intrs,
1303                        d->unit->sdperm.name);
1304                 d->intrs = 0;
1305         }
1306 }
1307
1308 static void iainterrupt(struct hw_trapframe *unused_hw_trapframe, void *a)
1309 {
1310         int i;
1311         uint32_t cause, mask;
1312         struct ctlr *c;
1313         struct drive *d;
1314
1315         c = a;
1316         spin_lock_irqsave(&c->Lock);
1317         cause = c->hba->isr;
1318         if (cause == 0) {
1319                 isctlrjabbering(c, cause);
1320                 // iprint("sdiahci: interrupt for no drive\n");
1321                 spin_unlock_irqsave(&c->Lock);
1322                 return;
1323         }
1324         for (i = 0; cause && i <= c->mport; i++) {
1325                 mask = 1 << i;
1326                 if ((cause & mask) == 0)
1327                         continue;
1328                 d = c->rawdrive + i;
1329                 spin_lock_irqsave(&d->Lock);
1330                 isdrivejabbering(d);
1331                 if (d->port->isr && c->hba->pi & mask)
1332                         updatedrive(d);
1333                 c->hba->isr = mask;
1334                 spin_unlock_irqsave(&d->Lock);
1335
1336                 cause &= ~mask;
1337         }
1338         if (cause) {
1339                 isctlrjabbering(c, cause);
1340                 iprint("sdiachi: intr cause unserviced: %#lx\n", cause);
1341         }
1342         spin_unlock_irqsave(&c->Lock);
1343 }
1344
1345 /* checkdrive, called from satakproc, will prod the drive while we wait */
1346 static void awaitspinup(struct drive *d)
1347 {
1348         int ms;
1349         uint16_t s;
1350         char *name;
1351
1352         spin_lock_irqsave(&d->Lock);
1353         if (d->unit == NULL || d->port == NULL) {
1354                 panic("awaitspinup: NULL d->unit or d->port");
1355                 spin_unlock_irqsave(&d->Lock);
1356                 return;
1357         }
1358         name = (d->unit ? d->unit->sdperm.name : NULL);
1359         s = d->port->sstatus;
1360         if (!(s & Devpresent)) { /* never going to be ready */
1361                 printd("awaitspinup: %s absent, not waiting\n", name);
1362                 spin_unlock_irqsave(&d->Lock);
1363                 return;
1364         }
1365
1366         for (ms = 20000; ms > 0; ms -= 50)
1367                 switch (d->state) {
1368                 case Dnull:
1369                         /* absent; done */
1370                         spin_unlock_irqsave(&d->Lock);
1371                         printd("awaitspinup: %s in null state\n", name);
1372                         return;
1373                 case Dready:
1374                 case Dnew:
1375                         if (d->sectors || d->mediachange) {
1376                                 /* ready to use; done */
1377                                 spin_unlock_irqsave(&d->Lock);
1378                                 printd("awaitspinup: %s ready!\n", name);
1379                                 return;
1380                         }
1381                 /* fall through */
1382                 default:
1383                 case Dmissing: /* normal waiting states */
1384                 case Dreset:
1385                 case Doffline: /* transitional states */
1386                 case Derror:
1387                 case Dportreset:
1388                         spin_unlock_irqsave(&d->Lock);
1389                         asleep(50);
1390                         spin_lock_irqsave(&d->Lock);
1391                         break;
1392                 }
1393         printd("awaitspinup: %s didn't spin up after 20 seconds\n", name);
1394         spin_unlock_irqsave(&d->Lock);
1395 }
1396
1397 static int iaverify(struct sdunit *u)
1398 {
1399         struct ctlr *c;
1400         struct drive *d;
1401
1402         c = u->dev->ctlr;
1403         d = c->drive[u->subno];
1404         spin_lock_irqsave(&c->Lock);
1405         spin_lock_irqsave(&d->Lock);
1406         d->unit = u;
1407         spin_unlock_irqsave(&d->Lock);
1408         spin_unlock_irqsave(&c->Lock);
1409         checkdrive(d, d->driveno); /* c->d0 + d->driveno */
1410
1411         /*
1412          * hang around until disks are spun up and thus available as
1413          * nvram, dos file systems, etc.  you wouldn't expect it, but
1414          * the intel 330 ssd takes a while to `spin up'.
1415          */
1416         awaitspinup(d);
1417         return 1;
1418 }
1419
1420 static int iaenable(struct sdev *s)
1421 {
1422         char name[32];
1423         struct ctlr *c;
1424         static int once;
1425
1426         c = s->ctlr;
1427         spin_lock_irqsave(&c->Lock);
1428         if (!c->enabled) {
1429                 if (once == 0) {
1430                         once = 1;
1431                         ktask("ahci", satakproc, 0);
1432                 }
1433                 if (c->ndrive == 0)
1434                         panic("iaenable: zero s->ctlr->ndrive");
1435                 pci_set_bus_master(c->pci);
1436                 snprintf(name, sizeof(name), "%s (%s)", s->name, s->ifc->name);
1437                 /*c->vector = intrenable(c->pci->intl, iainterrupt, c, c->pci->tbdf,
1438                  *name);*/
1439                 /* what do we do about the arg? */
1440                 register_irq(c->pci->irqline, iainterrupt, c, pci_to_tbdf(c->pci));
1441                 /* supposed to squelch leftover interrupts here. */
1442                 ahcienable(c->hba);
1443                 c->enabled = 1;
1444         }
1445         spin_unlock_irqsave(&c->Lock);
1446         return 1;
1447 }
1448
1449 static int iadisable(struct sdev *s)
1450 {
1451         char name[32];
1452         struct ctlr *c;
1453
1454         c = s->ctlr;
1455         spin_lock_irqsave(&c->Lock);
1456         ahcidisable(c->hba);
1457         snprintf(name, sizeof(name), "%s (%s)", s->name, s->ifc->name);
1458         // TODO: what to do here?
1459         // intrdisable(c->vector);
1460         c->enabled = 0;
1461         spin_unlock_irqsave(&c->Lock);
1462         return 1;
1463 }
1464
1465 static int iaonline(struct sdunit *unit)
1466 {
1467         int r;
1468         struct ctlr *c;
1469         struct drive *d;
1470
1471         c = unit->dev->ctlr;
1472         d = c->drive[unit->subno];
1473         r = 0;
1474
1475         if ((d->portm.feat & Datapi) && d->mediachange) {
1476                 r = scsionline(unit);
1477                 if (r > 0)
1478                         d->mediachange = 0;
1479                 return r;
1480         }
1481
1482         spin_lock_irqsave(&d->Lock);
1483         if (d->mediachange) {
1484                 r = 2;
1485                 d->mediachange = 0;
1486                 /* devsd resets this after online is called; why? */
1487                 unit->sectors = d->sectors;
1488                 unit->secsize = 512; /* default size */
1489         } else if (d->state == Dready)
1490                 r = 1;
1491         spin_unlock_irqsave(&d->Lock);
1492         return r;
1493 }
1494
1495 /* returns locked list! */
1496 static struct alist *ahcibuild(struct drive *d, unsigned char *cmd, void *data,
1497                                int n, int64_t lba)
1498 {
1499         unsigned char *c, acmd, dir, llba;
1500         struct alist *l;
1501         struct actab *t;
1502         struct aportm *pm;
1503         struct aprdt *p;
1504         static unsigned char tab[2][2] = {
1505             {0xc8, 0x25}, {0xca, 0x35},
1506         };
1507
1508         pm = &d->portm;
1509         dir = *cmd != 0x28;
1510         llba = pm->feat & Dllba ? 1 : 0;
1511         acmd = tab[dir][llba];
1512         qlock(&pm->ql);
1513         l = pm->list;
1514         t = pm->ctab;
1515         c = t->cfis;
1516
1517         c[0] = 0x27;
1518         c[1] = 0x80;
1519         c[2] = acmd;
1520         c[3] = 0;
1521
1522         c[4] = lba;        /* sector            lba low 7:0 */
1523         c[5] = lba >> 8;   /* cylinder low              lba mid 15:8 */
1524         c[6] = lba >> 16;  /* cylinder hi               lba hi  23:16 */
1525         c[7] = Obs | 0x40; /* 0x40 == lba */
1526         if (llba == 0)
1527                 c[7] |= (lba >> 24) & 7;
1528
1529         c[8] = lba >> 24;  /* sector (exp)              lba     31:24 */
1530         c[9] = lba >> 32;  /* cylinder low (exp)        lba     39:32 */
1531         c[10] = lba >> 48; /* cylinder hi (exp) lba     48:40 */
1532         c[11] = 0;         /* features (exp); */
1533
1534         c[12] = n;      /* sector count */
1535         c[13] = n >> 8; /* sector count (exp) */
1536         c[14] = 0;      /* r */
1537         c[15] = 0;      /* control */
1538
1539         *(uint32_t *)(c + 16) = 0;
1540
1541         l->flags = 1 << 16 | Lpref | 0x5; /* Lpref ?? */
1542         if (dir == Write)
1543                 l->flags |= Lwrite;
1544         l->len = 0;
1545         l->ctab = PCIWADDR(t);
1546         l->ctabhi = 0;
1547
1548         p = &t->prdt;
1549         p->dba = PCIWADDR(data);
1550         p->dbahi = 0;
1551         if (d->unit == NULL)
1552                 panic("ahcibuild: NULL d->unit");
1553         p->count = 1 << 31 | (d->unit->secsize * n - 2) | 1;
1554
1555         return l;
1556 }
1557
1558 static struct alist *ahcibuildpkt(struct aportm *pm, struct sdreq *r,
1559                                   void *data, int n)
1560 {
1561         int fill, len;
1562         unsigned char *c;
1563         struct alist *l;
1564         struct actab *t;
1565         struct aprdt *p;
1566
1567         qlock(&pm->ql);
1568         l = pm->list;
1569         t = pm->ctab;
1570         c = t->cfis;
1571
1572         fill = pm->feat & Datapi16 ? 16 : 12;
1573         if ((len = r->clen) > fill)
1574                 len = fill;
1575         memmove(t->atapi, r->cmd, len);
1576         memset(t->atapi + len, 0, fill - len);
1577
1578         c[0] = 0x27;
1579         c[1] = 0x80;
1580         c[2] = 0xa0;
1581         if (n != 0)
1582                 c[3] = 1; /* dma */
1583         else
1584                 c[3] = 0; /* features (exp); */
1585
1586         c[4] = 0;      /* sector                lba low 7:0 */
1587         c[5] = n;      /* cylinder low          lba mid 15:8 */
1588         c[6] = n >> 8; /* cylinder hi           lba hi  23:16 */
1589         c[7] = Obs;
1590
1591         *(uint32_t *)(c + 8) = 0;
1592         *(uint32_t *)(c + 12) = 0;
1593         *(uint32_t *)(c + 16) = 0;
1594
1595         l->flags = 1 << 16 | Lpref | Latapi | 0x5;
1596         if (r->write != 0 && data)
1597                 l->flags |= Lwrite;
1598         l->len = 0;
1599         l->ctab = PCIWADDR(t);
1600         l->ctabhi = 0;
1601
1602         if (data == 0)
1603                 return l;
1604
1605         p = &t->prdt;
1606         p->dba = PCIWADDR(data);
1607         p->dbahi = 0;
1608         p->count = 1 << 31 | (n - 2) | 1;
1609
1610         return l;
1611 }
1612
1613 static int waitready(struct drive *d)
1614 {
1615         uint32_t s, i, delta;
1616
1617         for (i = 0; i < 15000; i += 250) {
1618                 if (d->state == Dreset || d->state == Dportreset || d->state == Dnew)
1619                         return 1;
1620                 delta = ms() - d->lastseen;
1621                 if (d->state == Dnull || delta > 10 * 1000)
1622                         return -1;
1623                 spin_lock_irqsave(&d->Lock);
1624                 s = d->port->sstatus;
1625                 spin_unlock_irqsave(&d->Lock);
1626                 if ((s & Intpm) == 0 && delta > 1500)
1627                         return -1; /* no detect */
1628                 if (d->state == Dready && (s & Devdet) == (Devphycomm | Devpresent))
1629                         return 0; /* ready, present & phy. comm. */
1630                 esleep(250);
1631         }
1632         printd("%s: not responding; offline\n", d->unit->sdperm.name);
1633         setstate(d, Doffline);
1634         return -1;
1635 }
1636
1637 static int lockready(struct drive *d)
1638 {
1639         int i;
1640
1641         qlock(&d->portm.ql);
1642         while ((i = waitready(d)) == 1) { /* could wait forever? */
1643                 qunlock(&d->portm.ql);
1644                 esleep(1);
1645                 qlock(&d->portm.ql);
1646         }
1647         return i;
1648 }
1649
1650 static int flushcache(struct drive *d)
1651 {
1652         int i;
1653
1654         i = -1;
1655         if (lockready(d) == 0)
1656                 i = ahciflushcache(&d->portc);
1657         qunlock(&d->portm.ql);
1658         return i;
1659 }
1660
1661 static int iariopkt(struct sdreq *r, struct drive *d)
1662 {
1663         ERRSTACK(2);
1664         int n, count, try, max, flag, task, wormwrite;
1665         char *name;
1666         unsigned char *cmd, *data;
1667         struct aport *p;
1668         struct Asleep as;
1669
1670         cmd = r->cmd;
1671         name = d->unit->sdperm.name;
1672         p = d->port;
1673
1674         aprintd("ahci: iariopkt: %04#x %04#x %c %d %p\n", cmd[0], cmd[2],
1675                 "rw"[r->write], r->dlen, r->data);
1676         if (cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
1677                 return sdmodesense(r, cmd, d->info, d->infosz);
1678         r->rlen = 0;
1679         count = r->dlen;
1680         max = 65536;
1681
1682         try = 0;
1683 retry:
1684         data = r->data;
1685         n = count;
1686         if (n > max)
1687                 n = max;
1688         ahcibuildpkt(&d->portm, r, data, n);
1689         switch (waitready(d)) {
1690         case -1:
1691                 qunlock(&d->portm.ql);
1692                 return SDeio;
1693         case 1:
1694                 qunlock(&d->portm.ql);
1695                 esleep(1);
1696                 goto retry;
1697         }
1698         /* d->portm qlock held here */
1699
1700         spin_lock_irqsave(&d->Lock);
1701         d->portm.flag = 0;
1702         spin_unlock_irqsave(&d->Lock);
1703         p->ci = 1;
1704
1705         as.p = p;
1706         as.i = 1;
1707         d->intick = ms();
1708         d->active++;
1709
1710         while (waserror())
1711                 ;
1712         /* don't sleep here forever */
1713         rendez_sleep_timeout(&d->portm.Rendez, ahciclear, &as, (3 * 1000) * 1000);
1714         poperror();
1715         if (!ahciclear(&as)) {
1716                 qunlock(&d->portm.ql);
1717                 printd("%s: ahciclear not true after 3 seconds\n", name);
1718                 r->status = SDcheck;
1719                 return SDcheck;
1720         }
1721
1722         d->active--;
1723         spin_lock_irqsave(&d->Lock);
1724         flag = d->portm.flag;
1725         task = d->port->task;
1726         spin_unlock_irqsave(&d->Lock);
1727
1728         if ((task & (Efatal << 8)) ||
1729             ((task & (ASbsy | ASdrq)) && (d->state == Dready))) {
1730                 d->port->ci = 0;
1731                 ahcirecover(&d->portc);
1732                 task = d->port->task;
1733                 flag &= ~Fdone; /* either an error or do-over */
1734         }
1735         qunlock(&d->portm.ql);
1736         if (flag == 0) {
1737                 if (++try == 10) {
1738                         printd("%s: bad disk\n", name);
1739                         r->status = SDcheck;
1740                         return SDcheck;
1741                 }
1742                 /*
1743                  * write retries cannot succeed on write-once media,
1744                  * so just accept any failure.
1745                  */
1746                 wormwrite = 0;
1747                 switch (d->unit->inquiry[0] & SDinq0periphtype) {
1748                 case SDperworm:
1749                 case SDpercd:
1750                         switch (cmd[0]) {
1751                         case 0x0a: /* write (6?) */
1752                         case 0x2a: /* write (10) */
1753                         case 0x8a: /* int32_t write (16) */
1754                         case 0x2e: /* write and verify (10) */
1755                                 wormwrite = 1;
1756                                 break;
1757                         }
1758                         break;
1759                 }
1760                 if (!wormwrite) {
1761                         printd("%s: retry\n", name);
1762                         goto retry;
1763                 }
1764         }
1765         if (flag & Ferror) {
1766                 if ((task & Eidnf) == 0)
1767                         printd("%s: i/o error task=%#x\n", name, task);
1768                 r->status = SDcheck;
1769                 return SDcheck;
1770         }
1771
1772         data += n;
1773
1774         r->rlen = data - (unsigned char *)r->data;
1775         r->status = SDok;
1776         return SDok;
1777 }
1778
1779 static int iario(struct sdreq *r)
1780 {
1781         ERRSTACK(2);
1782         int i, n, count, try, max, flag, task;
1783         int64_t lba;
1784         char *name;
1785         unsigned char *cmd, *data;
1786         struct aport *p;
1787         struct Asleep as;
1788         struct ctlr *c;
1789         struct drive *d;
1790         struct sdunit *unit;
1791
1792         unit = r->unit;
1793         c = unit->dev->ctlr;
1794         d = c->drive[unit->subno];
1795         if (d->portm.feat & Datapi)
1796                 return iariopkt(r, d);
1797         cmd = r->cmd;
1798         name = d->unit->sdperm.name;
1799         p = d->port;
1800
1801         if (r->cmd[0] == 0x35 || r->cmd[0] == 0x91) {
1802                 if (flushcache(d) == 0)
1803                         return sdsetsense(r, SDok, 0, 0, 0);
1804                 return sdsetsense(r, SDcheck, 3, 0xc, 2);
1805         }
1806
1807         if ((i = sdfakescsi(r, d->info, d->infosz)) != SDnostatus) {
1808                 r->status = i;
1809                 return i;
1810         }
1811
1812         if (*cmd != 0x28 && *cmd != 0x2a) {
1813                 printd("%s: bad cmd %.2#x\n", name, cmd[0]);
1814                 r->status = SDcheck;
1815                 return SDcheck;
1816         }
1817
1818         lba = cmd[2] << 24 | cmd[3] << 16 | cmd[4] << 8 | cmd[5];
1819         count = cmd[7] << 8 | cmd[8];
1820         if (r->data == NULL)
1821                 return SDok;
1822         if (r->dlen < count * unit->secsize)
1823                 count = r->dlen / unit->secsize;
1824         max = 128;
1825
1826         try = 0;
1827 retry:
1828         data = r->data;
1829         while (count > 0) {
1830                 n = count;
1831                 if (n > max)
1832                         n = max;
1833                 ahcibuild(d, cmd, data, n, lba);
1834                 switch (waitready(d)) {
1835                 case -1:
1836                         qunlock(&d->portm.ql);
1837                         return SDeio;
1838                 case 1:
1839                         qunlock(&d->portm.ql);
1840                         esleep(1);
1841                         goto retry;
1842                 }
1843                 /* d->portm qlock held here */
1844                 spin_lock_irqsave(&d->Lock);
1845                 d->portm.flag = 0;
1846                 spin_unlock_irqsave(&d->Lock);
1847                 p->ci = 1;
1848
1849                 as.p = p;
1850                 as.i = 1;
1851                 d->intick = ms();
1852                 d->active++;
1853
1854                 while (waserror())
1855                         ;
1856                 /* don't sleep here forever */
1857                 rendez_sleep_timeout(&d->portm.Rendez, ahciclear, &as,
1858                                      (3 * 1000) * 1000);
1859                 poperror();
1860                 if (!ahciclear(&as)) {
1861                         qunlock(&d->portm.ql);
1862                         printd("%s: ahciclear not true after 3 seconds\n", name);
1863                         r->status = SDcheck;
1864                         return SDcheck;
1865                 }
1866
1867                 d->active--;
1868                 spin_lock_irqsave(&d->Lock);
1869                 flag = d->portm.flag;
1870                 task = d->port->task;
1871                 spin_unlock_irqsave(&d->Lock);
1872
1873                 if ((task & (Efatal << 8)) ||
1874                     ((task & (ASbsy | ASdrq)) && d->state == Dready)) {
1875                         d->port->ci = 0;
1876                         ahcirecover(&d->portc);
1877                         task = d->port->task;
1878                 }
1879                 qunlock(&d->portm.ql);
1880                 if (flag == 0) {
1881                         if (++try == 10) {
1882                                 printd("%s: bad disk\n", name);
1883                                 r->status = SDeio;
1884                                 return SDeio;
1885                         }
1886                         printd("%s: retry blk %lld\n", name, lba);
1887                         goto retry;
1888                 }
1889                 if (flag & Ferror) {
1890                         printk("%s: i/o error task=%#x @%,lld\n", name, task, lba);
1891                         r->status = SDeio;
1892                         return SDeio;
1893                 }
1894
1895                 count -= n;
1896                 lba += n;
1897                 data += n * unit->secsize;
1898         }
1899         r->rlen = data - (unsigned char *)r->data;
1900         r->status = SDok;
1901         return SDok;
1902 }
1903
1904 /*
1905  * configure drives 0-5 as ahci sata (c.f. errata).
1906  * what about 6 & 7, as claimed by marvell 0x9123?
1907  */
1908 static int iaahcimode(struct pci_device *p)
1909 {
1910         printd("iaahcimode: %#x %#x %#x\n", pcidev_read8(p, 0x91),
1911                pcidev_read8(p, 92), pcidev_read8(p, 93));
1912         pcidev_write16(p, 0x92, pcidev_read16(p, 0x92) | 0x3f); /* ports 0-5 */
1913         return 0;
1914 }
1915
1916 static void iasetupahci(struct ctlr *c)
1917 {
1918         uint32_t *p = (void *)c->mmio;
1919         /* disable cmd block decoding. */
1920         pcidev_write16(c->pci, 0x40, pcidev_read16(c->pci, 0x40) & ~(1 << 15));
1921         pcidev_write16(c->pci, 0x42, pcidev_read16(c->pci, 0x42) & ~(1 << 15));
1922
1923         p[0x4 / 4] |= 1 << 31;     /* enable ahci mode (ghc register) */
1924         p[0xc / 4] = (1 << 6) - 1; /* 5 ports. (supposedly ro pi reg.) */
1925
1926         /* enable ahci mode and 6 ports; from ich9 datasheet */
1927         pcidev_write16(c->pci, 0x90, 1 << 6 | 1 << 5);
1928 }
1929
1930 static int didtype(struct pci_device *p)
1931 {
1932         switch (p->ven_id) {
1933         case Vintel:
1934                 if ((p->dev_id & 0xfffc) == 0x2680)
1935                         return Tesb;
1936                 /*
1937                  * 0x27c4 is the intel 82801 in compatibility (not sata) mode.
1938                  */
1939                 if (p->dev_id == 0x1e02 ||            /* c210 */
1940                     p->dev_id == 0x24d1 ||            /* 82801eb/er */
1941                     (p->dev_id & 0xfffb) == 0x27c1 || /* 82801g[bh]m ich7 */
1942                     p->dev_id == 0x2821 ||            /* 82801h[roh] */
1943                     (p->dev_id & 0xfffe) == 0x2824 || /* 82801h[b] */
1944                     (p->dev_id & 0xfeff) == 0x2829 || /* ich8/9m */
1945                     (p->dev_id & 0xfffe) == 0x2922 || /* ich9 */
1946                     p->dev_id == 0x3a02 ||            /* 82801jd/do */
1947                     (p->dev_id & 0xfefe) == 0x3a22 || /* ich10, pch */
1948                     (p->dev_id & 0xfff8) == 0x3b28)   /* pchm */
1949                         return Tich;
1950                 break;
1951         case Vatiamd:
1952                 if (p->dev_id == 0x4380 || p->dev_id == 0x4390 || p->dev_id == 0x4391) {
1953                         printd("detected sb600 vid %#x did %#x\n", p->ven_id, p->dev_id);
1954                         return Tsb600;
1955                 }
1956                 break;
1957         case Vmarvell:
1958                 if (p->dev_id == 0x9123)
1959                         printk("ahci: marvell sata 3 controller has delusions of something on unit 7\n");
1960                 break;
1961         }
1962         if (p->class == Pcibcstore && p->subclass == Pciscsata && p->progif == 1) {
1963                 printd("ahci: Tunk: vid %#4.4x did %#4.4x\n", p->ven_id, p->dev_id);
1964                 return Tunk;
1965         }
1966         return -1;
1967 }
1968
1969 static int newctlr(struct ctlr *ctlr, struct sdev *sdev, int nunit)
1970 {
1971         int i, n;
1972         struct drive *drive;
1973
1974         ctlr->ndrive = sdev->nunit = nunit;
1975         ctlr->mport = ctlr->hba->cap & ((1 << 5) - 1);
1976
1977         i = (ctlr->hba->cap >> 20) & ((1 << 4) - 1); /* iss */
1978         printk("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", sdev->idno, Tname(ctlr),
1979                ctlr->physio, descmode[i], nunit, ctlr->pci->irqline);
1980         /* map the drives -- they don't all need to be enabled. */
1981         n = 0;
1982         ctlr->rawdrive = kzmalloc(NCtlrdrv * sizeof(struct drive), 0);
1983         if (ctlr->rawdrive == NULL) {
1984                 printd("ahci: out of memory\n");
1985                 return -1;
1986         }
1987         for (i = 0; i < NCtlrdrv; i++) {
1988                 drive = ctlr->rawdrive + i;
1989                 spinlock_init(&drive->Lock);
1990                 drive->portno = i;
1991                 drive->driveno = -1;
1992                 drive->sectors = 0;
1993                 drive->serial[0] = ' ';
1994                 drive->ctlr = ctlr;
1995                 if ((ctlr->hba->pi & (1 << i)) == 0)
1996                         continue;
1997                 drive->port = (struct aport *)(ctlr->mmio + 0x80 * i + 0x100);
1998                 drive->portc.p = drive->port;
1999                 drive->portc.pm = &drive->portm;
2000                 qlock_init(&drive->portm.ql);
2001                 rendez_init(&drive->portm.Rendez);
2002                 drive->driveno = n++;
2003                 ctlr->drive[drive->driveno] = drive;
2004                 iadrive[niadrive + drive->driveno] = drive;
2005         }
2006         for (i = 0; i < n; i++)
2007                 if (ahciidle(ctlr->drive[i]->port) == -1) {
2008                         printd("ahci: %s: port %d wedged; abort\n", Tname(ctlr), i);
2009                         return -1;
2010                 }
2011         for (i = 0; i < n; i++) {
2012                 ctlr->drive[i]->mode = DMsatai;
2013                 configdrive(ctlr->drive[i]);
2014         }
2015         return n;
2016 }
2017
2018 static void releasedrive(struct kref *kref)
2019 {
2020         printk("release drive called, but we don't do that yet\n");
2021 }
2022
2023 static struct sdev *iapnp(void)
2024 {
2025         int n, nunit, type;
2026         struct ctlr *c;
2027         struct pci_device *p;
2028         struct sdev *head, *tail, *s;
2029
2030         // TODO: ensure we're only called once.
2031
2032         memset(olds, 0xff, sizeof olds);
2033         p = NULL;
2034         head = tail = NULL;
2035         STAILQ_FOREACH(p, &pci_devices, all_dev) {
2036                 type = didtype(p);
2037                 printd("didtype: %d\n", type);
2038                 if (type == -1)
2039                         continue;
2040                 if (p->bar[Abar].mmio_base32 == 0)
2041                         continue;
2042                 if (niactlr == NCtlr) {
2043                         printk("ahci: iapnp: %s: too many controllers\n", tname[type]);
2044                         break;
2045                 }
2046                 c = iactlr + niactlr;
2047                 s = sdevs + niactlr;
2048                 memset(c, 0, sizeof *c);
2049                 memset(s, 0, sizeof *s);
2050                 kref_init(&s->r, releasedrive, 1);
2051                 qlock_init(&s->ql);
2052                 qlock_init(&s->unitlock);
2053                 c->physio = p->bar[Abar].mmio_base32 & ~0xf;
2054                 c->mmio = vmap_pmem_nocache(c->physio, p->bar[Abar].mmio_sz);
2055                 if (c->mmio == 0) {
2056                         printk("ahci: %s: address %#lX in use did=%#x\n", Tname(c),
2057                                c->physio, p->dev_id);
2058                         continue;
2059                 }
2060                 printk("sdiahci %s: Mapped %p/%d to %p\n", tname[type], c->physio,
2061                        p->bar[Abar].mmio_sz, c->mmio);
2062                 c->pci = p;
2063                 c->type = type;
2064
2065                 s->ifc = &sdiahciifc;
2066                 s->idno = 'E' + niactlr;
2067                 s->ctlr = c;
2068                 c->sdev = s;
2069
2070                 if (Intel(c) && p->dev_id != 0x2681)
2071                         iasetupahci(c);
2072                 nunit = ahciconf(c);
2073                 //              ahcihbareset((Ahba*)c->mmio);
2074                 if (Intel(c) && iaahcimode(p) == -1)
2075                         break;
2076                 if (nunit < 1) {
2077                         vunmap_vmem(c->mmio, p->bar[Abar].mmio_sz);
2078                         continue;
2079                 }
2080                 n = newctlr(c, s, nunit);
2081                 if (n < 0)
2082                         continue;
2083                 niadrive += n;
2084                 niactlr++;
2085                 if (head)
2086                         tail->next = s;
2087                 else
2088                         head = s;
2089                 tail = s;
2090         }
2091         return head;
2092 }
2093
2094 static char *smarttab[] = {"unset", "error", "threshold exceeded", "normal"};
2095
2096 static char *pflag(char *s, char *e, unsigned char f)
2097 {
2098         unsigned char i;
2099
2100         for (i = 0; i < 8; i++)
2101                 if (f & (1 << i))
2102                         s = seprintf(s, e, "%s ", flagname[i]);
2103         return seprintf(s, e, "\n");
2104 }
2105
2106 static int iarctl(struct sdunit *u, char *p, int l)
2107 {
2108         char buf[32];
2109         char *e, *op;
2110         struct aport *o;
2111         struct ctlr *c;
2112         struct drive *d;
2113
2114         c = u->dev->ctlr;
2115         if (c == NULL) {
2116                 printk("iarctl: nil u->dev->ctlr\n");
2117                 return 0;
2118         }
2119         d = c->drive[u->subno];
2120         o = d->port;
2121
2122         e = p + l;
2123         op = p;
2124         if (d->state == Dready) {
2125                 p = seprintf(p, e, "model\t%s\n", d->model);
2126                 p = seprintf(p, e, "serial\t%s\n", d->serial);
2127                 p = seprintf(p, e, "firm\t%s\n", d->firmware);
2128                 if (d->smartrs == 0xff)
2129                         p = seprintf(p, e, "smart\tenable error\n");
2130                 else if (d->smartrs == 0)
2131                         p = seprintf(p, e, "smart\tdisabled\n");
2132                 else
2133                         p = seprintf(p, e, "smart\t%s\n", smarttab[d->portm.smart]);
2134                 p = seprintf(p, e, "flag\t");
2135                 p = pflag(p, e, d->portm.feat);
2136         } else
2137                 p = seprintf(p, e, "no disk present [%s]\n", diskstates[d->state]);
2138         serrstr(o->serror, buf, buf + sizeof buf - 1);
2139         p = seprintf(p, e,
2140                          "reg\ttask %#lx cmd %#lx serr %#lx %s ci %#lx is %#lx; sig %#lx sstatus %06#lx\n",
2141                      o->task, o->cmd, o->serror, buf, o->ci, o->isr, o->sig,
2142                      o->sstatus);
2143         if (d->unit == NULL)
2144                 panic("iarctl: nil d->unit");
2145         p = seprintf(p, e, "geometry %llu %lu\n", d->sectors, d->unit->secsize);
2146         return p - op;
2147 }
2148
2149 static void runflushcache(struct drive *d)
2150 {
2151         int32_t t0;
2152
2153         t0 = ms();
2154         if (flushcache(d) != 0)
2155                 error(EIO, "Flush cache failed");
2156         printd("ahci: flush in %ld ms\n", ms() - t0);
2157 }
2158
2159 static void forcemode(struct drive *d, char *mode)
2160 {
2161         int i;
2162
2163         for (i = 0; i < ARRAY_SIZE(modename); i++)
2164                 if (strcmp(mode, modename[i]) == 0)
2165                         break;
2166         if (i == ARRAY_SIZE(modename))
2167                 i = 0;
2168         spin_lock_irqsave(&d->Lock);
2169         d->mode = i;
2170         spin_unlock_irqsave(&d->Lock);
2171 }
2172
2173 static void runsmartable(struct drive *d, int i)
2174 {
2175         ERRSTACK(2);
2176         if (waserror()) {
2177                 qunlock(&d->portm.ql);
2178                 d->smartrs = 0;
2179                 nexterror();
2180         }
2181         if (lockready(d) == -1)
2182                 error(EIO, "runsmartable: lockready returned -1");
2183         d->smartrs = smart(&d->portc, i);
2184         d->portm.smart = 0;
2185         qunlock(&d->portm.ql);
2186         poperror();
2187 }
2188
2189 static void forcestate(struct drive *d, char *state)
2190 {
2191         int i;
2192
2193         for (i = 0; i < ARRAY_SIZE(diskstates); i++)
2194                 if (strcmp(state, diskstates[i]) == 0)
2195                         break;
2196         if (i == ARRAY_SIZE(diskstates))
2197                 error(EINVAL, "Can't set state to invalid value '%s'", state);
2198         setstate(d, i);
2199 }
2200
2201 /*
2202  * force this driver to notice a change of medium if the hardware doesn't
2203  * report it.
2204  */
2205 static void changemedia(struct sdunit *u)
2206 {
2207         struct ctlr *c;
2208         struct drive *d;
2209
2210         c = u->dev->ctlr;
2211         d = c->drive[u->subno];
2212         spin_lock_irqsave(&d->Lock);
2213         d->mediachange = 1;
2214         u->sectors = 0;
2215         spin_unlock_irqsave(&d->Lock);
2216 }
2217
2218 static int iawctl(struct sdunit *u, struct cmdbuf *cmd)
2219 {
2220         ERRSTACK(2);
2221         char **f;
2222         struct ctlr *c;
2223         struct drive *d;
2224         unsigned int i;
2225
2226         c = u->dev->ctlr;
2227         d = c->drive[u->subno];
2228         f = cmd->f;
2229
2230         if (strcmp(f[0], "change") == 0)
2231                 changemedia(u);
2232         else if (strcmp(f[0], "flushcache") == 0)
2233                 runflushcache(d);
2234         else if (strcmp(f[0], "identify") == 0) {
2235                 i = strtoul(f[1] ? f[1] : "0", 0, 0);
2236                 if (i > 0xff)
2237                         i = 0;
2238                 printd("ahci: %04d %#x\n", i, d->info[i]);
2239         } else if (strcmp(f[0], "mode") == 0)
2240                 forcemode(d, f[1] ? f[1] : "satai");
2241         else if (strcmp(f[0], "nop") == 0) {
2242                 if ((d->portm.feat & Dnop) == 0) {
2243                         sdierror(cmd, "no drive support");
2244                         return -1;
2245                 }
2246                 if (waserror()) {
2247                         qunlock(&d->portm.ql);
2248                         nexterror();
2249                 }
2250                 if (lockready(d) == -1)
2251                         error(EIO, "%s: lockready returned -1", __func__);
2252                 nop(&d->portc);
2253                 qunlock(&d->portm.ql);
2254                 poperror();
2255         } else if (strcmp(f[0], "reset") == 0)
2256                 forcestate(d, "reset");
2257         else if (strcmp(f[0], "smart") == 0) {
2258                 if (d->smartrs == 0)
2259                         sdierror(cmd, "smart not enabled");
2260                 if (waserror()) {
2261                         qunlock(&d->portm.ql);
2262                         d->smartrs = 0;
2263                         nexterror();
2264                 }
2265                 if (lockready(d) == -1)
2266                         error(EIO, "%s: lockready returned -1", __func__);
2267                 d->portm.smart = 2 + smartrs(&d->portc);
2268                 qunlock(&d->portm.ql);
2269                 poperror();
2270         } else if (strcmp(f[0], "smartdisable") == 0)
2271                 runsmartable(d, 1);
2272         else if (strcmp(f[0], "smartenable") == 0)
2273                 runsmartable(d, 0);
2274         else if (strcmp(f[0], "state") == 0)
2275                 forcestate(d, f[1] ? f[1] : "null");
2276         else {
2277                 sdierror(cmd, "%s: unknown control '%s'", __func__, f[0]);
2278                 return -1;
2279         }
2280         return 0;
2281 }
2282
2283 static char *portr(char *p, char *e, unsigned int x)
2284 {
2285         int i, a;
2286
2287         p[0] = 0;
2288         a = -1;
2289         for (i = 0; i < 32; i++) {
2290                 if ((x & (1 << i)) == 0) {
2291                         if (a != -1 && i - 1 != a)
2292                                 p = seprintf(p, e, "-%d", i - 1);
2293                         a = -1;
2294                         continue;
2295                 }
2296                 if (a == -1) {
2297                         if (i > 0)
2298                                 p = seprintf(p, e, ", ");
2299                         p = seprintf(p, e, "%d", a = i);
2300                 }
2301         }
2302         if (a != -1 && i - 1 != a)
2303                 p = seprintf(p, e, "-%d", i - 1);
2304         return p;
2305 }
2306
2307 /* must emit exactly one line per controller (sd(3)) */
2308 static char *iartopctl(struct sdev *sdev, char *p, char *e)
2309 {
2310         uint32_t cap;
2311         char pr[25];
2312         Ahba *hba;
2313         struct ctlr *ctlr;
2314
2315 #define has(x, str)                                                            \
2316         do {                                                                       \
2317                 if (cap & (x))                                                         \
2318                         p = seprintf(p, e, "%s ", (str));                                  \
2319         } while (0)
2320
2321         ctlr = sdev->ctlr;
2322         hba = ctlr->hba;
2323         p = seprintf(p, e, "sd%c ahci port %#p: ", sdev->idno, ctlr->physio);
2324         cap = hba->cap;
2325         has(Hs64a, "64a");
2326         has(Hsalp, "alp");
2327         has(Hsam, "am");
2328         has(Hsclo, "clo");
2329         has(Hcccs, "coal");
2330         has(Hems, "ems");
2331         has(Hsal, "led");
2332         has(Hsmps, "mps");
2333         has(Hsncq, "ncq");
2334         has(Hssntf, "ntf");
2335         has(Hspm, "pm");
2336         has(Hpsc, "pslum");
2337         has(Hssc, "slum");
2338         has(Hsss, "ss");
2339         has(Hsxs, "sxs");
2340         portr(pr, pr + sizeof pr, hba->pi);
2341         return seprintf(
2342             p, e, "iss %ld ncs %ld np %ld; ghc %#lx isr %#lx pi %#lx %s ver %#lx\n",
2343             (cap >> 20) & 0xf, (cap >> 8) & 0x1f, 1 + (cap & 0x1f), hba->ghc,
2344             hba->isr, hba->pi, pr, hba->ver);
2345 #undef has
2346 }
2347
2348 static int iawtopctl(struct sdev *sdev, struct cmdbuf *cmd)
2349 {
2350         int *v;
2351         char **f;
2352
2353         f = cmd->f;
2354         v = 0;
2355
2356         if (f[0] == NULL)
2357                 return 0;
2358         if (strcmp(f[0], "debug") == 0)
2359                 v = &debug;
2360         else if (strcmp(f[0], "iprintd") == 0)
2361                 v = &prid;
2362         else if (strcmp(f[0], "aprint") == 0)
2363                 v = &datapi;
2364         else
2365                 sdierror(cmd, "%s: bad control '%s'", __func__, f[0]);
2366
2367         switch (cmd->nf) {
2368         default:
2369                 sdierror(cmd, "%s: %d args, only 1 or 2 allowed", __func__, cmd->nf);
2370         case 1:
2371                 *v ^= 1;
2372                 break;
2373         case 2:
2374                 if (f[1])
2375                         *v = strcmp(f[1], "on") == 0;
2376                 else
2377                         *v ^= 1;
2378                 break;
2379         }
2380         return 0;
2381 }
2382
2383 struct sdifc sdiahciifc = {
2384     "iahci",
2385
2386     iapnp,
2387     NULL,               /* legacy */
2388     iaenable,
2389     iadisable,
2390
2391     iaverify,
2392     iaonline,
2393     iario,
2394     iarctl,
2395     iawctl,
2396
2397     scsibio,
2398     NULL,               /* probe */
2399     NULL,               /* clear */
2400     iartopctl,
2401     iawtopctl,
2402 };