This source file includes following definitions.
- wait
- buslogic_prefix
- buslogic_stat
- buslogic_out
- buslogic_in
- makecode
- test_port
- buslogic_info
- buslogic_interrupt
- buslogic_queuecommand
- internal_done
- buslogic_command
- setup_mailboxes
- getconfig
- buslogic_query
- buslogic_detect
- buslogic_abort
- buslogic_reset
- buslogic_biosparam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include <linux/string.h>
63 #include <linux/sched.h>
64 #include <linux/kernel.h>
65 #include <linux/head.h>
66 #include <linux/types.h>
67 #include <linux/ioport.h>
68
69 #include <asm/io.h>
70 #include <asm/system.h>
71 #include <asm/dma.h>
72
73 #include "../block/blk.h"
74 #include "scsi.h"
75 #include "hosts.h"
76 # include "sd.h"
77 #define BUSLOGIC_PRIVATE_H
78 #include "buslogic.h"
79
80 #ifndef BUSLOGIC_DEBUG
81 # define BUSLOGIC_DEBUG UD_ABORT
82 #endif
83
84 #define BUSLOGIC_VERSION "1.00"
85
86
87
88
89
90
91
92
93
94
95
96
97 #define WAITNEXTTIMEOUT 3000000
98
99
100
101
102
103
104
105 #define BUSLOGIC_SG_MALLOC 512
106
107
108 #define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain))
109
110
111
112 #define DMA_MODE_REG 0xD6
113 #define DMA_MASK_REG 0xD4
114 #define CASCADE 0xC0
115
116 #define BUSLOGIC_MAILBOXES 16
117
118
119
120
121
122
123
124
125
126 static const unsigned int bases[] = {
127 #ifdef BUSLOGIC_PORT_OVERRIDE
128 BUSLOGIC_PORT_OVERRIDE
129 #else
130 0x330, 0x334,
131 #endif
132 };
133
134 #define BIOS_TRANSLATION_6432 1
135 #define BIOS_TRANSLATION_25563 2
136
137 struct hostdata {
138 unsigned char bus_type;
139 int bios_translation;
140 size_t last_mbi_used;
141 size_t last_mbo_used;
142 Scsi_Cmnd *SCint[BUSLOGIC_MAILBOXES];
143 struct mailbox mb[2 * BUSLOGIC_MAILBOXES];
144 struct ccb ccbs[BUSLOGIC_MAILBOXES];
145 };
146
147 #define HOSTDATA(host) ((struct hostdata *)&(host)->hostdata)
148
149
150 static struct Scsi_Host *host[7] = { NULL, };
151
152 static int setup_mailboxes(unsigned int base, struct Scsi_Host *SHpnt);
153
154 #define INTR_RESET(base) outb(RINT, CONTROL(base))
155
156 #define buslogic_printk buslogic_prefix(),printk
157
158 #define CHECK(cond) if (cond) ; else goto fail
159
160 #define WAIT(port, mask, allof, noneof) CHECK(wait(port, mask, allof, noneof))
161 #define WAIT_WHILE(port, mask) WAIT(port, mask, 0, mask)
162 #define WAIT_UNTIL(port, mask) WAIT(port, mask, mask, 0)
163
164 static __inline__ int wait(unsigned short port, unsigned char mask,
165 unsigned char allof, unsigned char noneof)
166 {
167 int bits;
168 unsigned int timeout = WAITNEXTTIMEOUT;
169
170 for (;;) {
171 bits = inb(port) & mask;
172 if ((bits & allof) == allof && (bits & noneof) == 0)
173 break;
174 if (--timeout == 0)
175 return FALSE;
176 }
177 return TRUE;
178 }
179
180 static void buslogic_prefix(void)
181 {
182 printk("BusLogic SCSI: ");
183 }
184
185 #if 0
186 static void buslogic_stat(unsigned int base)
187 {
188 int s = inb(STATUS(base)), i = inb(INTERRUPT(base));
189
190 printk("status=%02X intrflags=%02X\n", s, i);
191 }
192 #else
193 # define buslogic_stat(base)
194 #endif
195
196
197
198
199
200 static int buslogic_out(unsigned int base, const unsigned char *cmdp, size_t len)
201 {
202 if (len == 1) {
203 for (;;) {
204 WAIT_WHILE(STATUS(base), CPRBSY);
205 cli();
206 if (!(inb(STATUS(base)) & CPRBSY)) {
207 outb(*cmdp, COMMAND_PARAMETER(base));
208 sti();
209 return FALSE;
210 }
211 sti();
212 }
213 } else {
214 cli();
215 while (len--) {
216 WAIT_WHILE(STATUS(base), CPRBSY);
217 outb(*cmdp++, COMMAND_PARAMETER(base));
218 }
219 sti();
220 }
221 return FALSE;
222 fail:
223 sti();
224 buslogic_printk("buslogic_out failed(%u): ", len + 1);
225 buslogic_stat(base);
226 return TRUE;
227 }
228
229 static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len)
230 {
231 cli();
232 while (len--) {
233 WAIT_UNTIL(STATUS(base), DIRRDY);
234 *cmdp++ = inb(DATA_IN(base));
235 }
236 sti();
237 return FALSE;
238 fail:
239 sti();
240 buslogic_printk("buslogic_in failed(%u): ", len + 1);
241 buslogic_stat(base);
242 return TRUE;
243 }
244
245 static unsigned int makecode(unsigned int hosterr, unsigned int scsierr)
246 {
247 switch (hosterr) {
248 case 0x00:
249 case 0x0A:
250
251 case 0x0B:
252
253 hosterr = DID_OK;
254 break;
255
256 case 0x11:
257
258
259 hosterr = DID_TIME_OUT;
260 break;
261
262 case 0x14:
263
264
265
266
267 hosterr = DID_RESET;
268 break;
269
270 case 0x12:
271
272
273
274 case 0x13:
275
276 case 0x15:
277
278
279 case 0x16:
280
281
282 case 0x17:
283
284
285
286 case 0x18:
287
288 case 0x19:
289
290
291
292 case 0x1A:
293
294
295
296 case 0x1B:
297 case 0x1C:
298
299 case 0x20:
300 case 0x21:
301
302
303 case 0x22:
304 case 0x23:
305 #if BUSLOGIC_DEBUG
306 buslogic_printk("%X %X\n", hosterr, scsierr);
307 #endif
308 hosterr = DID_ERROR;
309 break;
310
311 default:
312 buslogic_printk("makecode: unknown hoststatus %X\n", hosterr);
313 break;
314 }
315 return (hosterr << 16) | scsierr;
316 }
317
318 static int test_port(unsigned int base, struct Scsi_Host *SHpnt)
319 {
320 unsigned int i;
321 unsigned char inquiry_cmd[] = { CMD_INQUIRY };
322 unsigned char inquiry_result[4];
323 unsigned char *cmdp;
324 int len;
325 volatile int debug = 0;
326
327
328 if (inb(STATUS(base)) == 0xFF)
329 return TRUE;
330
331
332
333
334 #if BUSLOGIC_DEBUG
335 buslogic_printk("test_port called\n");
336 #endif
337
338 outb(RSOFT | RINT, CONTROL(base));
339
340
341 i = jiffies + 2;
342 while (i > jiffies);
343
344 debug = 1;
345
346 WAIT(STATUS(base), STATMASK, INREQ | HARDY,
347 DACT | DFAIL | CMDINV | DIRRDY | CPRBSY);
348
349 debug = 2;
350
351 if (inb(INTERRUPT(base)) & INTRMASK)
352 goto fail;
353
354
355
356 buslogic_out(base, inquiry_cmd, 1);
357
358 debug = 3;
359 len = 4;
360 cmdp = &inquiry_result[0];
361 while (len--) {
362 WAIT(STATUS(base), DIRRDY, DIRRDY, 0);
363 *cmdp++ = inb(DATA_IN(base));
364 }
365
366 debug = 4;
367
368 if (inb(STATUS(base)) & DIRRDY)
369 goto fail;
370
371 debug = 5;
372
373 WAIT_UNTIL(INTERRUPT(base), CMDC);
374
375
376
377 debug = 6;
378
379 outb(RINT, CONTROL(base));
380
381 debug = 7;
382
383 return FALSE;
384 fail:
385 return TRUE;
386 }
387
388 const char *buslogic_info(void)
389 {
390 return "BusLogic SCSI Driver version " BUSLOGIC_VERSION;
391 }
392
393
394 static void buslogic_interrupt(int junk)
395 {
396 void (*my_done)(Scsi_Cmnd *) = NULL;
397 int errstatus, mbistatus = 0, number_serviced, found;
398 size_t mbi, mbo = 0;
399 struct Scsi_Host *SHpnt;
400 Scsi_Cmnd *SCtmp;
401 int irqno, base;
402 struct mailbox *mb;
403 struct ccb *ccb;
404
405
406 irqno = ((int *)junk)[-2];
407
408 SHpnt = host[irqno - 9];
409 if (!SHpnt)
410 panic("buslogic.c: NULL SCSI host entry");
411
412 mb = HOSTDATA(SHpnt)->mb;
413 ccb = HOSTDATA(SHpnt)->ccbs;
414 base = SHpnt->io_port;
415
416 #if BUSLOGIC_DEBUG
417 {
418 int flag = inb(INTERRUPT(base));
419
420 buslogic_printk("buslogic_interrupt: ");
421 if (!(flag & INTV))
422 printk("no interrupt? ");
423 if (flag & IMBL)
424 printk("IMBL ");
425 if (flag & MBOR)
426 printk("MBOR ");
427 if (flag & CMDC)
428 printk("CMDC ");
429 if (flag & RSTS)
430 printk("RSTS ");
431 printk("status %02X\n", inb(STATUS(base)));
432 }
433 #endif
434
435 number_serviced = 0;
436
437 for (;;) {
438 INTR_RESET(base);
439
440 cli();
441
442 mbi = HOSTDATA(SHpnt)->last_mbi_used + 1;
443 if (mbi >= 2 * BUSLOGIC_MAILBOXES)
444 mbi = BUSLOGIC_MAILBOXES;
445
446
447
448
449 found = FALSE;
450 do {
451 if (mb[mbi].status != MBX_NOT_IN_USE) {
452 found = TRUE;
453 break;
454 }
455 mbi++;
456 if (mbi >= 2 * BUSLOGIC_MAILBOXES)
457 mbi = BUSLOGIC_MAILBOXES;
458 } while (mbi != HOSTDATA(SHpnt)->last_mbi_used);
459
460 if (found) {
461 mbo = (struct ccb *)mb[mbi].ccbptr - ccb;
462 mbistatus = mb[mbi].status;
463 mb[mbi].status = MBX_NOT_IN_USE;
464 HOSTDATA(SHpnt)->last_mbi_used = mbi;
465 }
466
467 sti();
468
469 if (!found) {
470
471 if (number_serviced)
472 return;
473 buslogic_printk("interrupt received, but no mail\n");
474 return;
475 }
476
477 #if BUSLOGIC_DEBUG
478 if (ccb[mbo].tarstat || ccb[mbo].hastat)
479 buslogic_printk("buslogic_interrupt: returning %08X (status %d)\n",
480 ((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat,
481 mb[mbi].status);
482 #endif
483
484 if (mbistatus == 0x03)
485 continue;
486
487 #if BUSLOGIC_DEBUG
488 buslogic_printk("...done %u %u\n", mbo, mbi);
489 #endif
490
491 SCtmp = HOSTDATA(SHpnt)->SCint[mbo];
492
493 if (!SCtmp || !SCtmp->scsi_done) {
494 buslogic_printk("buslogic_interrupt: Unexpected interrupt\n");
495 return;
496 }
497
498 my_done = SCtmp->scsi_done;
499 if (SCtmp->host_scribble)
500 scsi_free(SCtmp->host_scribble, BUSLOGIC_SG_MALLOC);
501
502
503 if (mbistatus != 1)
504
505 errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
506 else
507 errstatus = 0;
508
509 #if BUSLOGIC_DEBUG
510 if (errstatus)
511 buslogic_printk("error: %08X %04X %04X\n",
512 errstatus, ccb[mbo].hastat, ccb[mbo].tarstat);
513
514 if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) {
515 size_t i;
516
517 buslogic_printk("buslogic_interrupt: sense: ");
518 for (i = 0; i < sizeof SCtmp->sense_buffer; i++)
519 printk(" %02X", SCtmp->sense_buffer[i]);
520 printk("\n");
521 }
522
523 if (errstatus)
524 buslogic_printk("buslogic_interrupt: returning %08X\n", errstatus);
525 #endif
526
527 SCtmp->result = errstatus;
528 HOSTDATA(SHpnt)->SCint[mbo] = NULL;
529
530
531 my_done(SCtmp);
532 number_serviced++;
533 }
534 }
535
536 int buslogic_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
537 {
538 static const unsigned char buscmd[] = { CMD_START_SCSI };
539 unsigned char direction;
540 unsigned char *cmd = (unsigned char *)SCpnt->cmnd;
541 unsigned char target = SCpnt->target;
542 unsigned char lun = SCpnt->lun;
543 void *buff = SCpnt->request_buffer;
544 int bufflen = SCpnt->request_bufflen;
545 int mbo;
546 struct mailbox *mb;
547 struct ccb *ccb;
548
549 #if BUSLOGIC_DEBUG
550 if (target > 1) {
551 SCpnt->result = DID_TIME_OUT << 16;
552 done(SCpnt);
553 return 0;
554 }
555 #endif
556
557 if (*cmd == REQUEST_SENSE) {
558 #ifndef DEBUG
559 if (bufflen != sizeof SCpnt->sense_buffer) {
560 buslogic_printk("Wrong buffer length supplied for request sense (%d)\n",
561 bufflen);
562 }
563 #endif
564 SCpnt->result = 0;
565 done(SCpnt);
566 return 0;
567 }
568
569 #if BUSLOGIC_DEBUG
570 {
571 int i;
572
573 if (*cmd == READ_10 || *cmd == WRITE_10)
574 i = xscsi2int(cmd + 2);
575 else if (*cmd == READ_6 || *cmd == WRITE_6)
576 i = scsi2int(cmd + 2);
577 else
578 i = -1;
579 buslogic_printk("buslogic_queuecommand: dev %d cmd %02X pos %d len %d ",
580 target, *cmd, i, bufflen);
581 buslogic_stat(SCpnt->host->io_port);
582 buslogic_printk("buslogic_queuecommand: dumping scsi cmd: ");
583 for (i = 0; i < (COMMAND_SIZE(*cmd)); i++)
584 printk(" %02X", cmd[i]);
585 printk("\n");
586 if (*cmd == WRITE_10 || *cmd == WRITE_6)
587 return 0;
588 }
589 #endif
590
591 mb = HOSTDATA(SCpnt->host)->mb;
592 ccb = HOSTDATA(SCpnt->host)->ccbs;
593
594
595
596
597 cli();
598
599 mbo = HOSTDATA(SCpnt->host)->last_mbo_used + 1;
600 if (mbo >= BUSLOGIC_MAILBOXES)
601 mbo = 0;
602
603 do {
604 if (mb[mbo].status == MBX_NOT_IN_USE
605 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL)
606 break;
607 mbo++;
608 if (mbo >= BUSLOGIC_MAILBOXES)
609 mbo = 0;
610 } while (mbo != HOSTDATA(SCpnt->host)->last_mbo_used);
611
612 if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(SCpnt->host)->SCint[mbo]) {
613
614
615 panic("buslogic.c: unable to find empty mailbox");
616 }
617
618 HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt;
619
620
621
622 HOSTDATA(SCpnt->host)->last_mbo_used = mbo;
623
624 sti();
625
626 #if BUSLOGIC_DEBUG
627 buslogic_printk("sending command (%d %08X)...", mbo, done);
628 #endif
629
630
631 mb[mbo].ccbptr = &ccb[mbo];
632
633 memset(&ccb[mbo], 0, sizeof (struct ccb));
634
635 ccb[mbo].cdblen = COMMAND_SIZE(*cmd);
636
637
638 direction = 0;
639 if (*cmd == READ_10 || *cmd == READ_6)
640 direction = 8;
641 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
642 direction = 16;
643
644 memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
645
646 if (SCpnt->use_sg) {
647 struct scatterlist *sgpnt;
648 struct chain *cptr;
649 size_t i;
650
651 ccb[mbo].op = CCB_OP_INIT_SG;
652 SCpnt->host_scribble = (unsigned char *)scsi_malloc(BUSLOGIC_SG_MALLOC);
653 if (SCpnt->host_scribble == NULL)
654 panic("buslogic.c: unable to allocate DMA memory");
655 sgpnt = (struct scatterlist *)SCpnt->request_buffer;
656 cptr = (struct chain *)SCpnt->host_scribble;
657 if (SCpnt->use_sg > SCpnt->host->sg_tablesize) {
658 buslogic_printk("buslogic_queuecommand bad segment list, %d > %d\n",
659 SCpnt->use_sg, SCpnt->host->sg_tablesize);
660 panic("buslogic.c: bad segment list");
661 }
662 for (i = 0; i < SCpnt->use_sg; i++) {
663 cptr[i].dataptr = sgpnt[i].address;
664 cptr[i].datalen = sgpnt[i].length;
665 }
666 ccb[mbo].datalen = SCpnt->use_sg * sizeof (struct chain);
667 ccb[mbo].dataptr = cptr;
668 #if BUSLOGIC_DEBUG
669 {
670 unsigned char *ptr;
671
672 buslogic_printk("cptr %08X: ", cptr);
673 ptr = (unsigned char *)cptr;
674 for (i = 0; i < 18; i++)
675 printk(" %02X", ptr[i]);
676 printk("\n");
677 }
678 #endif
679 } else {
680 ccb[mbo].op = CCB_OP_INIT;
681 SCpnt->host_scribble = NULL;
682 ccb[mbo].datalen = bufflen;
683 ccb[mbo].dataptr = buff;
684 }
685 ccb[mbo].id = target;
686 ccb[mbo].lun = lun;
687 ccb[mbo].dir = direction;
688 ccb[mbo].rsalen = sizeof SCpnt->sense_buffer;
689 ccb[mbo].senseptr = SCpnt->sense_buffer;
690 ccb[mbo].linkptr = NULL;
691 ccb[mbo].commlinkid = 0;
692
693 #if BUSLOGIC_DEBUG
694 {
695 size_t i;
696
697 buslogic_printk("buslogic_queuecommand: sending...");
698 for (i = 0; i < sizeof ccb[mbo]; i++)
699 printk(" %02X", ((unsigned char *)&ccb[mbo])[i]);
700 printk("\n");
701 }
702 #endif
703
704 if (done) {
705 #if BUSLOGIC_DEBUG
706 buslogic_printk("buslogic_queuecommand: now waiting for interrupt: ");
707 buslogic_stat(SCpnt->host->io_port);
708 #endif
709 SCpnt->scsi_done = done;
710 mb[mbo].status = MBX_ACTION_START;
711
712 buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd);
713 #if BUSLOGIC_DEBUG
714 buslogic_printk("buslogic_queuecommand: status: ");
715 buslogic_stat(SCpnt->host->io_port);
716 #endif
717 } else
718 buslogic_printk("buslogic_queuecommand: done can't be NULL\n");
719
720 return 0;
721 }
722
723 #if 0
724 static void internal_done(Scsi_Cmnd *SCpnt)
725 {
726 SCpnt->SCp.Status++;
727 }
728
729 int buslogic_command(Scsi_Cmnd *SCpnt)
730 {
731 #if BUSLOGIC_DEBUG
732 buslogic_printk("buslogic_command: ..calling buslogic_queuecommand\n");
733 #endif
734
735 buslogic_queuecommand(SCpnt, internal_done);
736
737 SCpnt->SCp.Status = 0;
738 while (!SCpnt->SCp.Status)
739 continue;
740 return SCpnt->result;
741 return internal_done_errcode;
742 }
743 #endif
744
745
746 static int setup_mailboxes(unsigned int base, struct Scsi_Host *SHpnt)
747 {
748 size_t i;
749 int ok = FALSE;
750 struct mailbox *mb = HOSTDATA(SHpnt)->mb;
751 struct ccb *ccb = HOSTDATA(SHpnt)->ccbs;
752 struct {
753 unsigned char cmd, count;
754 void *base PACKED;
755 } cmd = { CMD_INITEXTMB, BUSLOGIC_MAILBOXES, mb };
756
757 for (i = 0; i < BUSLOGIC_MAILBOXES; i++) {
758 mb[i].status = mb[BUSLOGIC_MAILBOXES + i].status = MBX_NOT_IN_USE;
759 mb[i].ccbptr = &ccb[i];
760 }
761 INTR_RESET(base);
762
763
764 if (buslogic_out(base, (unsigned char *)&cmd, sizeof cmd))
765 goto must_be_adaptec;
766
767
768
769
770 WAIT_UNTIL(STATUS(base), HARDY);
771 if (inb(STATUS(base)) & CMDINV)
772 goto must_be_adaptec;
773
774 WAIT_UNTIL(INTERRUPT(base), CMDC);
775 while (0) {
776 fail:
777 buslogic_printk("buslogic_detect: failed setting up mailboxes\n");
778 }
779 ok = TRUE;
780 return ok;
781 must_be_adaptec:
782 INTR_RESET(base);
783 printk("- must be Adaptec\n");
784 return ok;
785 }
786
787 static int getconfig(unsigned int base, unsigned char *irq,
788 unsigned char *dma, unsigned char *id,
789 unsigned char *bus_type, unsigned short *max_sg)
790 {
791 unsigned char inquiry_cmd[2];
792 unsigned char inquiry_result[4];
793 int i;
794
795 i = inb(STATUS(base));
796 if (i & DIRRDY)
797 i = inb(DATA_IN(base));
798 inquiry_cmd[0] = CMD_RETCONF;
799 buslogic_out(base, inquiry_cmd, 1);
800 buslogic_in(base, inquiry_result, 3);
801 WAIT_UNTIL(INTERRUPT(base), CMDC);
802 INTR_RESET(base);
803
804 *dma = inquiry_result[0];
805 switch (inquiry_result[1]) {
806 case 0x01:
807 *irq = 9;
808 break;
809 case 0x02:
810 *irq = 10;
811 break;
812 case 0x04:
813 *irq = 11;
814 break;
815 case 0x08:
816 *irq = 12;
817 break;
818 case 0x20:
819 *irq = 14;
820 break;
821 case 0x40:
822 *irq = 15;
823 break;
824 default:
825 buslogic_printk("Unable to determine BusLogic IRQ level. Disabling board.\n");
826 return TRUE;
827 }
828 *id = inquiry_result[2] & 0x7;
829
830 inquiry_cmd[0] = CMD_INQEXTSETUP;
831 inquiry_cmd[1] = 4;
832 if (buslogic_out(base, inquiry_cmd, 2)
833 || buslogic_in(base, inquiry_result, 4))
834 return TRUE;
835 WAIT_UNTIL(INTERRUPT(base), CMDC);
836 INTR_RESET(base);
837
838 #ifdef BUSLOGIC_BUS_TYPE_OVERRIDE
839 *bus_type = BUS_TYPE_OVERRIDE;
840 #else
841 *bus_type = inquiry_result[0];
842 #endif
843 CHECK(*bus_type == 'A' || *bus_type == 'E' || *bus_type == 'M');
844 #ifdef BUSLOGIC_BUS_TYPE_OVERRIDE
845 if (inquiry_result[0] != BUS_TYPE_OVERRIDE)
846 buslogic_printk("Overriding bus type %c with %c\n",
847 inquiry_result[0], BUS_TYPE_OVERRIDE);
848 #endif
849 *max_sg = (inquiry_result[3] << 8) | inquiry_result[2];
850
851
852
853
854
855 if (*bus_type == 'A')
856 switch (*dma) {
857 case 0:
858 *dma = 0;
859 break;
860 case 0x20:
861 *dma = 5;
862 break;
863 case 0x40:
864 *dma = 6;
865 break;
866 case 0x80:
867 *dma = 7;
868 break;
869 default:
870 buslogic_printk("Unable to determine BusLogic DMA channel. Disabling board.\n");
871 return TRUE;
872 }
873 else
874 *dma = 0;
875
876 while (0) {
877 fail:
878 buslogic_printk("buslogic_detect: query board settings\n");
879 return TRUE;
880 }
881
882 return FALSE;
883 }
884
885
886 static int buslogic_query(unsigned int base, int *trans)
887 {
888 unsigned const char inquiry_cmd[] = { CMD_INQUIRY };
889 unsigned char inquiry_result[4];
890 int i;
891
892 i = inb(STATUS(base));
893 if (i & DIRRDY)
894 i = inb(DATA_IN(base));
895 buslogic_out(base, inquiry_cmd, sizeof inquiry_cmd);
896 buslogic_in(base, inquiry_result, 4);
897 WAIT_UNTIL(INTERRUPT(base), CMDC);
898 INTR_RESET(base);
899
900 buslogic_printk("Inquiry Bytes: %X %X %X %X\n",
901 inquiry_result[0],inquiry_result[1],
902 inquiry_result[2],inquiry_result[3]);
903 while (0) {
904 fail:
905 buslogic_printk("buslogic_query: query board settings\n");
906 return TRUE;
907 }
908
909 *trans = BIOS_TRANSLATION_6432;
910
911 return FALSE;
912 }
913
914
915 int buslogic_detect(Scsi_Host_Template * tpnt)
916 {
917 unsigned char dma;
918 unsigned char irq;
919 unsigned int base = 0;
920 unsigned char id;
921 unsigned char bus_type;
922 unsigned short max_sg;
923 int trans;
924 struct Scsi_Host *SHpnt = NULL;
925 int count = 0;
926 int indx;
927 int val;
928
929 #if BUSLOGIC_DEBUG
930 buslogic_printk("buslogic_detect:\n");
931 #endif
932
933 for (indx = 0; indx < ARRAY_SIZE(bases); indx++)
934 if (!check_region(bases[indx], 3)) {
935 SHpnt = scsi_register(tpnt, sizeof (struct hostdata));
936
937 base = bases[indx];
938
939 if (test_port(base, SHpnt))
940 goto unregister;
941
942
943 {
944
945 static const unsigned char oncmd[] = { CMD_BUSON_TIME, 7 };
946 static const unsigned char offcmd[] = { CMD_BUSOFF_TIME, 5 };
947
948 INTR_RESET(base);
949 buslogic_out(base, oncmd, sizeof oncmd);
950 WAIT_UNTIL(INTERRUPT(base), CMDC);
951
952
953
954 INTR_RESET(base);
955 buslogic_out(base, offcmd, sizeof offcmd);
956 WAIT_UNTIL(INTERRUPT(base), CMDC);
957 while (0) {
958 fail:
959 buslogic_printk("buslogic_detect: setting bus on/off-time failed\n");
960 }
961 INTR_RESET(base);
962 }
963
964 if (buslogic_query(base, &trans))
965 goto unregister;
966
967 if (getconfig(base, &irq, &dma, &id, &bus_type, &max_sg))
968 goto unregister;
969
970 #if BUSLOGIC_DEBUG
971 buslogic_stat(base);
972 #endif
973
974
975 if (!setup_mailboxes(base, SHpnt))
976 goto unregister;
977
978 printk("Configuring BusLogic %s HA at port 0x%03X, IRQ %u",
979 (bus_type == 'A' ? "ISA"
980 : (bus_type == 'E' ? "EISA/VESA" : "MCA")),
981 base, irq);
982 if (dma != 0)
983 printk(", DMA %u", dma);
984 printk(", ID %u\n", id);
985
986 #if BUSLOGIC_DEBUG
987 buslogic_stat(base);
988 #endif
989
990 #if BUSLOGIC_DEBUG
991 buslogic_printk("buslogic_detect: enable interrupt channel %d\n",
992 irq);
993 #endif
994
995 cli();
996 val = request_irq(irq, buslogic_interrupt);
997 if (val) {
998 buslogic_printk("Unable to allocate IRQ for "
999 "BusLogic controller.\n");
1000 sti();
1001 goto unregister;
1002 }
1003
1004 if (dma) {
1005 if (request_dma(dma)) {
1006 buslogic_printk("Unable to allocate DMA channel for "
1007 "BusLogic controller.\n");
1008 free_irq(irq);
1009 sti();
1010 goto unregister;
1011 }
1012
1013 if (dma >= 5) {
1014 outb((dma - 4) | CASCADE, DMA_MODE_REG);
1015 outb(dma - 4, DMA_MASK_REG);
1016 }
1017 }
1018
1019 host[irq - 9] = SHpnt;
1020 SHpnt->this_id = id;
1021 #ifdef CONFIG_NO_BUGGY_BUSLOGIC
1022
1023 SHpnt->unchecked_isa_dma = (bus_type == 'A');
1024 #else
1025
1026 SHpnt->unchecked_isa_dma = 1;
1027 #endif
1028 SHpnt->sg_tablesize = max_sg;
1029 if (SHpnt->sg_tablesize > BUSLOGIC_MAX_SG)
1030 SHpnt->sg_tablesize = BUSLOGIC_MAX_SG;
1031
1032
1033 SHpnt->hostt->can_queue = BUSLOGIC_MAILBOXES;
1034
1035 SHpnt->io_port = base;
1036 SHpnt->dma_channel = dma;
1037 SHpnt->irq = irq;
1038 HOSTDATA(SHpnt)->bios_translation = trans;
1039 if (trans == BIOS_TRANSLATION_25563)
1040 buslogic_printk("Using extended bios translation.\n");
1041 HOSTDATA(SHpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1;
1042 HOSTDATA(SHpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1;
1043 memset(HOSTDATA(SHpnt)->SCint, 0, sizeof HOSTDATA(SHpnt)->SCint);
1044 sti();
1045
1046 #if 0
1047 {
1048 unsigned char buf[8];
1049 unsigned char cmd[]
1050 = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1051 size_t i;
1052
1053 #if BUSLOGIC_DEBUG
1054 buslogic_printk("*** READ CAPACITY ***\n");
1055 #endif
1056 for (i = 0; i < sizeof buf; i++)
1057 buf[i] = 0x87;
1058 for (i = 0; i < 2; i++)
1059 if (!buslogic_command(i, cmd, buf, sizeof buf)) {
1060 buslogic_printk("bus_detect: LU %u sector_size %d "
1061 "device_size %d\n",
1062 i, xscsi2int(buf + 4), xscsi2int(buf));
1063 }
1064
1065 #if BUSLOGIC_DEBUG
1066 buslogic_printk("*** NOW RUNNING MY OWN TEST ***\n");
1067 #endif
1068 for (i = 0; i < 4; i++) {
1069 static buffer[512];
1070
1071 cmd[0] = READ_10;
1072 cmd[1] = 0;
1073 xany2scsi(cmd + 2, i);
1074 cmd[6] = 0;
1075 cmd[7] = 0;
1076 cmd[8] = 1;
1077 cmd[9] = 0;
1078 buslogic_command(0, cmd, buffer, sizeof buffer);
1079 }
1080 }
1081 #endif
1082
1083 snarf_region(bases[indx], 3);
1084
1085 count++;
1086 continue;
1087 unregister:
1088 scsi_unregister(SHpnt);
1089 }
1090 return count;
1091 }
1092
1093
1094
1095
1096
1097 int buslogic_abort(Scsi_Cmnd *SCpnt)
1098 {
1099 static const unsigned char buscmd[] = { CMD_START_SCSI };
1100 struct mailbox *mb;
1101 int mbi, mbo, i;
1102
1103 buslogic_printk("buslogic_abort: %X %X\n",
1104 inb(STATUS(SCpnt->host->io_port)),
1105 inb(INTERRUPT(SCpnt->host->io_port)));
1106
1107 cli();
1108 mb = HOSTDATA(SCpnt->host)->mb;
1109 mbi = HOSTDATA(SCpnt->host)->last_mbi_used + 1;
1110 if (mbi >= 2 * BUSLOGIC_MAILBOXES)
1111 mbi = BUSLOGIC_MAILBOXES;
1112
1113 do {
1114 if (mb[mbi].status != MBX_NOT_IN_USE)
1115 break;
1116 mbi++;
1117 if (mbi >= 2 * BUSLOGIC_MAILBOXES)
1118 mbi = BUSLOGIC_MAILBOXES;
1119 } while (mbi != HOSTDATA(SCpnt->host)->last_mbi_used);
1120 sti();
1121
1122 if (mb[mbi].status != MBX_NOT_IN_USE) {
1123 buslogic_printk("Lost interrupt discovered on irq %d - attempting to recover\n",
1124 SCpnt->host->irq);
1125 {
1126 int intval[3];
1127
1128 intval[0] = SCpnt->host->irq;
1129 buslogic_interrupt((int)&intval[2]);
1130 return SCSI_ABORT_SUCCESS;
1131 }
1132 }
1133
1134
1135
1136 for (i = 0; i < BUSLOGIC_MAILBOXES; i++)
1137 if (HOSTDATA(SCpnt->host)->SCint[i]) {
1138 if (HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) {
1139 buslogic_printk("Timed out command pending for %4.4X\n",
1140 SCpnt->request.dev);
1141 if (HOSTDATA(SCpnt->host)->mb[i].status != MBX_NOT_IN_USE) {
1142 buslogic_printk("OGMB still full - restarting\n");
1143 buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd);
1144 }
1145 } else
1146 buslogic_printk("Other pending command %4.4X\n",
1147 SCpnt->request.dev);
1148 }
1149
1150 #if (BUSLOGIC_DEBUG & BD_ABORT)
1151 buslogic_printk("buslogic_abort\n");
1152 #endif
1153
1154 #if 1
1155
1156
1157 cli();
1158 for (mbo = 0; mbo < BUSLOGIC_MAILBOXES; mbo++)
1159 if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]) {
1160 HOSTDATA(SCpnt->host)->mb[mbo].status = MBX_ACTION_ABORT;
1161 buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd);
1162 break;
1163 }
1164 sti();
1165 #endif
1166
1167 return SCSI_ABORT_PENDING;
1168 }
1169
1170
1171
1172
1173 int buslogic_reset(Scsi_Cmnd *SCpnt)
1174 {
1175 #if BUSLOGIC_DEBUG
1176 buslogic_printk("buslogic_reset\n");
1177 #endif
1178 return SCSI_RESET_PUNT;
1179 }
1180
1181 int buslogic_biosparam(Disk * disk, int dev, int *ip)
1182 {
1183 int size = disk->capacity;
1184 int translation_algorithm;
1185
1186
1187
1188
1189
1190
1191 translation_algorithm = HOSTDATA(disk->device->host)->bios_translation;
1192
1193 if ((size >> 11) > 1024
1194 && translation_algorithm == BIOS_TRANSLATION_25563) {
1195
1196 ip[0] = 255;
1197 ip[1] = 63;
1198 ip[2] = size / 255 / 63;
1199 } else {
1200 ip[0] = 64;
1201 ip[1] = 32;
1202 ip[2] = size >> 11;
1203 }
1204
1205
1206 return 0;
1207 }