Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Mylex MultiMaster (Buslogic BT-*) SCSI Host Adapter
3
 * in both 24-bit and 32-bit mode.
4
 * 24-bit mode works for Adaptec AHA-154xx series too.
5
 *
6
 * To do:
7
 *	allocate more Ccb's as needed, up to NMbox-1;
8
 *	add nmbox and nccb to Ctlr struct for the above;
9
 *	64-bit LUN/explicit wide support necessary?
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 "ureg.h"
19
#include "../port/error.h"
20
 
21
#include "../port/sd.h"
22
 
23
#define K2BPA(va, tbdf)	PADDR(va)
24
#define BPA2K(pa, tbdf)	KADDR(pa)
25
 
26
extern SDifc sdmylexifc;
27
 
28
enum {					/* registers */
29
	Rcontrol	= 0x00,		/* WO: control register */
30
	Rstatus		= 0x00,		/* RO: status register */
31
	Rcpr		= 0x01,		/* WO: command/parameter register */
32
	Rdatain		= 0x01,		/* RO: data-in register */
33
	Rinterrupt	= 0x02,		/* RO: interrupt register */
34
};
35
 
36
enum {					/* Rcontrol */
37
	Rsbus		= 0x10,		/* SCSI Bus Reset */
38
	Rint		= 0x20,		/* Interrupt Reset */
39
	Rsoft		= 0x40,		/* Soft Reset */
40
	Rhard		= 0x80,		/* Hard Reset */
41
};
42
 
43
enum {					/* Rstatus */
44
	Cmdinv		= 0x01,		/* Command Invalid */
45
	Dirrdy		= 0x04,		/* Data In Register Ready */
46
	Cprbsy		= 0x08,		/* Command/Parameter Register Busy */
47
	Hardy		= 0x10,		/* Host Adapter Ready */
48
	Inreq		= 0x20,		/* Initialisation Required */
49
	Dfail		= 0x40,		/* Diagnostic Failure */
50
	Dact		= 0x80,		/* Diagnostic Active */
51
};
52
 
53
enum {					/* Rcpr */
54
	Cinitialise	= 0x01,		/* Initialise Mailbox */
55
	Cstart		= 0x02,		/* Start Mailbox Command */
56
	Cinquiry	= 0x04,		/* Adapter Inquiry */
57
	Ceombri		= 0x05,		/* Enable OMBR Interrupt */
58
	Cinquire	= 0x0B,		/* Inquire Configuration */
59
	Cextbios	= 0x28,		/* AHA-1542: extended BIOS info. */
60
	Cmbienable	= 0x29,		/* AHA-1542: Mailbox interface enable */
61
	Ciem		= 0x81,		/* Initialise Extended Mailbox */
62
	Ciesi		= 0x8D,		/* Inquire Extended Setup Information */
63
	Cerrm		= 0x8F,		/* Enable strict round-robin mode */
64
	Cwide		= 0x96,		/* Wide CCB */
65
};
66
 
67
enum {					/* Rinterrupt */
68
	Imbl		= 0x01,		/* Incoming Mailbox Loaded */
69
	Mbor		= 0x02,		/* Mailbox Out Ready */
70
	Cmdc		= 0x04,		/* Command Complete */
71
	Rsts		= 0x08,		/* SCSI Reset State */
72
	Intv		= 0x80,		/* Interrupt Valid */
73
};
74
 
75
typedef struct Mbox24 Mbox24;
76
struct Mbox24 {
77
	uchar	code;			/* action/completion code */
78
	uchar	ccb[3];			/* CCB pointer (MSB, ..., LSB) */
79
};
80
 
81
typedef struct Mbox32 Mbox32;
82
struct Mbox32 {
83
	uchar	ccb[4];			/* CCB pointer (LSB, ..., MSB) */
84
	uchar	btstat;			/* BT-7[45]7[SD] status */
85
	uchar	sdstat;			/* SCSI device status */
86
	uchar	pad;
87
	uchar	code;			/* action/completion code */
88
};
89
 
90
enum {					/* mailbox commands */
91
	Mbfree		= 0x00,		/* Mailbox not in use */
92
 
93
	Mbostart	= 0x01,		/* Start a mailbox command */
94
	Mboabort	= 0x02,		/* Abort a mailbox command */
95
 
96
	Mbiok		= 0x01,		/* CCB completed without error */
97
	Mbiabort	= 0x02,		/* CCB aborted at request of host */
98
	Mbinx		= 0x03,		/* Aborted CCB not found */
99
	Mbierror	= 0x04,		/* CCB completed with error */
100
};
101
 
102
typedef struct Ccb24 Ccb24;
103
typedef struct Ccb32 Ccb32;
104
typedef union Ccb Ccb;
105
 
106
typedef struct Ccb24 {
107
	uchar	opcode;			/* Operation code */
108
	uchar	datadir;		/* Data direction control */
109
	uchar	cdblen;			/* Length of CDB */
110
	uchar	senselen;		/* Length of sense area */
111
	uchar	datalen[3];		/* Data length (MSB, ..., LSB) */
112
	uchar	dataptr[3];		/* Data pointer (MSB, ..., LSB) */
113
	uchar	linkptr[3];		/* Link pointer (MSB, ..., LSB) */
114
	uchar	linkid;			/* command linking identifier */
115
	uchar	btstat;			/* BT-* adapter status */
116
	uchar	sdstat;			/* SCSI device status */
117
	uchar	reserved[2];		/* */
118
	uchar	cs[12+0xFF];		/* Command descriptor block + Sense */
119
 
120
	void*	data;			/* buffer if address > 24-bits */
121
 
122
	Rendez;
123
	int	done;			/* command completed */
124
 
125
	Ccb*	ccb;			/* link on free list */
126
} Ccb24;
127
 
128
 
129
typedef struct Ccb32 {
130
	uchar	opcode;			/* Operation code */
131
	uchar	datadir;		/* Data direction control */
132
	uchar	cdblen;			/* Length of CDB */
133
	uchar	senselen;		/* Length of sense area */
134
	uchar	datalen[4];		/* Data length (LSB, ..., MSB) */
135
	uchar	dataptr[4];		/* Data pointer (LSB, ..., MSB) */
136
	uchar	reserved[2];
137
	uchar	btstat;			/* BT-* adapter status */
138
	uchar	sdstat;			/* SCSI device status */
139
	uchar	targetid;		/* Target ID */
140
	uchar	luntag;			/* LUN & tag */
141
	uchar	cdb[12];		/* Command descriptor block */
142
	uchar	ccbctl;			/* CCB control */
143
	uchar	linkid;			/* command linking identifier */
144
	uchar	linkptr[4];		/* Link pointer (LSB, ..., MSB) */
145
	uchar	senseptr[4];		/* Sense pointer (LSB, ..., MSB) */
146
	uchar	sense[0xFF];		/* Sense bytes */
147
 
148
	Rendez;
149
	int	done;			/* command completed */
150
 
151
	Ccb*	ccb;			/* link on free list */
152
} Ccb32;
153
 
154
typedef union Ccb {
155
	Ccb24;
156
	Ccb32;
157
} Ccb;
158
 
159
enum {					/* opcode */
160
	OInitiator	= 0x00,		/* initiator CCB */
161
	Ordl		= 0x03,		/* initiator CCB with
162
					 * residual data length returned
163
					 */
164
};
165
 
166
enum {					/* datadir */
167
	CCBdatain	= 0x08,		/* inbound, length is checked */
168
	CCBdataout	= 0x10,		/* outbound, length is checked */
169
};
170
 
171
enum {					/* btstat */
172
	Eok		= 0x00,		/* normal completion with no errors */
173
};
174
 
175
enum {					/* luntag */
176
	TagEnable	= 0x20,		/* Tag enable */
177
	SQTag		= 0x00,		/* Simple Queue Tag */
178
	HQTag		= 0x40,		/* Head of Queue Tag */
179
	OQTag		= 0x80,		/* Ordered Queue Tag */
180
};
181
 
182
enum {					/* CCB control */
183
	NoDisc		= 0x08,		/* No disconnect */
184
	NoUnd		= 0x10,		/* No underrrun error report */
185
	NoData		= 0x20,		/* No data transfer */
186
	NoStat		= 0x40,		/* No CCB status if zero */
187
	NoIntr		= 0x80,		/* No Interrupts */
188
};
189
 
190
typedef struct Ctlr Ctlr;
191
struct Ctlr {
192
	int	port;			/* I/O port */
193
	int	id;			/* adapter SCSI id */
194
	int	bus;			/* 24 or 32 -bit */
195
	int	irq;
196
	int	wide;
197
	Pcidev*	pcidev;
198
	SDev*	sdev;
199
	int	spurious;
200
 
201
	Lock	issuelock;
202
 
203
	Lock	ccblock;
204
	QLock	ccbq;
205
	Rendez	ccbr;
206
 
207
	Lock	mboxlock;
208
	void*	mb;			/* mailbox out + mailbox in */
209
	int	mbox;			/* current mailbox out index into mb */
210
	int	mbix;			/* current mailbox in index into mb */
211
 
212
	Lock	cachelock;
213
	Ccb*	ccb;			/* list of free Ccb's */
214
	Ccb**	cache;			/* last completed Ccb */
215
};
216
 
217
/*
218
 * The number of mailboxes should be a multiple of 8 (4 for Mbox32)
219
 * to ensure the boundary between the out and in mailboxes doesn't
220
 * straddle a cache-line boundary.
221
 * The number of Ccb's should be less than the number of mailboxes to
222
 * ensure no queueing is necessary on mailbox allocation.
223
 */
224
enum {
225
	NMbox		= 8*8,		/* number of Mbox's */
226
	NCcb		= NMbox-1,	/* number of Ccb's */
227
};
228
 
229
#define PADDR24(a, n)	((PADDR(a)+(n)) <= (1<<24))
230
 
231
static void
232
ccbfree(Ctlr* ctlr, Ccb* ccb)
233
{
234
	lock(&ctlr->ccblock);
235
	if(ctlr->bus == 24)
236
		((Ccb24*)ccb)->ccb = ctlr->ccb;
237
	else
238
		((Ccb32*)ccb)->ccb = ctlr->ccb;
239
	if(ctlr->ccb == nil)
240
		wakeup(&ctlr->ccbr);
241
	ctlr->ccb = ccb;
242
	unlock(&ctlr->ccblock);
243
}
244
 
245
static int
246
ccbavailable(void* a)
247
{
248
	return ((Ctlr*)a)->ccb != nil;
249
}
250
 
251
static Ccb*
252
ccballoc(Ctlr* ctlr)
253
{
254
	Ccb *ccb;
255
 
256
	for(;;){
257
		lock(&ctlr->ccblock);
258
		if((ccb = ctlr->ccb) != nil){
259
			if(ctlr->bus == 24)
260
				 ctlr->ccb = ((Ccb24*)ccb)->ccb;
261
			else
262
				 ctlr->ccb = ((Ccb32*)ccb)->ccb;
263
			unlock(&ctlr->ccblock);
264
			break;
265
		}
266
 
267
		unlock(&ctlr->ccblock);
268
		qlock(&ctlr->ccbq);
269
		if(waserror()){
270
			qunlock(&ctlr->ccbq);
271
			continue;
272
		}
273
		sleep(&ctlr->ccbr, ccbavailable, ctlr);
274
		qunlock(&ctlr->ccbq);
275
		poperror();
276
	}
277
 
278
	return ccb;
279
}
280
 
281
static int
282
done24(void* arg)
283
{
284
	return ((Ccb24*)arg)->done;
285
}
286
 
287
static int
288
mylex24rio(SDreq* r)
289
{
290
	ulong p;
291
	Ctlr *ctlr;
292
	Ccb24 *ccb;
293
	Mbox24 *mb;
294
	uchar *data, lun, *sense;
295
	int d, n, btstat, sdstat, target;
296
 
297
	ctlr = r->unit->dev->ctlr;
298
	target = r->unit->subno;
299
	lun = (r->cmd[1]>>5) & 0x07;
300
 
301
	/*
302
	 * Ctlr->cache holds the last completed Ccb for this target if it
303
	 * returned 'check condition'.
304
	 * If this command is a request-sense and there is valid sense data
305
	 * from the last completed Ccb, return it immediately.
306
	 */
307
	lock(&ctlr->cachelock);
308
	if((ccb = ctlr->cache[target]) != nil){
309
		ctlr->cache[target] = nil;
310
		if(r->cmd[0] == 0x03
311
		&& ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){
312
			unlock(&ctlr->cachelock);
313
			if(r->dlen){
314
				sense = &ccb->cs[ccb->cdblen];
315
				n = 8+sense[7];
316
				if(n > r->dlen)
317
					n = r->dlen;
318
				memmove(r->data, sense, n);
319
				r->rlen = n;
320
			}
321
			ccbfree(ctlr, (Ccb*)ccb);
322
			return SDok;
323
		}
324
	}
325
	unlock(&ctlr->cachelock);
326
	if(ccb == nil)
327
		ccb = ccballoc(ctlr);
328
 
329
	/*
330
	 * Check if the transfer is to memory above the 24-bit limit the
331
	 * controller can address. If it is, try to allocate a temporary
332
	 * buffer as a staging area.
333
	 */
334
	n = r->dlen;
335
	if(n && !PADDR24(r->data, n)){
336
		data = mallocz(n, 0);
337
		if(data == nil || !PADDR24(data, n)){
338
			if(data != nil){
339
				free(data);
340
				ccb->data = nil;
341
			}
342
			ccbfree(ctlr, (Ccb*)ccb);
343
			return SDmalloc;
344
		}
345
		if(r->write)
346
			memmove(data, r->data, n);
347
		ccb->data = r->data;
348
	}
349
	else
350
		data = r->data;
351
 
352
	/*
353
	 * Fill in the ccb.
354
	 */
355
	ccb->opcode = Ordl;
356
 
357
	ccb->datadir = (target<<5)|lun;
358
	if(n == 0)
359
		ccb->datadir |= CCBdataout|CCBdatain;
360
	else if(!r->write)
361
		ccb->datadir |= CCBdatain;
362
	else
363
		ccb->datadir |= CCBdataout;
364
 
365
	ccb->cdblen = r->clen;
366
	ccb->senselen = 0xFF;
367
 
368
	ccb->datalen[0] = n>>16;
369
	ccb->datalen[1] = n>>8;
370
	ccb->datalen[2] = n;
371
	if(data == nil)
372
		p = 0;
373
	else
374
		p = PADDR(data);
375
	ccb->dataptr[0] = p>>16;
376
	ccb->dataptr[1] = p>>8;
377
	ccb->dataptr[2] = p;
378
 
379
	ccb->linkptr[0] = ccb->linkptr[1] = ccb->linkptr[2] = 0;
380
	ccb->linkid = 0;
381
	ccb->btstat = ccb->sdstat = 0;
382
	ccb->reserved[0] = ccb->reserved[1] = 0;
383
 
384
	memmove(ccb->cs, r->cmd, r->clen);
385
 
386
	/*
387
	 * There's one more mbox than there there is
388
	 * ccb so there is always one free.
389
	 */
390
	lock(&ctlr->mboxlock);
391
	mb = ctlr->mb;
392
	mb += ctlr->mbox;
393
	p = PADDR(ccb);
394
	mb->ccb[0] = p>>16;
395
	mb->ccb[1] = p>>8;
396
	mb->ccb[2] = p;
397
	mb->code = Mbostart;
398
	ctlr->mbox++;
399
	if(ctlr->mbox >= NMbox)
400
		ctlr->mbox = 0;
401
 
402
	/*
403
	 * This command does not require Hardy
404
	 * and doesn't generate a Cmdc interrupt.
405
	 */
406
	ccb->done = 0;
407
	outb(ctlr->port+Rcpr, Cstart);
408
	unlock(&ctlr->mboxlock);
409
 
410
	/*
411
	 * Wait for the request to complete and return the status.
412
	 * Since the buffer is not reference counted cannot return
413
	 * until the DMA is done writing into the buffer so the caller
414
	 * cannot free the buffer prematurely.
415
	 */
416
	while(waserror())
417
		;
418
	sleep(ccb, done24, ccb);
419
	poperror();
420
 
421
	/*
422
	 * Save the status and patch up the number of
423
	 * bytes actually transferred.
424
	 * There's a firmware bug on some 956C controllers
425
	 * which causes the return count from a successful
426
	 * READ CAPACITY not be updated, so fix it here.
427
	 */
428
	sdstat = ccb->sdstat;
429
	btstat = ccb->btstat;
430
 
431
	d = ccb->datalen[0]<<16;
432
	d |= ccb->datalen[1]<<8;
433
	d |= ccb->datalen[2];
434
	if(ccb->cs[0] == 0x25 && sdstat == SDok)
435
		d = 0;
436
	n -= d;
437
	r->rlen = n;
438
 
439
	/*
440
	 * Tidy things up if a staging area was used for the data,
441
	 */
442
	if(ccb->data != nil){
443
		if(sdstat == SDok && btstat == 0 && !r->write)
444
			memmove(ccb->data, data, n);
445
		free(data);
446
		ccb->data = nil;
447
	}
448
 
449
	/*
450
	 * If there was a check-condition, save the
451
	 * ccb for a possible request-sense command.
452
	 */
453
	if(sdstat == SDcheck){
454
		if(r->flags & SDnosense){
455
			lock(&ctlr->cachelock);
456
			if(ctlr->cache[target])
457
				ccbfree(ctlr, ctlr->cache[target]);
458
			ctlr->cache[target] = (Ccb*)ccb;
459
			unlock(&ctlr->cachelock);
460
			return SDcheck;
461
		}
462
		sense = &ccb->cs[ccb->cdblen];
463
		n = 8+sense[7];
464
		if(n > sizeof(r->sense)-1)
465
			n = sizeof(r->sense)-1;
466
		memmove(r->sense, sense, n);
467
		r->flags |= SDvalidsense;
468
	}
469
	ccbfree(ctlr, (Ccb*)ccb);
470
 
471
	if(btstat){
472
		if(btstat == 0x11)
473
			return SDtimeout;
474
		return SDeio;
475
	}
476
	return sdstat;
477
}
478
 
479
static void
480
mylex24interrupt(Ureg*, void* arg)
481
{
482
	ulong pa;
483
	Ctlr *ctlr;
484
	Ccb24 *ccb;
485
	Mbox24 *mb, *mbox;
486
	int port, rinterrupt, rstatus;
487
 
488
	ctlr = arg;
489
	port = ctlr->port;
490
 
491
	/*
492
	 * Save and clear the interrupt(s). The only
493
	 * interrupts expected are Cmdc, which is ignored,
494
	 * and Imbl which means something completed.
495
	 * There's one spurious interrupt left over from
496
	 * initialisation, ignore it.
497
	 */
498
	rinterrupt = inb(port+Rinterrupt);
499
	rstatus = inb(port+Rstatus);
500
	outb(port+Rcontrol, Rint);
501
	if((rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
502
		print("%s: interrupt 0x%2.2ux\n",
503
			ctlr->sdev->name, rinterrupt);
504
	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
505
		print("%s: command invalid\n", ctlr->sdev->name);
506
 
507
	/*
508
	 * Look for something in the mail.
509
	 * If there is, save the status, free the mailbox
510
	 * and wakeup whoever.
511
	 */
512
	mb = ctlr->mb;
513
	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
514
		pa = (mbox->ccb[0]<<16)|(mbox->ccb[1]<<8)|mbox->ccb[2];
515
		ccb = BPA2K(pa, BUSUNKNOWN);
516
		mbox->code = 0;
517
		ccb->done = 1;
518
		wakeup(ccb);
519
 
520
		ctlr->mbix++;
521
		if(ctlr->mbix >= NMbox+NMbox)
522
			ctlr->mbix = NMbox;
523
	}
524
}
525
 
526
static int
527
done32(void* arg)
528
{
529
	return ((Ccb32*)arg)->done;
530
}
531
 
532
static int
533
mylex32rio(SDreq* r)
534
{
535
	ulong p;
536
	uchar lun;
537
	Ctlr *ctlr;
538
	Ccb32 *ccb;
539
	Mbox32 *mb;
540
	int d, n, btstat, sdstat, target;
541
 
542
	ctlr = r->unit->dev->ctlr;
543
	target = r->unit->subno;
544
	lun = (r->cmd[1]>>5) & 0x07;
545
 
546
	/*
547
	 * Ctlr->cache holds the last completed Ccb for this target if it
548
	 * returned 'check condition'.
549
	 * If this command is a request-sense and there is valid sense data
550
	 * from the last completed Ccb, return it immediately.
551
	 */
552
	lock(&ctlr->cachelock);
553
	if((ccb = ctlr->cache[target]) != nil){
554
		ctlr->cache[target] = nil;
555
		if(r->cmd[0] == 0x03
556
		&& ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){
557
			unlock(&ctlr->cachelock);
558
			if(r->dlen){
559
				n = 8+ccb->sense[7];
560
				if(n > r->dlen)
561
					n = r->dlen;
562
				memmove(r->data, ccb->sense, n);
563
				r->rlen = n;
564
			}
565
			ccbfree(ctlr, (Ccb*)ccb);
566
			return SDok;
567
		}
568
	}
569
	unlock(&ctlr->cachelock);
570
	if(ccb == nil)
571
		ccb = ccballoc(ctlr);
572
 
573
	/*
574
	 * Fill in the ccb.
575
	 */
576
	ccb->opcode = Ordl;
577
 
578
	n = r->dlen;
579
	if(n == 0)
580
		ccb->datadir = CCBdataout|CCBdatain;
581
	else if(!r->write)
582
		ccb->datadir = CCBdatain;
583
	else
584
		ccb->datadir = CCBdataout;
585
 
586
	ccb->cdblen = r->clen;
587
 
588
	ccb->datalen[0] = n;
589
	ccb->datalen[1] = n>>8;
590
	ccb->datalen[2] = n>>16;
591
	ccb->datalen[3] = n>>24;
592
	if(r->data == nil)
593
		p = 0;
594
	else
595
		p = PADDR(r->data);
596
	ccb->dataptr[0] = p;
597
	ccb->dataptr[1] = p>>8;
598
	ccb->dataptr[2] = p>>16;
599
	ccb->dataptr[3] = p>>24;
600
 
601
	ccb->targetid = target;
602
	ccb->luntag = lun;
603
	if(r->unit->inquiry[7] & 0x02)
604
		if(ctlr->wide)
605
			ccb->datadir |= SQTag|TagEnable;
606
		else
607
			ccb->luntag |= SQTag|TagEnable;
608
	memmove(ccb->cdb, r->cmd, r->clen);
609
	ccb->btstat = ccb->sdstat = 0;
610
	ccb->ccbctl = 0;
611
 
612
	/*
613
	 * There's one more mbox than there there is
614
	 * ccb so there is always one free.
615
	 */
616
	lock(&ctlr->mboxlock);
617
	mb = ctlr->mb;
618
	mb += ctlr->mbox;
619
	p = PADDR(ccb);
620
	mb->ccb[0] = p;
621
	mb->ccb[1] = p>>8;
622
	mb->ccb[2] = p>>16;
623
	mb->ccb[3] = p>>24;
624
	mb->code = Mbostart;
625
	ctlr->mbox++;
626
	if(ctlr->mbox >= NMbox)
627
		ctlr->mbox = 0;
628
 
629
	/*
630
	 * This command does not require Hardy
631
	 * and doesn't generate a Cmdc interrupt.
632
	 */
633
	ccb->done = 0;
634
	outb(ctlr->port+Rcpr, Cstart);
635
	unlock(&ctlr->mboxlock);
636
 
637
	/*
638
	 * Wait for the request to complete and return the status.
639
	 * Since the buffer is not reference counted cannot return
640
	 * until the DMA is done writing into the buffer so the caller
641
	 * cannot free the buffer prematurely.
642
	 */
643
	while(waserror())
644
		;
645
	sleep(ccb, done32, ccb);
646
	poperror();
647
 
648
	/*
649
	 * Save the status and patch up the number of
650
	 * bytes actually transferred.
651
	 * There's a firmware bug on some 956C controllers
652
	 * which causes the return count from a successful
653
	 * READ CAPACITY not to be updated, so fix it here.
654
	 */
655
	sdstat = ccb->sdstat;
656
	btstat = ccb->btstat;
657
 
658
	d = ccb->datalen[0];
659
	d |= (ccb->datalen[1]<<8);
660
	d |= (ccb->datalen[2]<<16);
661
	d |= (ccb->datalen[3]<<24);
662
	if(ccb->cdb[0] == 0x25 && sdstat == SDok)
663
		d = 0;
664
	n -= d;
665
	r->rlen = n;
666
 
667
	/*
668
	 * If there was a check-condition, save the
669
	 * ccb for a possible request-sense command.
670
	 */
671
	if(sdstat == SDcheck){
672
		if(r->flags & SDnosense){
673
			lock(&ctlr->cachelock);
674
			if(ctlr->cache[target])
675
				ccbfree(ctlr, ctlr->cache[target]);
676
			ctlr->cache[target] = (Ccb*)ccb;
677
			unlock(&ctlr->cachelock);
678
			return SDcheck;
679
		}
680
		n = 8+ccb->sense[7];
681
		if(n > sizeof(r->sense)-1)
682
			n = sizeof(r->sense)-1;
683
		memmove(r->sense, ccb->sense, n);
684
		r->flags |= SDvalidsense;
685
	}
686
	ccbfree(ctlr, (Ccb*)ccb);
687
 
688
	if(btstat){
689
		if(btstat == 0x11)
690
			return SDtimeout;
691
		return SDeio;
692
	}
693
	return sdstat;
694
}
695
 
696
static void
697
mylex32interrupt(Ureg*, void* arg)
698
{
699
	ulong pa;
700
	Ctlr *ctlr;
701
	Ccb32 *ccb;
702
	Mbox32 *mb, *mbox;
703
	int port, rinterrupt, rstatus;
704
 
705
	ctlr = arg;
706
	port = ctlr->port;
707
 
708
	/*
709
	 * Save and clear the interrupt(s). The only
710
	 * interrupts expected are Cmdc, which is ignored,
711
	 * and Imbl which means something completed.
712
	 * There's one spurious interrupt left over from
713
	 * initialisation, ignore it.
714
	 * In order to share PCI IRQs, just ignore spurious interrupts.
715
	 */
716
	rinterrupt = inb(port+Rinterrupt);
717
	rstatus = inb(port+Rstatus);
718
	outb(port+Rcontrol, Rint);
719
	if(0 && (rinterrupt & ~(Cmdc|Imbl)) != Intv && ctlr->spurious++)
720
		print("%s: interrupt 0x%2.2ux\n",
721
			ctlr->sdev->name, rinterrupt);
722
	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
723
		print("%s: command invalid\n", ctlr->sdev->name);
724
 
725
	/*
726
	 * Look for something in the mail.
727
	 * If there is, free the mailbox and wakeup whoever.
728
	 */
729
	mb = ctlr->mb;
730
	for(mbox = &mb[ctlr->mbix]; mbox->code; mbox = &mb[ctlr->mbix]){
731
		pa = (mbox->ccb[3]<<24)
732
		    |(mbox->ccb[2]<<16)
733
		    |(mbox->ccb[1]<<8)
734
		    |mbox->ccb[0];
735
		if(ctlr->pcidev)
736
			ccb = BPA2K(pa, ctlr->pcidev->tbdf);
737
		else
738
			ccb = BPA2K(pa, BUSUNKNOWN);
739
		mbox->code = 0;
740
		ccb->done = 1;
741
		wakeup(ccb);
742
 
743
		ctlr->mbix++;
744
		if(ctlr->mbix >= NMbox+NMbox)
745
			ctlr->mbix = NMbox;
746
	}
747
}
748
 
749
static int
750
mylexrio(SDreq* r)
751
{
752
	int subno;
753
	Ctlr *ctlr;
754
 
755
	subno = r->unit->subno;
756
	ctlr = r->unit->dev->ctlr;
757
	if(subno == ctlr->id || (!ctlr->wide && subno >= 8))
758
		r->status = SDtimeout;
759
	else if(ctlr->bus == 24)
760
		r->status = mylex24rio(r);
761
	else
762
		r->status = mylex32rio(r);
763
	return r->status;
764
}
765
 
766
/*
767
 * Issue a command to a controller. The command and its length is
768
 * contained in cmd and cmdlen. If any data is to be
769
 * returned, datalen should be non-zero, and the returned data
770
 * will be placed in data.
771
 * If Cmdc is set, bail out, the invalid command will be handled
772
 * when the interrupt is processed.
773
 */
774
static void
775
issueio(int port, uchar* cmd, int cmdlen, uchar* data, int datalen)
776
{
777
	int len;
778
 
779
	if(cmd[0] != Cstart && cmd[0] != Ceombri){
780
		while(!(inb(port+Rstatus) & Hardy))
781
			;
782
	}
783
	outb(port+Rcpr, cmd[0]);
784
 
785
	len = 1;
786
	while(len < cmdlen){
787
		if(!(inb(port+Rstatus) & Cprbsy)){
788
			outb(port+Rcpr, cmd[len]);
789
			len++;
790
		}
791
		if(inb(port+Rinterrupt) & Cmdc)
792
			return;
793
	}
794
 
795
	if(datalen){
796
		len = 0;
797
		while(len < datalen){
798
			if(inb(port+Rstatus) & Dirrdy){
799
				data[len] = inb(port+Rdatain);
800
				len++;
801
			}
802
			if(inb(port+Rinterrupt) & Cmdc)
803
				return;
804
		}
805
	}
806
}
807
 
808
/*
809
 * Issue a command to a controller, wait for it to complete then
810
 * try to reset the interrupt. Should only be called at initialisation.
811
 */
812
static int
813
issue(Ctlr* ctlr, uchar* cmd, int cmdlen, uchar* data, int datalen)
814
{
815
	int port;
816
	uchar rinterrupt, rstatus;
817
	static Lock mylexissuelock;
818
 
819
	port = ctlr->port;
820
 
821
	ilock(&ctlr->issuelock);
822
	issueio(port, cmd, cmdlen, data, datalen);
823
 
824
	while(!((rinterrupt = inb(port+Rinterrupt)) & Cmdc))
825
		;
826
 
827
	rstatus = inb(port+Rstatus);
828
	outb(port+Rcontrol, Rint);
829
	iunlock(&ctlr->issuelock);
830
 
831
	if((rinterrupt & Cmdc) && (rstatus & Cmdinv))
832
		return 0;
833
	return 1;
834
}
835
 
836
static SDev*
837
mylexprobe(int port, int irq)
838
{
839
	SDev *sdev;
840
	Ctlr *ctlr;
841
	uchar cmd[6], data[256];
842
	int clen, dlen, timeo;
843
	static int count;
844
 
845
	if(ioalloc(port, 0x3, 0, "mylex") < 0)
846
		return nil;
847
	ctlr = nil;
848
	sdev = nil;
849
	/*
850
	 * Attempt to hard-reset the board and reset
851
	 * the SCSI bus. If the board state doesn't settle to
852
	 * idle with mailbox initialisation required, either
853
	 * it isn't a compatible board or it's broken.
854
	 * If the controller has SCAM set this can take a while.
855
	 */
856
	if(getconf("*noscsireset") != nil)
857
		outb(port+Rcontrol, Rhard);
858
	else
859
		outb(port+Rcontrol, Rhard|Rsbus);
860
	for(timeo = 0; timeo < 100; timeo++){
861
		if(inb(port+Rstatus) == (Inreq|Hardy))
862
			break;
863
		delay(100);
864
	}
865
	if(inb(port+Rstatus) != (Inreq|Hardy)){
866
buggery:
867
		if(ctlr != nil)
868
			free(ctlr);
869
		if (sdev != nil)
870
			free(sdev);
871
		iofree(port);
872
		return nil;
873
	}
874
 
875
	if((ctlr = malloc(sizeof(Ctlr))) == nil)
876
		goto buggery;
877
	ctlr->port = port;
878
	ctlr->irq = irq;
879
	ctlr->bus = 24;
880
	ctlr->wide = 0;
881
 
882
	/*
883
	 * Try to determine if this is a 32-bit MultiMaster controller
884
	 * by attempting to obtain the extended inquiry information;
885
	 * this command is not implemented on Adaptec 154xx
886
	 * controllers. If successful, the first byte of the returned
887
	 * data is the host adapter bus type, 'E' for 32-bit EISA,
888
	 * PCI and VLB buses.
889
	 */
890
	cmd[0] = Ciesi;
891
	cmd[1] = 14;
892
	clen = 2;
893
	dlen = 256;
894
	if(issue(ctlr, cmd, clen, data, dlen)){
895
		if(data[0] == 'E')
896
			ctlr->bus = 32;
897
		ctlr->wide = data[0x0D] & 0x01;
898
		/*
899
		 * devsd doesn't pass us the `spec' argument, so
900
		 * we'll assume that sd0 goes to the first scsi host
901
		 * adapter found, etc.
902
		 */
903
		print("#S/sd%d: mylex SCSI: port 0x%ux: %d-bit, ",
904
			count++, ctlr->port, ctlr->bus);
905
		if (ctlr->wide)
906
			print("wide\n");
907
		else
908
			print("narrow\n");
909
	}
910
	else{
911
		/*
912
		 * Inconceivable though it may seem, a hard controller reset
913
		 * is necessary here to clear out the command queue. Every
914
		 * board seems to lock-up in a different way if you give an
915
		 * invalid command and then try to clear out the
916
		 * command/parameter and/or data-in register.
917
		 * Soft reset doesn't do the job either. Fortunately no
918
		 * serious initialisation has been done yet so there's nothing
919
		 * to tidy up.
920
		 */
921
		outb(port+Rcontrol, Rhard);
922
		for(timeo = 0; timeo < 100; timeo++){
923
			if(inb(port+Rstatus) == (Inreq|Hardy))
924
				break;
925
			delay(100);
926
		}
927
		if(inb(port+Rstatus) != (Inreq|Hardy))
928
			goto buggery;
929
	}
930
 
931
	/*
932
	 * If the BIOS is enabled on the AHA-1542C/CF and BIOS options for
933
	 * support of drives > 1Gb, dynamic scanning of the SCSI bus or more
934
	 * than 2 drives under DOS 5.0 are enabled, the BIOS disables
935
	 * accepting Cmbinit to protect against running with drivers which
936
	 * don't support those options. In order to unlock the interface it
937
	 * is necessary to read a lock-code using Cextbios and write it back
938
	 * using Cmbienable; the lock-code is non-zero.
939
	 */
940
	cmd[0] = Cinquiry;
941
	clen = 1;
942
	dlen = 4;
943
	if(issue(ctlr, cmd, clen, data, dlen) == 0)
944
		goto buggery;
945
	if(data[0] >= 0x43){
946
		cmd[0] = Cextbios;
947
		clen = 1;
948
		dlen = 2;
949
		if(issue(ctlr, cmd, clen, data, dlen) == 0)
950
			goto buggery;
951
 
952
		/*
953
		 * Lock-code returned in data[1]. If it's non-zero write
954
		 * it back along with bit 0 of byte 0 cleared to enable
955
		 * mailbox initialisation.
956
		 */
957
		if(data[1]){
958
			cmd[0] = Cmbienable;
959
			cmd[1] = 0;
960
			cmd[2] = data[1];
961
			clen = 3;
962
			if(issue(ctlr, cmd, clen, 0, 0) == 0)
963
				goto buggery;
964
		}
965
	}
966
 
967
	/*
968
	 * Get the id, DMA and IRQ info from the board. This will
969
	 * cause an interrupt which will hopefully not cause any
970
	 * trouble because the interrupt number isn't known yet.
971
	 * This is necessary as the DMA won't be set up if the
972
	 * board has the BIOS disabled.
973
	 *
974
	 * If the IRQ is already known, this must be a 32-bit PCI
975
	 * or EISA card, in which case the returned DMA and IRQ can
976
	 * be ignored.
977
	 */
978
	cmd[0] = Cinquire;
979
	clen = 1;
980
	dlen = 3;
981
	if(issue(ctlr, cmd, clen, data, dlen) == 0)
982
		goto buggery;
983
 
984
	ctlr->id = data[2] & 0x07;
985
	if(ctlr->irq < 0){
986
		switch(data[0]){		/* DMA Arbitration Priority */
987
		case 0x80:			/* Channel 7 */
988
			outb(0xD6, 0xC3);
989
			outb(0xD4, 0x03);
990
			break;
991
		case 0x40:			/* Channel 6 */
992
			outb(0xD6, 0xC2);
993
			outb(0xD4, 0x02);
994
			break;
995
		case 0x20:			/* Channel 5 */
996
			outb(0xD6, 0xC1);
997
			outb(0xD4, 0x01);
998
			break;
999
		case 0x01:			/* Channel 0 */
1000
			outb(0x0B, 0xC0);
1001
			outb(0x0A, 0x00);
1002
			break;
1003
		default:
1004
			if(ctlr->bus == 24)
1005
				goto buggery;
1006
			break;
1007
		}
1008
 
1009
		switch(data[1]){		/* Interrupt Channel */
1010
		case 0x40:
1011
			ctlr->irq = 15;
1012
			break;
1013
		case 0x20:
1014
			ctlr->irq = 14;
1015
			break;
1016
		case 0x08:
1017
			ctlr->irq = 12;
1018
			break;
1019
		case 0x04:
1020
			ctlr->irq = 11;
1021
			break;
1022
		case 0x02:
1023
			ctlr->irq = 10;
1024
			break;
1025
		case 0x01:
1026
			ctlr->irq = 9;
1027
			break;
1028
		default:
1029
			goto buggery;
1030
		}
1031
	}
1032
 
1033
	if((sdev = malloc(sizeof(SDev))) == nil)
1034
		goto buggery;
1035
	sdev->ifc = &sdmylexifc;
1036
	sdev->ctlr = ctlr;
1037
	sdev->idno = '0';
1038
	ctlr->sdev = sdev;
1039
	if(!ctlr->wide)
1040
		sdev->nunit = 8;
1041
	else
1042
		sdev->nunit = 16;
1043
 
1044
	return sdev;
1045
}
1046
 
1047
static int mylexport[8] = {
1048
	0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0x000, 0x000,
1049
};
1050
 
1051
static SDev*
1052
mylexpnp(void)
1053
{
1054
	Pcidev *p;
1055
	Ctlr *ctlr;
1056
	ISAConf isa;
1057
	int cfg, ctlrno, i, x;
1058
	SDev *sdev, *head, *tail;
1059
 
1060
	p = nil;
1061
	head = tail = nil;
1062
	while(p = pcimatch(p, 0x104B, 0)){
1063
		if((sdev = mylexprobe(p->mem[0].bar & ~0x01, p->intl)) == nil)
1064
			continue;
1065
 
1066
		ctlr = sdev->ctlr;
1067
		ctlr->pcidev = p;
1068
 
1069
		if(head != nil)
1070
			tail->next = sdev;
1071
		else
1072
			head = sdev;
1073
		tail = sdev;
1074
	}
1075
 
1076
	if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){
1077
		for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){
1078
			x = 0;
1079
			for(i = 0; i < 4; i++)
1080
				x |= inb(cfg+CfgEISA+i)<<(i*8);
1081
			if(x != 0x0142B30A && x != 0x0242B30A)
1082
				continue;
1083
 
1084
			x = inb(cfg+0xC8C);
1085
			if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil)
1086
				continue;
1087
 
1088
			if(head != nil)
1089
				tail->next = sdev;
1090
			else
1091
				head = sdev;
1092
			tail = sdev;
1093
		}
1094
	}
1095
 
1096
	for(ctlrno = 0; ctlrno < 4; ctlrno++){
1097
		memset(&isa, 0, sizeof(isa));
1098
		if(!isaconfig("scsi", ctlrno, &isa))
1099
			continue;
1100
		if(strcmp(isa.type, "aha1542"))
1101
			continue;
1102
		if((sdev = mylexprobe(isa.port, -1)) == nil)
1103
			continue;
1104
 
1105
		if(head != nil)
1106
			tail->next = sdev;
1107
		else
1108
			head = sdev;
1109
		tail = sdev;
1110
	}
1111
 
1112
	return head;
1113
}
1114
 
1115
static int
1116
mylex24enable(Ctlr* ctlr)
1117
{
1118
	ulong p;
1119
	Ccb24 *ccb, *ccbp;
1120
	uchar cmd[6], *v;
1121
	int len;
1122
 
1123
	len = (sizeof(Mbox24)*NMbox*2)+(sizeof(Ccb24)*NCcb);
1124
	v = xspanalloc(len, 32, 0);
1125
 
1126
	if(!PADDR24(ctlr, sizeof(Ctlr)) || !PADDR24(v, len))
1127
		return 0;
1128
 
1129
	ctlr->mb = v;
1130
	v += sizeof(Mbox24)*NMbox*2;
1131
 
1132
	ccb = (Ccb24*)v;
1133
	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
1134
		ccbp->ccb = ctlr->ccb;
1135
		ctlr->ccb = (Ccb*)ccbp;
1136
	}
1137
 
1138
	/*
1139
	 * Initialise the software controller and
1140
	 * set the board scanning the mailboxes.
1141
	 */
1142
	ctlr->mbix = NMbox;
1143
 
1144
	cmd[0] = Cinitialise;
1145
	cmd[1] = NMbox;
1146
	p = K2BPA(ctlr->mb, BUSUNKNOWN);
1147
	cmd[2] = p>>16;
1148
	cmd[3] = p>>8;
1149
	cmd[4] = p;
1150
 
1151
	return issue(ctlr, cmd, 5, 0, 0);
1152
}
1153
 
1154
static int
1155
mylex32enable(Ctlr* ctlr)
1156
{
1157
	ulong p;
1158
	Ccb32 *ccb, *ccbp;
1159
	uchar cmd[6], *v;
1160
 
1161
	v = xspanalloc((sizeof(Mbox32)*NMbox*2)+(sizeof(Ccb32)*NCcb), 32, 0);
1162
 
1163
	ctlr->mb = v;
1164
	v += sizeof(Mbox32)*NMbox*2;
1165
 
1166
	ccb = (Ccb32*)v;
1167
	for(ccbp = ccb; ccbp < &ccb[NCcb]; ccbp++){
1168
		/*
1169
		 * Fill in some stuff that doesn't change.
1170
		 */
1171
		ccbp->senselen = sizeof(ccbp->sense);
1172
		p = PADDR(ccbp->sense);
1173
		ccbp->senseptr[0] = p;
1174
		ccbp->senseptr[1] = p>>8;
1175
		ccbp->senseptr[2] = p>>16;
1176
		ccbp->senseptr[3] = p>>24;
1177
 
1178
		ccbp->ccb = ctlr->ccb;
1179
		ctlr->ccb = (Ccb*)ccbp;
1180
	}
1181
 
1182
	/*
1183
	 * Attempt wide mode setup.
1184
	 */
1185
	if(ctlr->wide){
1186
		cmd[0] = Cwide;
1187
		cmd[1] = 1;
1188
		if(!issue(ctlr, cmd, 2, 0, 0)) {
1189
			ctlr->wide = 0;
1190
			print("mylex32enable: port 0x%ux: scsi wide-mode setup "
1191
				"failed on wide host adapter", ctlr->port);
1192
		}
1193
	}
1194
 
1195
	/*
1196
	 * Initialise the software controller and
1197
	 * set the board scanning the mailboxes.
1198
	 */
1199
	ctlr->mbix = NMbox;
1200
 
1201
	cmd[0] = Ciem;
1202
	cmd[1] = NMbox;
1203
	if(ctlr->pcidev)
1204
		p = K2BPA(ctlr->mb, ctlr->tbdf);
1205
	else
1206
		p = K2BPA(ctlr->mb, BUSUNKNOWN);
1207
	cmd[2] = p;
1208
	cmd[3] = p>>8;
1209
	cmd[4] = p>>16;
1210
	cmd[5] = p>>24;
1211
 
1212
	return issue(ctlr, cmd, 6, 0, 0);
1213
}
1214
 
1215
static int
1216
mylexenable(SDev* sdev)
1217
{
1218
	int tbdf;
1219
	Ctlr *ctlr;
1220
	void (*interrupt)(Ureg*, void*);
1221
	char name[32];
1222
 
1223
	ctlr = sdev->ctlr;
1224
	if(ctlr->cache == nil){
1225
		if((ctlr->cache = malloc(sdev->nunit*sizeof(Ccb*))) == nil)
1226
			return 0;
1227
	}
1228
 
1229
	tbdf = BUSUNKNOWN;
1230
	if(ctlr->bus == 32){
1231
		if(ctlr->pcidev){
1232
			tbdf = ctlr->pcidev->tbdf;
1233
			pcisetbme(ctlr->pcidev);
1234
		}
1235
		if(!mylex32enable(ctlr))
1236
			return 0;
1237
		interrupt = mylex32interrupt;
1238
	}
1239
	else if(mylex24enable(ctlr))
1240
		interrupt = mylex24interrupt;
1241
	else
1242
		return 0;
1243
 
1244
	snprint(name, sizeof(name), "sd%c (%s)", sdev->idno, sdev->ifc->name);
1245
	intrenable(ctlr->irq, interrupt, ctlr, tbdf, name);
1246
 
1247
	return 1;
1248
}
1249
 
1250
SDifc sdmylexifc = {
1251
	"mylex",			/* name */
1252
 
1253
	mylexpnp,			/* pnp */
1254
	nil,				/* legacy */
1255
	mylexenable,			/* enable */
1256
	nil,				/* disable */
1257
 
1258
	scsiverify,			/* verify */
1259
	scsionline,			/* online */
1260
	mylexrio,			/* rio */
1261
	nil,				/* rctl */
1262
	nil,				/* wctl */
1263
 
1264
	scsibio,			/* bio */
1265
	nil,				/* probe */
1266
	nil,				/* clear */
1267
	nil,				/* rtopctl */
1268
	nil,				/* wtopctl */
1269
};