Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/9/pc/sdmv50xx.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 */