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