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