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