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