xref: /plan9-contrib/sys/src/9/pc/sdmv50xx.c (revision ea58ad6fbee60d5a3fca57ac646881779dd8f0ea)
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
lhgets(void * p)367 lhgets(void *p)
368 {
369 	uchar *a = p;
370 	return ((ushort) a[1] << 8) | a[0];
371 }
372 
373 static ulong
lhgetl(void * p)374 lhgetl(void *p)
375 {
376 	uchar *a = p;
377 	return ((ulong) lhgets(a+2) << 16) | lhgets(a);
378 }
379 
380 static uvlong
lhgetv(void * p)381 lhgetv(void *p)
382 {
383 	uchar *a = p;
384 	return ((uvlong) lhgetl(a+4) << 32) | lhgetl(a);
385 }
386 
387 static void
idmove(char * p,ushort * a,int n)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*
allocsrb(void)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
freesrb(Srb * p)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
satawait(uchar * p,uchar mask,uchar v,int ms)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
unmask(ulong * mmio,int port,int coal)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
mask(ulong * mmio,int port,int coal)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
phyerrata(Drive * d)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
edmacleanout(Drive * d)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
resetdisk(Drive * d)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
edmainit(Drive * d)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
configdrive(Ctlr * ctlr,Drive * d,SDunit * unit)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
enabledrive(Drive * d)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
disabledrive(Drive * d)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
setudmamode(Drive * d,uchar mode)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
identifydrive(Drive * d)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
serrdecode(ulong r,char * s,char * e)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*
iecdecode(ulong cause)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
updatedrive(Drive * d)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*
srbrw(int req,Drive * d,uchar * data,uint sectors,uvlong lba)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
advance(uintptr pa,int shift)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
mvsatarequest(ushort * cmd,Srb * srb,int ext)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
startsrb(Drive * d,Srb * srb)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
completesrb(Drive * d)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
srbdone(void * v)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
mv50interrupt(Ureg *,void * a)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
westerndigitalhung(Drive * d)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
checkdrive(Drive * d,int i)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
satakproc(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*
mv50pnp(void)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
mv50enable(SDev * sdev)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
mv50disable(SDev * sdev)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
mv50clear(SDev * sdev)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
mv50verify(SDunit * unit)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
mv50online(SDunit * unit)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*
rdregs(char * p,char * e,void * base,Regs * r,int n,char * prefix)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*
rdinfo(char * p,char * e,ushort * info)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
mv50rctl(SDunit * unit,char * p,int l)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
mv50wctl(SDunit * unit,Cmdbuf * cb)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*
mv50rtopctl(SDev * sdev,char * p,char * e)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
waitready(Drive * d)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
mv50rio(SDreq * r)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  */
1763