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