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