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