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