FreeBSD/Linux Kernel Cross Reference
sys/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 */
Cache object: bfbe01960659951d284f7b3cfdeec898
|