xref: /plan9/sys/src/9/pc/sdmylex.c (revision fececb924262ae5acb31c5c448a4a6a523887b15)
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
ccbfree(Ctlr * ctlr,Ccb * ccb)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
ccbavailable(void * a)246 ccbavailable(void* a)
247 {
248 	return ((Ctlr*)a)->ccb != nil;
249 }
250 
251 static Ccb*
ccballoc(Ctlr * ctlr)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
done24(void * arg)282 done24(void* arg)
283 {
284 	return ((Ccb24*)arg)->done;
285 }
286 
287 static int
mylex24rio(SDreq * r)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
mylex24interrupt(Ureg *,void * arg)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
done32(void * arg)527 done32(void* arg)
528 {
529 	return ((Ccb32*)arg)->done;
530 }
531 
532 static int
mylex32rio(SDreq * r)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
mylex32interrupt(Ureg *,void * arg)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
mylexrio(SDreq * r)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
issueio(int port,uchar * cmd,int cmdlen,uchar * data,int datalen)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
issue(Ctlr * ctlr,uchar * cmd,int cmdlen,uchar * data,int datalen)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*
mylexprobe(int port,int irq)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*
mylexpnp(void)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
mylex24enable(Ctlr * ctlr)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
mylex32enable(Ctlr * ctlr)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
mylexenable(SDev * sdev)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 };
1270