]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/sdmv50xx.c
merge
[plan9front.git] / sys / src / 9 / pc / sdmv50xx.c
1 /*
2  * Marvell 88SX[56]0[48][01] Serial ATA (SATA) driver
3  *
4  * See MV-S101357-00 Rev B Marvell PCI/PCI-X to 8-Port/4-Port
5  * SATA Host Controller, ATA-5 ANSI NCITS 340-2000.
6  *
7  * This is a heavily-modified version (by Coraid) of a heavily-modified
8  * version (from The Labs) of a driver written by Coraid, Inc.
9  * The original copyright notice appears at the end of this file.
10  */
11
12 #include "u.h"
13 #include "../port/lib.h"
14 #include "mem.h"
15 #include "dat.h"
16 #include "fns.h"
17 #include "io.h"
18 #include "../port/error.h"
19 #include        "../port/sd.h"
20 #include <fis.h>
21
22 #define dprint(...)     // print(__VA_ARGS__)
23 #define idprint(...)    print(__VA_ARGS__)
24 #define Ticks           MACHP(0)->ticks
25
26 enum {
27         NCtlr           = 4,
28         NCtlrdrv                = 8,
29         NDrive          = NCtlr*NCtlrdrv,
30
31         SrbRing = 32,
32
33         /* Addresses of ATA register */
34         ARcmd           = 027,
35         ARdev           = 026,
36         ARerr           = 021,
37         ARfea           = 021,
38         ARlba2          = 025,
39         ARlba1          = 024,
40         ARlba0          = 023,
41         ARseccnt        = 022,
42         ARstat          = 027,
43
44         ATAerr          = 1<<0,
45         ATAdrq          = 1<<3,
46         ATAdf           = 1<<5,
47         ATAdrdy         = 1<<6,
48         ATAbusy         = 1<<7,
49         ATAabort        = 1<<2,
50         ATAobs          = 1<<1 | 1<<2 | 1<<4,
51         ATAeIEN = 1<<1,
52         ATAbad          = ATAbusy|ATAdf|ATAdrq|ATAerr,
53
54         SFdone          = 1<<0,
55         SFerror                 = 1<<1,
56
57         PRDeot          = 1<<15,
58
59         /* EDMA interrupt error cause register */
60         ePrtDataErr     = 1<<0,
61         ePrtPRDErr      = 1<<1,
62         eDevErr         = 1<<2,
63         eDevDis         = 1<<3,
64         eDevCon = 1<<4,
65         eOverrun        = 1<<5,
66         eUnderrun       = 1<<6,
67         eSelfDis                = 1<<8,
68         ePrtCRQBErr     = 1<<9,
69         ePrtCRPBErr     = 1<<10,
70         ePrtIntErr      = 1<<11,
71         eIORdyErr       = 1<<12,
72
73         /* flags for sata 2 version */
74         eSelfDis2       = 1<<7,
75         SerrInt         = 1<<5,
76
77         /* EDMA Command Register */
78         eEnEDMA = 1<<0,
79         eDsEDMA         = 1<<1,
80         eAtaRst                 = 1<<2,
81
82         /* Interrupt mask for errors we care about */
83         IEM             = eDevDis | eDevCon | eSelfDis,
84         IEM2            = eDevDis | eDevCon | eSelfDis2,
85
86         /* phyerrata magic */
87         Mpreamp = 0x7e0,
88         Dpreamp = 0x720,
89
90         REV60X1B2       = 0x7,
91         REV60X1C0       = 0x9,
92
93         /* general mmio registers */
94         Portswtch       = 0x1d64/4,
95
96         /* drive states */
97         Dnull           = 0,
98         Dnew,
99         Dready,
100         Derror,
101         Dmissing,
102         Dreset,
103         Dlast,
104
105         /* sata mode */
106         DMautoneg       = 0,
107         DMsatai,
108         DMsataii,
109 };
110
111 typedef struct Arb Arb;
112 typedef struct Bridge Bridge;
113 typedef struct Chip Chip;
114 typedef struct Ctlr Ctlr;
115 typedef struct Drive Drive;
116 typedef struct Edma Edma;
117 typedef struct Prd Prd;
118 typedef struct Rx Rx;
119 typedef struct Srb Srb;
120 typedef struct Tx Tx;
121
122 /*
123  * there are 4 drives per chip.  thus an 8-port
124  * card has two chips.
125  */
126 struct Chip
127 {
128         Arb     *arb;
129         Edma    *edma;
130 };
131
132 struct Drive
133 {
134         Lock;
135
136         Ctlr    *ctlr;
137         SDunit  *unit;
138         char    name[10];
139         Sfis;
140
141         Bridge  *bridge;
142         Edma    *edma;
143         Chip    *chip;
144         int     chipx;
145
146         int     drivechange;
147         int     state;
148         uvlong  sectors;
149         uint    secsize;
150         ulong   pm2;            /* phymode 2 init state */
151         ulong   intick;         /* check for hung drives. */
152         int     wait;
153         int     mode;           /* DMautoneg, satai or sataii. */
154
155         char    serial[20+1];
156         char    firmware[8+1];
157         char    model[40+1];
158         uvlong  wwn;
159
160         ushort  info[256];
161
162         Srb     *srb[SrbRing-1];
163         int     nsrb;
164         Prd     *prd;
165         Tx      *tx;
166         Rx      *rx;
167
168         Srb     *srbhead;
169         Srb     *srbtail;
170         int     driveno;                /* ctlr*NCtlrdrv + unit */
171 };
172
173 struct Ctlr
174 {
175         Lock;
176
177         int     irq;
178         int     tbdf;
179         int     rid;
180         ulong   magic;
181         int     enabled;
182         int     type;
183         SDev    *sdev;
184         Pcidev  *pcidev;
185
186         uchar   *mmio;
187         ulong   *lmmio;
188         Chip    chip[2];
189         int     nchip;
190         Drive   drive[NCtlrdrv];
191         int     ndrive;
192 };
193
194 struct Srb                      /* request buffer */
195 {
196         Lock;
197         Rendez;
198         Srb     *next;
199
200         Drive   *drive;
201         uvlong  blockno;
202         int     count;
203         int     req;
204         int     flag;
205         uchar   *data;
206
207         uchar   cmd;
208         uchar   lba[6];
209         uchar   sectors;
210         int     sta;
211         int     err;
212 };
213
214 /*
215  * Memory-mapped I/O registers in many forms.
216  */
217 struct Bridge                   /* memory-mapped per-drive registers */
218 {
219         ulong   status;
220         ulong   serror;
221         ulong   sctrl;
222         ulong   phyctrl;
223         ulong   phymode3;
224         ulong   phymode4;
225         uchar   fill0[0x14];
226         ulong   phymode1;
227         ulong   phymode2;
228         char    fill1[8];
229         ulong   ctrl;
230         char    fill2[0x34];
231         ulong   phymode;
232         char    fill3[0x88];
233 };                              /* must be 0x100 hex in length */
234
235 struct Arb                      /* memory-mapped per-chip registers */
236 {
237         ulong   config;         /* satahc configuration register (sata2 only) */
238         ulong   rqop;           /* request queue out-pointer */
239         ulong   rqip;           /* response queue in pointer */
240         ulong   ict;            /* inerrupt caolescing threshold */
241         ulong   itt;            /* interrupt timer threshold */
242         ulong   ic;             /* interrupt cause */
243         ulong   btc;            /* bridges test control */
244         ulong   bts;            /* bridges test status */
245         ulong   bpc;            /* bridges pin configuration */
246         char    fill1[0xdc];
247         Bridge  bridge[4];
248 };
249
250 struct Edma                     /* memory-mapped per-drive DMA-related registers */
251 {
252         ulong   config;         /* configuration register */
253         ulong   timer;
254         ulong   iec;            /* interrupt error cause */
255         ulong   iem;            /* interrupt error mask */
256
257         ulong   txbasehi;               /* request queue base address high */
258         ulong   txi;            /* request queue in pointer */
259         ulong   txo;            /* request queue out pointer */
260
261         ulong   rxbasehi;               /* response queue base address high */
262         ulong   rxi;            /* response queue in pointer */
263         ulong   rxo;            /* response queue out pointer */
264
265         ulong   ctl;            /* command register */
266         ulong   testctl;                /* test control */
267         ulong   status;
268         ulong   iordyto;                /* IORDY timeout */
269         char    fill[0x18];
270         ulong   sataconfig;     /* sata 2 */
271         char    fill[0xac];
272         ushort  pio;            /* data register */
273         char    pad0[2];
274         uchar   err;            /* features and error */
275         char    pad1[3];
276         uchar   seccnt;         /* sector count */
277         char    pad2[3];
278         uchar   lba0;
279         char    pad3[3];
280         uchar   lba1;
281         char    pad4[3];
282         uchar   lba2;
283         char    pad5[3];
284         uchar   lba3;
285         char    pad6[3];
286         uchar   cmdstat;                /* cmd/status */
287         char    pad7[3];
288         uchar   altstat;                /* alternate status */
289         uchar   fill2[0x1df];
290         Bridge  port;
291         char    fill3[0x1c00];  /* pad to 0x2000 bytes */
292 };
293
294 /*
295  * Memory structures shared with card.
296  */
297 struct Prd                      /* physical region descriptor */
298 {
299         ulong   pa;             /* byte address of physical memory */
300         ushort  count;          /* byte count (bit0 must be 0) */
301         ushort  flag;
302         ulong   zero;           /* high long of 64 bit address */
303         ulong   reserved;
304 };
305
306 struct Tx                               /* command request block */
307 {
308         ulong   prdpa;          /* physical region descriptor table structures */
309         ulong   zero;           /* must be zero (high long of prd address) */
310         ushort  flag;           /* control flags */
311         ushort  regs[11];
312 };
313
314 struct Rx                               /* command response block */
315 {
316         ushort  cid;            /* cID of response */
317         uchar   cEdmaSts;       /* EDMA status */
318         uchar   cDevSts;                /* status from disk */
319         ulong   ts;             /* time stamp */
320 };
321
322 static  Ctlr    *mvsatactlr[NCtlr];
323 static  Drive   *mvsatadrive[NDrive];
324 static  int     nmvsatadrive;
325 static  char    *diskstates[Dlast] = {
326         "null",
327         "new",
328         "ready",
329         "error",
330         "missing",
331         "reset",
332 };
333
334 extern SDifc sdmv50xxifc;
335
336 /*
337  * Request buffers.
338  */
339 static struct
340 {
341         Lock;
342         Srb     *freechain;
343         int     nalloc;
344 } srblist;
345
346 static Srb*
347 allocsrb(void)
348 {
349         Srb *p;
350
351         ilock(&srblist);
352         if((p = srblist.freechain) == nil){
353                 srblist.nalloc++;
354                 iunlock(&srblist);
355                 p = smalloc(sizeof *p);
356         }else{
357                 srblist.freechain = p->next;
358                 iunlock(&srblist);
359         }
360         return p;
361 }
362
363 static void
364 freesrb(Srb *p)
365 {
366         ilock(&srblist);
367         p->next = srblist.freechain;
368         srblist.freechain = p;
369         iunlock(&srblist);
370 }
371
372 static int
373 satawait(uchar *p, uchar mask, uchar v, int ms)
374 {
375         int i;
376
377         for(i=0; i<ms && (*p & mask) != v; i++)
378                 microdelay(1000);
379         return (*p & mask) == v;
380 }
381
382 /* unmask in the pci registers err done */
383 static void
384 portswitch(ulong *mmio, int port, uint coal, uint on)
385 {
386         ulong m;
387
388         m = 3<<(port&3)*2 | coal<<8;
389         if((port&7) >= 4)
390                 m <<= 9;
391         if(on)
392                 mmio[Portswtch] |= m;
393         else
394                 mmio[Portswtch] &= m;
395 }
396
397 static char*
398 dnam(Drive *d)
399 {
400         if(d->unit)
401                 return d->unit->name;
402         return d->name;
403 }
404
405 /* I give up, marvell.  You win. */
406 static void
407 phyerrata(Drive *d)
408 {
409         ulong n, m;
410         enum { BadAutoCal = 0xf << 26, };
411
412         if(d->ctlr->type == 1){
413                 /* set phyctrl bits [0:1] to 01 per MV-S102013-00 Rev C. */
414                 n = d->bridge->phyctrl;
415                 n &= ~3;
416                 d->bridge->phyctrl = n | 1;
417                 return;
418         }
419         microdelay(200);
420         n = d->bridge->phymode2;
421         while ((n & BadAutoCal) == BadAutoCal) {
422                 dprint("%s: badautocal\n", dnam(d));
423                 n &= ~(1<<16);
424                 n |= 1<<31;
425                 d->bridge->phymode2 = n;
426                 microdelay(200);
427                 d->bridge->phymode2 &= ~(1<<16 | 1<<31);
428                 microdelay(200);
429                 n = d->bridge->phymode2;
430         }
431         n &= ~(1<<31);
432         d->bridge->phymode2 = n;
433         microdelay(200);
434
435         /* abra cadabra!  (random magic) */
436         m = d->bridge->phymode3;
437         m &= ~0x7f800000;
438         m |= 0x2a800000;
439         d->bridge->phymode3 = m;
440
441         /* fix phy mode 4 */
442         m = d->bridge->phymode3;
443         n = d->bridge->phymode4;
444         n &= ~(1<<1);
445         n |= 1;
446         switch(d->ctlr->rid){
447         case REV60X1B2:
448         default:
449                 d->bridge->phymode4 = n;
450                 d->bridge->phymode3 = m;
451                 break;
452         case REV60X1C0:
453                 d->bridge->phymode4 = n;
454                 break;
455         }
456
457         /* revert values of pre-emphasis and signal amps to the saved ones */
458         n = d->bridge->phymode2;
459         n &= ~Mpreamp;
460         n |= d->pm2;
461         n &= ~(1<<16);
462         d->bridge->phymode2 = n;
463 }
464
465 static void
466 edmacleanout(Drive *d)
467 {
468         int i;
469         Srb *srb;
470
471         for(i=0; i<nelem(d->srb); i++){
472                 if(srb = d->srb[i]){
473                         d->srb[i] = nil;
474                         d->nsrb--;
475                         srb->flag |= SFerror|SFdone;
476                         wakeup(srb);
477                 }
478         }
479         while(srb = d->srbhead){
480                 d->srbhead = srb->next;
481                 srb->flag |= SFerror|SFdone;
482                 wakeup(srb);
483         }
484 }
485
486 static int
487 edmadisable(Drive *d, int reset)
488 {
489         Edma *e;
490
491         e = d->edma;
492         if(!reset && (e->ctl & eEnEDMA) == 0)
493                 return 0;
494         e->ctl = eDsEDMA;
495         microdelay(1);
496         if(reset)
497                 e->ctl = eAtaRst;
498         microdelay(25);
499         e->ctl = 0;
500         if (satawait((uchar *)&e->ctl, eEnEDMA, 0, 3*1000) == 0){
501                 print("%s: eEnEDMA never cleared on reset\n", dnam(d));
502                 return -1;
503         }
504         edmacleanout(d);
505         return 0;
506 }
507
508 static void
509 resetdisk(Drive *d)
510 {
511         ulong n;
512
513         d->sectors = 0;
514         d->unit->sectors = 0;
515         if (d->ctlr->type == 2) {
516                 /*
517                  * without bit 8 we can boot without disks, but
518                  * inserted disks will never appear.  :-X
519                  */
520                 n = d->edma->sataconfig;
521                 n &= 0xff;
522                 n |= 0x9b1100;
523                 d->edma->sataconfig = n;
524                 n = d->edma->sataconfig;        /* flush */
525                 USED(n);
526         }
527         if(edmadisable(d, 1) == -1){
528         }
529         phyerrata(d);
530         d->bridge->sctrl = 0x301 | d->mode<<4;
531         d->state = Dmissing;
532 }
533
534 static void
535 edmainit(Drive *d)
536 {
537         int i;
538
539         if(d->tx != nil)
540                 return;
541
542         d->tx = xspanalloc(32*sizeof(Tx), 1024, 0);
543         d->rx = xspanalloc(32*sizeof(Rx), 256, 0);
544         d->prd = xspanalloc(32*sizeof(Prd), 32, 0);
545         for(i = 0; i < 32; i++)
546                 d->tx[i].prdpa = PCIWADDR(&d->prd[i]);
547         coherence();
548 }
549
550 static int
551 configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
552 {
553         dprint("%s: configdrive\n", unit->name);
554         d->unit = unit;
555         resetdisk(d);
556         portswitch(ctlr->lmmio, d->driveno, 0, 1);
557         delay(100);
558         if(d->bridge->status){
559                 dprint("%s: configdrive: found drive %lux\n", unit->name, d->bridge->status);
560                 return 0;
561         }
562         return -1;
563 }
564
565 static int
566 edmaenable(Drive *d)
567 {
568         Edma *edma;
569
570         dprint("%s: enabledrive..", dnam(d));
571
572         if((d->bridge->status & 0xf) != 3){
573                 dprint("%s: not present\n", dnam(d));
574                 return -1;
575         }
576         edma = d->edma;
577         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
578                 dprint("%s: busy timeout\n", dnam(d));
579                 return -1;
580         }
581         edma->iec = 0;
582         d->chip->arb->ic &= ~(0x101 << d->chipx);
583         edma->config = 0x51f;
584         if (d->ctlr->type == 2)
585                 edma->config |= 7<<11;
586         edma->txi = PCIWADDR(d->tx);
587         edma->txo = (ulong)d->tx & 0x3e0;
588         edma->rxi = (ulong)d->rx & 0xf8;
589         edma->rxo = PCIWADDR(d->rx);
590         edma->ctl |= 1;         /* enable dma */
591         return 0;
592 }
593
594 static int
595 enabledrive(Drive *d)
596 {
597         dprint("%s: enabledrive..", dnam(d));
598         if(edmaenable(d) == 0){
599                 switch(d->bridge->status){
600                 case 0x113:
601                 case 0x123:
602                         d->state = Dnew;
603                         break;
604                 }
605                 return 0;
606         }
607         print("mv50: enable reset\n");
608         d->state = Dreset;
609         return -1;
610 }
611
612 static void
613 disabledrive(Drive *d)
614 {
615         if(d->tx == nil)        /* never enabled */
616                 return;
617         d->edma->ctl = 0;
618         d->edma->iem = 0;
619         portswitch(d->ctlr->lmmio, d->driveno, 0, 0);
620 }
621
622 static int
623 setudmamode(Drive *d, uchar mode)
624 {
625         Edma *edma;
626
627         dprint("%s: setudmamode %d\n", dnam(d), mode);
628         edma = d->edma;
629         if(edma == nil) {
630                 iprint("setudamode(m%d): zero d->edma\m", d->driveno);
631                 return 0;
632         }
633         if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 250) == 0){
634                 iprint("%s: cmdstat 0x%.2ux ready timeout\n", dnam(d), edma->cmdstat);
635                 return 0;
636         }
637         edma->altstat = ATAeIEN;
638         edma->err = 3;
639         edma->seccnt = 0x40 | mode;
640         edma->cmdstat = 0xef;
641         microdelay(1);
642         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
643                 iprint("%s: cmdstat 0x%.2ux busy timeout\n", dnam(d), edma->cmdstat);
644                 return 0;
645         }
646         return 1;
647 }
648
649 static int
650 identifydrive(Drive *d)
651 {
652         char *s;
653         int i;
654         ushort *id;
655         Edma *edma;
656         SDunit *u;
657
658         dprint("%s: identifydrive\n", dnam(d));
659         setfissig(d, 0);                        /* BOTCH; need to find and set signature */
660         if(setudmamode(d, 5) == 0)      /* BOTCH; run after identify */
661                 goto Error;
662
663         id = d->info;
664         memset(d->info, 0, sizeof d->info);
665         edma = d->edma;
666         if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 5*1000) == 0)
667                 goto Error;
668
669         edma->altstat = ATAeIEN;        /* no interrupts */
670         edma->cmdstat = 0xec;
671         microdelay(1);
672         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
673                 goto Error;
674         for(i = 0; i < 256; i++)
675                 id[i] = edma->pio;
676         if(edma->cmdstat & ATAbad)
677                 goto Error;
678         d->sectors = idfeat(d, id);
679         d->secsize = idss(d, id);
680         idmove(d->serial, id+10, 20);
681         idmove(d->firmware, id+23, 8);
682         idmove(d->model, id+27, 40);
683         d->wwn = idwwn(d, id);
684
685         u = d->unit;
686         memset(u->inquiry, 0, sizeof u->inquiry);
687         u->inquiry[2] = 2;
688         u->inquiry[3] = 2;
689         u->inquiry[4] = sizeof u->inquiry - 4;
690         idmove((char*)u->inquiry+8, id+27, 40);
691
692         if(enabledrive(d) == 0) {
693                 d->state = Dready;
694                 d->drivechange = 1;
695                 s = nil;
696                 if(d->feat & Dllba)
697                         s = "L";
698                 idprint("%s: %sLBA %llud sectors\n", dnam(d), s, d->sectors);
699         } else
700                 d->state = Derror;
701         if(d->state == Dready)
702                 return 0;
703         return -1;
704 Error:
705         dprint("error...");
706         d->state = Derror;
707         return -1;
708 }
709
710 /*
711  * p. 163:
712  *      M       recovered error
713  *      P       protocol error
714  *      N       PhyRdy change
715  *      W       CommWake
716  *      B       8-to-10 encoding error
717  *      D       disparity error
718  *      C       crc error
719  *      H       handshake error
720  *      S       link sequence error
721  *      T       transport state transition error
722  *      F       unrecognized fis type
723  *      X       device changed
724  */
725
726 static char stab[] = {
727 [1]     'M',
728 [10]    'P',
729 [16]    'N',
730 [18]    'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
731 };
732 static ulong sbad = 7<<20 | 3<<23;
733
734 static void
735 serrdecode(ulong r, char *s, char *e)
736 {
737         int i;
738
739         e -= 3;
740         for(i = 0; i < nelem(stab) && s < e; i++)
741                 if(r & 1<<i && stab[i]){
742                         *s++ = stab[i];
743                         if(sbad & 1<<i)
744                                 *s++ = '*';
745                 }
746         *s = 0;
747 }
748
749 static char *iectab[] = {
750         "ePrtDataErr",
751         "ePrtPRDErr",
752         "eDevErr",
753         "eDevDis",
754         "eDevCon",
755         "SerrInt",
756         "eUnderrun",
757         "eSelfDis2",
758         "eSelfDis",
759         "ePrtCRQBErr",
760         "ePrtCRPBErr",
761         "ePrtIntErr",
762         "eIORdyErr",
763 };
764
765 static char*
766 iecdecode(ulong cause)
767 {
768         int i;
769
770         for(i = 0; i < nelem(iectab); i++)
771                 if(cause&(1<<i))
772                         return iectab[i];
773         return "";
774 }
775
776 enum{
777         Cerror1 = ePrtDataErr|ePrtPRDErr|eOverrun|ePrtCRQBErr|ePrtCRPBErr|ePrtIntErr,
778         Cerror2 = ePrtDataErr|ePrtPRDErr|ePrtCRQBErr|
779                         ePrtCRPBErr|ePrtIntErr|eDevErr|eSelfDis2,
780 };
781
782 static void
783 updatedrive(Drive *d)
784 {
785         int x;
786         ulong cause;
787         Edma *edma;
788         char buf[32+4+1];
789
790         edma = d->edma;
791         if((edma->ctl & eEnEDMA) == 0){
792                 /* FEr SATA#4 40xx */
793                 x = d->edma->cmdstat;
794                 USED(x);
795         }
796         cause = edma->iec;
797         if(cause == 0)
798                 return;
799         dprint("%s: cause %.8lux [%s]\n", dnam(d), cause, iecdecode(cause));
800         if(cause & eDevCon)
801                 d->state = Dnew;
802         if(cause & eDevDis && d->state == Dready)
803                 iprint("%s: pulled: st=%.8lux\n", dnam(d), cause);
804         switch(d->ctlr->type){
805         case 1:
806                 if(cause & eUnderrun){
807                         /* FEr SATA#5 50xx for revs A0, B0 */
808                         if(d->ctlr->rid < 2)
809                                 d->state = Dreset;
810                         else{
811                                 d->state = Derror;
812                                 dprint("%s: underrun\n", dnam(d));
813                         }
814                 }
815                 if(cause & (eDevErr | eSelfDis)){
816                         /*
817                          * FEr SATA#7 60xx for refs A0, B0
818                          * check for IRC error.  we only check the
819                          * ABORT flag as we don't get the upper nibble
820                          */
821                         if(d->ctlr->rid < 2)
822                         if(edma->altstat & ATAerr && edma->err & ATAabort)
823                                 d->state = Dreset;
824                         else
825                                 d->state = Derror;
826                 }
827                 if(cause & Cerror1)
828                         d->state = Dreset;
829                 break;
830         case 2:
831                 if(cause & Cerror2)
832                         d->state = Dreset;
833                 if(cause & SerrInt){
834                         serrdecode(d->bridge->serror, buf, buf+sizeof buf);
835                         dprint("%s: serror %.8lux [%s]\n", dnam(d), d->bridge->serror, buf);
836                         d->bridge->serror = ~0; /*d->bridge->serror;*/
837                 }
838                 break;
839         }
840         edma->iec = ~cause;
841 }
842
843 /*
844  * Requests
845  */
846 static Srb*
847 srbrw(int rw, Drive *d, uchar *data, uint sectors, uvlong lba)
848 {
849         int i;
850         Srb *srb;
851         static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
852
853         srb = allocsrb();
854         srb->req = rw;
855         srb->drive = d;
856         srb->blockno = lba;
857         srb->sectors = sectors;
858         srb->count = sectors * d->secsize;
859         srb->flag = 0;
860         srb->data = data;
861
862         for(i=0; i<6; i++)
863                 srb->lba[i] = lba >> 8*i;
864         srb->cmd = cmd[srb->req!=SDread][(d->feat&Dllba)!=0];
865         return srb;
866 }
867
868 #define CMD(r, v) (((r)<<8) | (v))
869 static void
870 mvsatarequest(ushort *cmd, Srb *srb, int llba)
871 {
872         *cmd++ = CMD(ARseccnt, 0);
873         *cmd++ = CMD(ARseccnt, srb->sectors);
874         *cmd++ = CMD(ARfea, 0);
875         if(llba){
876                 *cmd++ = CMD(ARlba0, srb->lba[3]);
877                 *cmd++ = CMD(ARlba0, srb->lba[0]);
878                 *cmd++ = CMD(ARlba1, srb->lba[4]);
879                 *cmd++ = CMD(ARlba1, srb->lba[1]);
880                 *cmd++ = CMD(ARlba2, srb->lba[5]);
881                 *cmd++ = CMD(ARlba2, srb->lba[2]);
882                 *cmd++ = CMD(ARdev, 0xe0);
883         }else{
884                 *cmd++ = CMD(ARlba0, srb->lba[0]);
885                 *cmd++ = CMD(ARlba1, srb->lba[1]);
886                 *cmd++ = CMD(ARlba2, srb->lba[2]);
887                 *cmd++ = CMD(ARdev, srb->lba[3] | 0xe0);
888         }
889         *cmd = CMD(ARcmd, srb->cmd) | 1<<15;
890 }
891
892 static uintptr
893 advance(uintptr pa, int shift)
894 {
895         int n, mask;
896
897         mask = 0x1F<<shift;
898         n = (pa & mask) + (1<<shift);
899         return (pa & ~mask) | (n & mask);
900 }
901
902 static void
903 startsrb(Drive *d, Srb *srb)
904 {
905         int i;
906         Edma *edma;
907         Prd *prd;
908         Tx *tx;
909
910         if(d->nsrb >= nelem(d->srb)){
911                 srb->next = nil;
912                 if(d->srbhead)
913                         d->srbtail->next = srb;
914                 else
915                         d->srbhead = srb;
916                 d->srbtail = srb;
917                 return;
918         }
919
920         d->nsrb++;
921         for(i=0; i<nelem(d->srb); i++)
922                 if(d->srb[i] == nil)
923                         break;
924         if(i == nelem(d->srb))
925                 panic("sdmv50xx: no free srbs");
926         d->intick = Ticks;
927         d->srb[i] = srb;
928         edma = d->edma;
929         tx = (Tx*)KADDR(edma->txi);
930         tx->flag = i<<1 | (srb->req == SDread);
931         prd = KADDR(tx->prdpa);
932         prd->pa = PCIWADDR(srb->data);
933         prd->count = srb->count;
934         prd->flag = PRDeot;
935         mvsatarequest(tx->regs, srb, d->feat&Dllba);
936         coherence();
937         edma->txi = advance(edma->txi, 5);
938         d->intick = Ticks;
939 }
940
941 enum{
942         Rpidx   = 0x1f<<3,
943 };
944
945 static void
946 completesrb(Drive *d)
947 {
948         Edma *edma;
949         Rx *rx;
950         Srb *srb;
951
952         edma = d->edma;
953         if((edma->ctl & eEnEDMA) == 0)
954                 return;
955
956         while((edma->rxo&Rpidx) != (edma->rxi&Rpidx)){
957                 rx = (Rx*)KADDR(edma->rxo);
958                 if(srb = d->srb[rx->cid]){
959                         d->srb[rx->cid] = nil;
960                         d->nsrb--;
961                         if(rx->cDevSts & ATAbad)
962                                 srb->flag |= SFerror;
963                         if (rx->cEdmaSts)
964                                 iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
965                         srb->sta = rx->cDevSts;
966                         srb->flag |= SFdone;
967                         wakeup(srb);
968                 }else
969                         iprint("srb missing\n");
970                 edma->rxo = advance(edma->rxo, 3);
971                 if(srb = d->srbhead){
972                         d->srbhead = srb->next;
973                         startsrb(d, srb);
974                 }
975         }
976 }
977
978 static int
979 srbdone(void *v)
980 {
981         Srb *srb;
982
983         srb = v;
984         return srb->flag & SFdone;
985 }
986
987 /*
988  * Interrupts
989  */
990 static void
991 mv50interrupt(Ureg*, void *v)
992 {
993         int i;
994         ulong cause, tk0, m;
995         Arb *a;
996         Ctlr *ctlr;
997         Drive *drive;
998         static uint st;
999
1000         ctlr = v;
1001         ilock(ctlr);
1002         cause = ctlr->lmmio[0x1d60/4];
1003 //      dprint("sd%c: mv50interrupt: %.8lux\n", ctlr->sdev->idno, cause);
1004         for(i=0; cause && i<ctlr->ndrive; i++)
1005                 if(cause & (3<<(i*2+i/4))){
1006                         drive = &ctlr->drive[i];
1007                         if(drive->edma == 0)
1008                                 continue;       /* not ready yet. */
1009                         ilock(drive);
1010                         updatedrive(drive);
1011                         tk0 = Ticks;
1012                         a = ctlr->chip[i/4].arb;
1013                         m = 0x0101 << i%4;
1014                         while(a->ic & m){
1015                                 a->ic = ~m;
1016                                 completesrb(drive);
1017                                 if(TK2MS(Ticks - tk0) > 3000){
1018                                         print("%s: irq wedge\n", dnam(drive));
1019                                         drive->state = Dreset;
1020                                         break;
1021                                 }
1022                         }
1023                         iunlock(drive);
1024                 }
1025         iunlock(ctlr);
1026 }
1027
1028 enum{
1029         Nms             = 256,
1030         Midwait         = 16*1024/Nms - 1,
1031         Mphywait        = 512/Nms - 1,
1032 };
1033
1034 static void
1035 hangck(Drive *d)
1036 {
1037         Edma *e;
1038
1039         e = d->edma;
1040         if(d->nsrb > 0
1041         && TK2MS(Ticks - d->intick) > 5*1000
1042         && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
1043                 print("%s: drive hung; resetting\n", dnam(d));
1044                 d->state = Dreset;
1045         }
1046 }
1047
1048 static void
1049 checkdrive(Drive *d, int i)
1050 {
1051         static ulong s, olds[NCtlr*NCtlrdrv];
1052
1053         ilock(d);
1054         s = d->bridge->status;
1055         if(s != olds[i]){
1056                 dprint("%s: status: %.8lux -> %.8lux: %s\n", dnam(d), olds[i], s, diskstates[d->state]);
1057                 olds[i] = s;
1058         }
1059         hangck(d);
1060         switch(d->state){
1061         case Dnew:
1062         case Dmissing:
1063                 switch(s){
1064                 case 0x000:
1065                         break;
1066                 default:
1067                         dprint("%s: unknown state %.8lux\n", dnam(d), s);
1068                 case 0x100:
1069                         if(++d->wait&Mphywait)
1070                                 break;
1071                 reset:  d->mode ^= 1;
1072                         dprint("%s: reset; new mode %d\n", dnam(d), d->mode);
1073                         resetdisk(d);
1074                         break;
1075                 case 0x123:
1076                 case 0x113:
1077                         s = d->edma->cmdstat;
1078                         if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
1079                                 if((++d->wait&Midwait) == 0)
1080                                         goto reset;
1081                         }else if(identifydrive(d) == -1)
1082                                 goto reset;
1083                 }
1084                 break;
1085         case Dready:
1086                 if(s != 0)
1087                         break;
1088                 iprint("%s: pulled: st=%.8lux\n", dnam(d), s); /* never happens */
1089         case Dreset:
1090         case Derror:
1091                 dprint("%s reset: mode %d\n", dnam(d), d->mode);
1092                 resetdisk(d);
1093                 break;
1094         }
1095         iunlock(d);
1096 }
1097
1098 static void
1099 satakproc(void*)
1100 {
1101         int i;
1102
1103         for(;;){
1104                 tsleep(&up->sleep, return0, 0, Nms);
1105                 for(i = 0; i < nmvsatadrive; i++)
1106                         checkdrive(mvsatadrive[i], i);
1107         }
1108 }
1109
1110 static void
1111 initdrive(Drive *d)
1112 {
1113         edmainit(d);
1114         d->mode = DMsatai;
1115         if(d->ctlr->type == 1){
1116                 d->edma->iem = IEM;
1117                 d->bridge = &d->chip->arb->bridge[d->chipx];
1118         }else{
1119                 d->edma->iem = IEM2;
1120                 d->bridge = &d->chip->edma[d->chipx].port;
1121 //              d->edma->iem = ~(1<<6);
1122                 d->pm2 = Dpreamp;
1123                 if(d->ctlr->lmmio[0x180d8/4] & 1)
1124                         d->pm2 = d->bridge->phymode2 & Mpreamp;
1125         }
1126 }
1127
1128 static SDev*
1129 mv50pnp(void)
1130 {
1131         int i, nunit;
1132         uchar *base;
1133         ulong io, n, *mem;
1134         Ctlr *ctlr;
1135         Drive *d;
1136         Pcidev *p;
1137         SDev *head, *tail, *sdev;
1138         static int ctlrno, done;
1139
1140         if(done++)
1141                 return nil;
1142
1143         p = nil;
1144         head = nil;
1145         tail = nil;
1146         while((p = pcimatch(p, 0x11ab, 0)) != nil){
1147                 if(p->ccrb != Pcibcstore || p->ccru + p->ccrp || p->did&0x0f00)
1148                         continue;
1149                 switch(p->did){
1150                 case 0x5040:
1151                 case 0x5041:
1152                 case 0x5080:
1153                 case 0x5081:
1154                 case 0x6041:
1155                 case 0x6081:
1156                         break;
1157                 default:
1158                         print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
1159                         continue;
1160                 }
1161                 if (ctlrno >= NCtlr) {
1162                         print("mv50pnp: too many controllers\n");
1163                         break;
1164                 }
1165                 nunit = (p->did&0xf0) >> 4;
1166                 print("#S/sd%c: Marvell 88sx%ux: %d sata-%s ports with%s flash\n",
1167                         'E' + ctlrno, (ushort)p->did, nunit,
1168                         ((p->did&0xf000)==0x6000? "II": "I"),
1169                         (p->did&1? "": "out"));
1170                 if((sdev = malloc(sizeof *sdev)) == nil)
1171                         continue;
1172                 if((ctlr = malloc(sizeof *ctlr)) == nil){
1173                         free(sdev);
1174                         continue;
1175                 }
1176                 io = p->mem[0].bar & ~0x0F;
1177                 mem = (ulong*)vmap(io, p->mem[0].size);
1178                 if(mem == 0){
1179                         print("sdmv50xx: address 0x%luX in use\n", io);
1180                         free(sdev);
1181                         free(ctlr);
1182                         continue;
1183                 }
1184                 ctlr->rid = p->rid;
1185
1186                 /* avert thine eyes!  (what does this do?) */
1187                 mem[0x104f0/4] = 0;
1188                 ctlr->type = (p->did >> 12) & 3;
1189                 if(ctlr->type == 1){
1190                         n = mem[0xc00/4];
1191                         n &= ~(3<<4);
1192                         mem[0xc00/4] = n;
1193                 }
1194
1195                 sdev->ifc = &sdmv50xxifc;
1196                 sdev->ctlr = ctlr;
1197                 sdev->nunit = nunit;
1198                 sdev->idno = 'E';
1199                 ctlr->sdev = sdev;
1200                 ctlr->irq = p->intl;
1201                 ctlr->tbdf = p->tbdf;
1202                 ctlr->pcidev = p;
1203                 ctlr->lmmio = mem;
1204                 ctlr->mmio = (uchar*)mem;
1205                 ctlr->nchip = (nunit+3)/4;
1206                 ctlr->ndrive = nunit;
1207                 ctlr->enabled = 0;
1208                 for(i = 0; i < ctlr->nchip; i++){
1209                         base = ctlr->mmio+0x20000+0x10000*i;
1210                         ctlr->chip[i].arb = (Arb*)base;
1211                         ctlr->chip[i].edma = (Edma*)(base + 0x2000);
1212                 }
1213                 for (i = 0; i < nunit; i++) {
1214                         d = &ctlr->drive[i];
1215                         snprint(d->name, sizeof d->name, "mv50%d.%d", ctlrno, i);
1216                         d->sectors = 0;
1217                         d->ctlr = ctlr;
1218                         d->driveno = ctlrno*NCtlrdrv + i;
1219                         d->chipx = i%4;
1220                         d->chip = &ctlr->chip[i/4];
1221                         d->edma = &d->chip->edma[d->chipx];
1222                         mvsatadrive[d->driveno] = d;
1223                         initdrive(d);
1224                 }
1225                 mvsatactlr[ctlrno] = ctlr;
1226                 nmvsatadrive += nunit;
1227                 ctlrno++;
1228                 if(head)
1229                         tail->next = sdev;
1230                 else
1231                         head = sdev;
1232                 tail = sdev;
1233         }
1234         return head;
1235 }
1236
1237 static int
1238 mv50enable(SDev *sdev)
1239 {
1240         char name[32];
1241         Ctlr *ctlr;
1242
1243         dprint("sd%c: enable\n", sdev->idno);
1244
1245         ctlr = sdev->ctlr;
1246         if (ctlr->enabled)
1247                 return 1;
1248         ctlr->enabled = 1;
1249         kproc("mvsata", satakproc, 0);
1250         snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1251         intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1252         return 1;
1253 }
1254
1255 static int
1256 mv50disable(SDev *sdev)
1257 {
1258         char name[32];
1259         int i;
1260         Ctlr *ctlr;
1261         Drive *drive;
1262
1263         dprint("sd%c: disable\n", sdev->idno);
1264
1265         ctlr = sdev->ctlr;
1266         ilock(ctlr);
1267         for(i=0; i<ctlr->sdev->nunit; i++){
1268                 drive = &ctlr->drive[i];
1269                 ilock(drive);
1270                 disabledrive(drive);
1271                 iunlock(drive);
1272         }
1273         iunlock(ctlr);
1274         snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1275         intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1276         return 0;
1277 }
1278
1279 /*
1280  * Check that there is a disk or at least a hot swap bay in the drive.
1281  */
1282 static int
1283 mv50verify(SDunit *unit)
1284 {
1285         Ctlr *ctlr;
1286         Drive *drive;
1287         int i;
1288
1289         dprint("%s: verify\n", unit->name);
1290         ctlr = unit->dev->ctlr;
1291         drive = &ctlr->drive[unit->subno];
1292         ilock(ctlr);
1293         ilock(drive);
1294         i = configdrive(ctlr, drive, unit);
1295         iunlock(drive);
1296         iunlock(ctlr);
1297
1298         /*
1299          * If ctlr->type == 1, then the drives spin up whenever
1300          * the controller feels like it; if ctlr->type == 2, then
1301          * they spin up as a result of configdrive.
1302          *
1303          * If there is a drive in the slot, give it 1.4s to spin up
1304          * before returning.  There is a noticeable drag on the
1305          * power supply when spinning up fifteen drives
1306          * all at once (like in the Coraid enclosures).
1307          */
1308         if(ctlr->type == 2 && i == 0)
1309                 if(!waserror()){
1310                         tsleep(&up->sleep, return0, 0, 1400);
1311                         poperror();
1312                 }
1313         return 1;
1314 }
1315
1316 /*
1317  * Check whether the disk is online.
1318  */
1319 static int
1320 mv50online(SDunit *unit)
1321 {
1322         Ctlr *ctlr;
1323         Drive *d;
1324         int r, s0;
1325         static int once;
1326
1327         ctlr = unit->dev->ctlr;
1328         d = &ctlr->drive[unit->subno];
1329         r = 0;
1330         ilock(d);
1331         s0 = d->state;
1332         USED(s0);
1333         if(d->state == Dnew)
1334                 identifydrive(d);
1335         if(d->drivechange){
1336                 idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
1337                 r = 2;
1338                 unit->sectors = d->sectors;
1339                 unit->secsize = d->secsize;
1340                 d->drivechange = 0;
1341         } else if(d->state == Dready)
1342                 r = 1;
1343         iunlock(d);
1344         return r;
1345 }
1346
1347 /*
1348  * Register dumps
1349  */
1350 typedef struct Regs Regs;
1351 struct Regs
1352 {
1353         ulong offset;
1354         char *name;
1355 };
1356
1357 static Regs regsctlr[] =
1358 {
1359         0x0C28, "pci serr# mask",
1360         0x1D40, "pci err addr low",
1361         0x1D44, "pci err addr hi",
1362         0x1D48, "pci err attr",
1363         0x1D50, "pci err cmd",
1364         0x1D58, "pci intr cause",
1365         0x1D5C, "pci mask cause",
1366         0x1D60, "device micr",
1367         0x1D64, "device mimr",
1368 };
1369
1370 static Regs regsarb[] =
1371 {
1372         0x0004, "arb rqop",
1373         0x0008, "arb rqip",
1374         0x000C, "arb ict",
1375         0x0010, "arb itt",
1376         0x0014, "arb ic",
1377         0x0018, "arb btc",
1378         0x001C, "arb bts",
1379         0x0020, "arb bpc",
1380 };
1381
1382 static Regs regsbridge[] =
1383 {
1384         0x0000, "bridge status",
1385         0x0004, "bridge serror",
1386         0x0008, "bridge sctrl",
1387         0x000C, "bridge phyctrl",
1388         0x003C, "bridge ctrl",
1389         0x0074, "bridge phymode",
1390 };
1391
1392 static Regs regsedma[] =
1393 {
1394         0x0000, "edma config",
1395         0x0004, "edma timer",
1396         0x0008, "edma iec",
1397         0x000C, "edma iem",
1398         0x0010, "edma txbasehi",
1399         0x0014, "edma txi",
1400         0x0018, "edma txo",
1401         0x001C, "edma rxbasehi",
1402         0x0020, "edma rxi",
1403         0x0024, "edma rxo",
1404         0x0028, "edma c",
1405         0x002C, "edma tc",
1406         0x0030, "edma status",
1407         0x0034, "edma iordyto",
1408 /*      0x0100, "edma pio",
1409         0x0104, "edma err",
1410         0x0108, "edma sectors",
1411         0x010C, "edma lba0",
1412         0x0110, "edma lba1",
1413         0x0114, "edma lba2",
1414         0x0118, "edma lba3",
1415         0x011C, "edma cmdstat",
1416         0x0120, "edma altstat",
1417 */
1418 };
1419
1420 static char*
1421 rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
1422 {
1423         int i;
1424
1425         for(i=0; i<n; i++)
1426                 p = seprint(p, e, "%s%s%-19s %.8ux\n",
1427                         prefix ? prefix : "", prefix ? ": " : "",
1428                         r[i].name, *(u32int*)((uchar*)base+r[i].offset));
1429         return p;
1430 }
1431
1432 static int
1433 mv50rctl(SDunit *unit, char *p, int l)
1434 {
1435         char *e, *op;
1436         Ctlr *ctlr;
1437         Drive *drive;
1438
1439         if((ctlr = unit->dev->ctlr) == nil)
1440                 return 0;
1441         drive = &ctlr->drive[unit->subno];
1442
1443         e = p+l;
1444         op = p;
1445         if(drive->state == Dready){
1446                 p = seprint(p, e, "model    %s\n", drive->model);
1447                 p = seprint(p, e, "serial   %s\n", drive->serial);
1448                 p = seprint(p, e, "firmware %s\n", drive->firmware);
1449                 p = seprint(p, e, "wwn\t%llux\n", drive->wwn);
1450                 p = seprint(p, e, "flag\t");
1451                 p = pflag(p, e, drive);
1452         }else
1453                 p = seprint(p, e, "no disk present\n");
1454         p = seprint(p, e, "geometry %llud %ud\n", drive->sectors, drive->secsize);
1455         p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1456         if(0){
1457                 p = rdregs(p, e, drive->chip->arb, regsarb, nelem(regsarb), nil);
1458                 p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1459                 p = rdregs(p, e, drive->edma, regsedma, nelem(regsedma), nil);
1460         }
1461         return p-op;
1462 }
1463
1464 static int
1465 mv50wctl(SDunit *unit, Cmdbuf *cb)
1466 {
1467         Ctlr *ctlr;
1468         Drive *drive;
1469
1470         if(strcmp(cb->f[0], "reset") == 0){
1471                 ctlr = unit->dev->ctlr;
1472                 drive = &ctlr->drive[unit->subno];
1473                 ilock(drive);
1474                 drive->state = Dreset;
1475                 iunlock(drive);
1476                 return 0;
1477         }
1478         cmderror(cb, Ebadctl);
1479         return -1;
1480 }
1481
1482 static int
1483 waitready(Drive *d)
1484 {
1485         ulong s, i;
1486
1487         for(i = 0; i < 120; i++){
1488                 ilock(d);
1489                 s = d->bridge->status;
1490                 iunlock(d);
1491                 if(s == 0)
1492                         return SDeio;
1493                 if(d->state == Dready)
1494                         return SDok;
1495                 if((i+1)%60 == 0){
1496                         ilock(d);
1497                         resetdisk(d);
1498                         iunlock(d);
1499                 }
1500                 if(!waserror()){
1501                         tsleep(&up->sleep, return0, 0, 1000);
1502                         poperror();
1503                 }
1504         }
1505         print("%s: not responding; error\n", dnam(d));
1506         return SDeio;
1507 }
1508
1509 static long
1510 mv50bio(SDunit *u, int /*lun*/, int write, void *a, long count, uvlong lba)
1511 {
1512         int n, try, flag;
1513         uchar *data;
1514         Ctlr *ctlr;
1515         Drive *d;
1516         Srb *srb;
1517
1518         ctlr = u->dev->ctlr;
1519         d = ctlr->drive + u->subno;
1520         try = 0;
1521         data = a;
1522 retry:
1523         if(waitready(d) != SDok)
1524                 return -1;
1525         while(count > 0){
1526                 /*
1527                  * Max is 128 sectors (64kB) because prd->count is 16 bits.
1528                  */
1529                 n = count;
1530                 if(n > 128)
1531                         n = 128;
1532                 ilock(d);
1533                 if((d->edma->ctl&eEnEDMA) == 0 && edmaenable(d) == -1){
1534                         iunlock(d);
1535                         goto tryagain;
1536                 }
1537                 srb = srbrw(write, d, data, n, lba);
1538                 startsrb(d, srb);
1539                 iunlock(d);
1540
1541                 while(waserror())
1542                         ;
1543                 sleep(srb, srbdone, srb);
1544                 poperror();
1545
1546                 flag = srb->flag;
1547                 freesrb(srb);
1548                 if(flag == 0){
1549         tryagain:               if(++try == 10){
1550                                 print("%s: bad disk\n", dnam(d));
1551                                 return -1;
1552                         }
1553                         dprint("%s: retry\n", dnam(d));
1554                         goto retry;
1555                 }
1556                 if(flag & SFerror){
1557                         print("%s: i/o error\n", dnam(d));
1558                         return -1;
1559                 }
1560                 count -= n;
1561                 lba += n;
1562                 data += n*u->secsize;
1563         }
1564         return data - (uchar*)a;
1565 }
1566
1567 static int
1568 mv50rio(SDreq *r)
1569 {
1570         int count, n, status, rw;
1571         uvlong lba;
1572         Ctlr *ctlr;
1573         Drive *d;
1574         SDunit *unit;
1575
1576         unit = r->unit;
1577         ctlr = unit->dev->ctlr;
1578         d = &ctlr->drive[unit->subno];
1579
1580         if((status = sdfakescsi(r)) != SDnostatus)
1581                 return r->status = status;
1582         if((status = sdfakescsirw(r, &lba, &count, &rw)) == SDcheck)
1583                 return status;
1584         n = mv50bio(r->unit, r->lun, rw, r->data, count, lba);
1585         if(n == -1)
1586                 return SDeio;
1587         r->rlen = n;
1588         return SDok;
1589 }
1590
1591 static void
1592 mkrfis(SDreq *r, Drive *d, Edma *e)
1593 {
1594         uchar *u;
1595
1596         u = r->cmd;
1597         u[Ftype] = 0x34;
1598         u[Fioport] = 0;
1599         if((d->feat & Dllba) && (r->ataproto & P28) == 0){
1600                 u[Frerror] = e->err;
1601                 u[Fsc8] = e->seccnt;
1602                 u[Fsc] = e->seccnt;
1603                 u[Flba24] = e->lba0;
1604                 u[Flba0] = e->lba0;
1605                 u[Flba32] = e->lba1;
1606                 u[Flba8] = e->lba1;
1607                 u[Flba40] = e->lba2;
1608                 u[Flba16] = e->lba2;
1609                 u[Fdev] = e->lba3;
1610                 u[Fstatus] = e->cmdstat;
1611         }else{
1612                 u[Frerror] = e->err;
1613                 u[Fsc] = e->seccnt;
1614                 u[Flba0] = e->lba0;
1615                 u[Flba8] = e->lba1;
1616                 u[Flba16] = e->lba2;
1617                 u[Fdev] = e->lba3;
1618                 u[Fstatus] = e->cmdstat;
1619         }
1620 }
1621
1622 static int
1623 piocmd(SDreq *r, Drive *d)
1624 {
1625         uchar *p, *c;
1626         int n, nsec, i, err;
1627         Edma *e;
1628         SDunit *u;
1629
1630         u = r->unit;
1631
1632         if(waitready(d) != SDok)
1633                 return SDeio;
1634         nsec = 0;
1635         if(u->secsize != 0)
1636                 nsec = r->dlen / u->secsize;
1637         if(r->dlen < nsec*u->secsize)
1638                 nsec = r->dlen/u->secsize;
1639         if(nsec > 256)
1640                 error("can't do more than 256 sectors");
1641
1642         ilock(d);
1643         e = d->edma;
1644         if(edmadisable(d, 0) == -1) {
1645                 iunlock(d);
1646                 error("can't disable edma");
1647         }
1648         n = satawait(&e->cmdstat, ATAdrdy|ATAbusy, ATAdrdy, 3*1000);
1649         if(n == 0) {
1650 print("piocmd: notready %.2ux\n", e->cmdstat);
1651                 iunlock(d);
1652                 return sdsetsense(r, SDcheck, 4, 8, 0);
1653         }
1654         c = r->cmd;
1655         if(r->ataproto & P28){
1656                 e->altstat = ATAeIEN;
1657                 e->seccnt = c[Fsc];
1658                 e->err = c[Ffeat];
1659                 e->lba0 = c[Flba0];
1660                 e->lba1 = c[Flba8];
1661                 e->lba2 = c[Flba16];
1662                 e->lba3 = c[Fdev];
1663                 e->cmdstat = c[Fcmd];
1664         }else{
1665                 e->altstat = ATAeIEN;
1666                 e->seccnt = c[Fsc8];
1667                 e->seccnt = c[Fsc];
1668                 e->err = c[Ffeat];
1669                 e->lba0 = c[Flba24];
1670                 e->lba0 = c[Flba0];
1671                 e->lba1 = c[Flba32];
1672                 e->lba1 = c[Flba8];
1673                 e->lba1 = c[Flba40];
1674                 e->lba2 = c[Flba16];
1675                 e->lba3 = c[Fdev];
1676                 e->cmdstat = c[Fcmd];
1677         }
1678         err = 0;
1679
1680         if((r->ataproto & Pdatam) == Pnd)
1681                 n = satawait(&e->cmdstat, ATAbusy, 0, 3*1000);
1682         else
1683                 n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 3*1000);
1684         if(n == 0 || e->cmdstat & ATAerr){
1685                 err = 1;
1686                 goto lose;
1687         }
1688         p = r->data;
1689         for(; nsec > 0; nsec--)
1690                 for (i = 0; i < u->secsize; i += 2) {
1691                         n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 300);
1692                         if (n == 0) {
1693                                 d->state = Dreset;
1694                                 err = 1;
1695                                 goto lose;
1696                         }
1697                         if(r->ataproto & Pout){
1698                                 n = (ushort)p[i + 1] << 8;
1699                                 e->pio = n | p[i];
1700                         } else {
1701                                 n = e->pio;
1702                                 p[i] = n;
1703                                 p[i + 1] = n >> 8;
1704                         }
1705                         microdelay(1);
1706                 }
1707 lose:
1708         if(nsec == 0)
1709                 r->rlen = r->dlen;
1710         mkrfis(r, d, e);
1711         iunlock(d);
1712         if(err)
1713                 return sdsetsense(r, SDcheck, 4, 8, 0);
1714         else
1715                 return sdsetsense(r, SDok, 0, 0, 0);
1716 }
1717
1718 /*
1719  * hack to allow udma mode to be set or unset
1720  * via direct ata command.  it would be better
1721  * to move the assumptions about dma mode out
1722  * of some of the helper functions.
1723  */
1724 static int
1725 isudm(SDreq *r)
1726 {
1727         uchar *c;
1728
1729         c = r->cmd;
1730         if(c[Fcmd] == 0xef && c[Ffeat] == 0x03){
1731                 if(c[Fsc]&0x40)
1732                         return 1;
1733                 return -1;
1734         }
1735         return 0;
1736 }
1737 static int
1738 fisreqchk(Sfis *f, SDreq *r)
1739 {
1740         if((r->ataproto & Pprotom) == Ppkt)
1741                 return SDnostatus;
1742         /*
1743          * handle oob requests;
1744          *    restrict & sanitize commands
1745          */
1746         if(r->clen != 16)
1747                 error(Eio);
1748         if(r->cmd[0] == 0xf0){
1749                 sigtofis(f, r->cmd);
1750                 r->status = SDok;
1751                 return SDok;
1752         }
1753         r->cmd[0] = 0x27;
1754         r->cmd[1] = 0x80;
1755         r->cmd[7] |= 0xa0;
1756         return SDnostatus;
1757 }
1758
1759 static int
1760 badf(SDreq *r, Drive*)
1761 {
1762 print("badf %.2ux %2ux\n", r->cmd[2], r->ataproto);
1763         return sdsetsense(r, SDcheck, 2, 24, 0);
1764 }
1765
1766 static int
1767 ataio0(SDreq *r, Drive *d)
1768 {
1769         int (*f)(SDreq*, Drive*);
1770
1771         f = badf;
1772         switch(r->ataproto & Pprotom){
1773         default:
1774                 break;
1775         case Ppio:
1776         case Pnd:
1777                 f = piocmd;
1778                 break;
1779         }
1780         return f(r, d);
1781 }
1782
1783 static int
1784 mv50ata(SDreq *r)
1785 {
1786         int status, udm;
1787         Ctlr *c;
1788         Drive *d;
1789         SDunit *u;
1790
1791         u = r->unit;
1792         c = u->dev->ctlr;
1793         d = c->drive + u->subno;
1794         if((status = fisreqchk(d, r)) != SDnostatus)
1795                 return status;
1796         udm = isudm(r);
1797         USED(udm);              /* botch */
1798
1799 //      qlock(d);
1800         if(waserror()){
1801 //              qunlock(d);
1802                 nexterror();
1803         }
1804 retry:
1805         switch(status = ataio0(r, d)){
1806         default:
1807                 dprint("%s: status %d\n", dnam(d), status);
1808                 break;
1809         case SDretry:
1810                 dprint("%s: retry\n", dnam(d));
1811                 goto retry;
1812         case SDok:
1813                 sdsetsense(r, SDok, 0, 0, 0);
1814                 break;
1815         }
1816         poperror();
1817 //      qunlock(d);
1818         return r->status = status;
1819 }
1820
1821
1822 SDifc sdmv50xxifc = {
1823         "mv50xx",                       /* name */
1824
1825         mv50pnp,                        /* pnp */
1826         nil,                            /* legacy */
1827         mv50enable,                     /* enable */
1828         mv50disable,                    /* disable */
1829
1830         mv50verify,                     /* verify */
1831         mv50online,                     /* online */
1832         mv50rio,                                /* rio */
1833         mv50rctl,                               /* rctl */
1834         mv50wctl,                       /* wctl */
1835
1836         mv50bio,                                /* bio */
1837         nil,                            /* probe */
1838         nil,                            /* clear */
1839         nil,                            /* rtopctl */
1840         nil,
1841         mv50ata,
1842 };
1843
1844 /*
1845  * The original driver on which this one is based came with the
1846  * following notice:
1847  *
1848  * Copyright 2005
1849  * Coraid, Inc.
1850  *
1851  * This software is provided `as-is,' without any express or implied
1852  * warranty.  In no event will the author be held liable for any damages
1853  * arising from the use of this software.
1854  *
1855  * Permission is granted to anyone to use this software for any purpose,
1856  * including commercial applications, and to alter it and redistribute it
1857  * freely, subject to the following restrictions:
1858  *
1859  * 1.  The origin of this software must not be misrepresented; you must
1860  * not claim that you wrote the original software.  If you use this
1861  * software in a product, an acknowledgment in the product documentation
1862  * would be appreciated but is not required.
1863  *
1864  * 2.  Altered source versions must be plainly marked as such, and must
1865  * not be misrepresented as being the original software.
1866  *
1867  * 3.  This notice may not be removed or altered from any source
1868  * distribution.
1869  */