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#define blogic_drvr_version "2.1.16"
30#define blogic_drvr_date "18 July 2002"
31
32#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/interrupt.h>
35#include <linux/types.h>
36#include <linux/blkdev.h>
37#include <linux/delay.h>
38#include <linux/ioport.h>
39#include <linux/mm.h>
40#include <linux/stat.h>
41#include <linux/pci.h>
42#include <linux/spinlock.h>
43#include <linux/jiffies.h>
44#include <linux/dma-mapping.h>
45#include <linux/slab.h>
46#include <scsi/scsicam.h>
47
48#include <asm/dma.h>
49#include <asm/io.h>
50
51#include <scsi/scsi.h>
52#include <scsi/scsi_cmnd.h>
53#include <scsi/scsi_device.h>
54#include <scsi/scsi_host.h>
55#include <scsi/scsi_tcq.h>
56#include "BusLogic.h"
57#include "FlashPoint.c"
58
59#ifndef FAILURE
60#define FAILURE (-1)
61#endif
62
63static struct scsi_host_template blogic_template;
64
65
66
67
68
69
70
71static int blogic_drvr_options_count;
72
73
74
75
76
77
78
79
80static struct blogic_drvr_options blogic_drvr_options[BLOGIC_MAX_ADAPTERS];
81
82
83
84
85
86
87MODULE_LICENSE("GPL");
88#ifdef MODULE
89static char *BusLogic;
90module_param(BusLogic, charp, 0);
91#endif
92
93
94
95
96
97
98
99static struct blogic_probe_options blogic_probe_options;
100
101
102
103
104
105
106
107static struct blogic_global_options blogic_global_options;
108
109static LIST_HEAD(blogic_host_list);
110
111
112
113
114
115static int blogic_probeinfo_count;
116
117
118
119
120
121
122
123
124
125static struct blogic_probeinfo *blogic_probeinfo_list;
126
127
128
129
130
131
132
133
134static char *blogic_cmd_failure_reason;
135
136
137
138
139
140
141static void blogic_announce_drvr(struct blogic_adapter *adapter)
142{
143 blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
144 blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", adapter);
145}
146
147
148
149
150
151
152
153static const char *blogic_drvr_info(struct Scsi_Host *host)
154{
155 struct blogic_adapter *adapter =
156 (struct blogic_adapter *) host->hostdata;
157 return adapter->full_model;
158}
159
160
161
162
163
164
165
166static void blogic_init_ccbs(struct blogic_adapter *adapter, void *blk_pointer,
167 int blk_size, dma_addr_t blkp)
168{
169 struct blogic_ccb *ccb = (struct blogic_ccb *) blk_pointer;
170 unsigned int offset = 0;
171 memset(blk_pointer, 0, blk_size);
172 ccb->allocgrp_head = blkp;
173 ccb->allocgrp_size = blk_size;
174 while ((blk_size -= sizeof(struct blogic_ccb)) >= 0) {
175 ccb->status = BLOGIC_CCB_FREE;
176 ccb->adapter = adapter;
177 ccb->dma_handle = (u32) blkp + offset;
178 if (blogic_flashpoint_type(adapter)) {
179 ccb->callback = blogic_qcompleted_ccb;
180 ccb->base_addr = adapter->fpinfo.base_addr;
181 }
182 ccb->next = adapter->free_ccbs;
183 ccb->next_all = adapter->all_ccbs;
184 adapter->free_ccbs = ccb;
185 adapter->all_ccbs = ccb;
186 adapter->alloc_ccbs++;
187 ccb++;
188 offset += sizeof(struct blogic_ccb);
189 }
190}
191
192
193
194
195
196
197static bool __init blogic_create_initccbs(struct blogic_adapter *adapter)
198{
199 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
200 void *blk_pointer;
201 dma_addr_t blkp;
202
203 while (adapter->alloc_ccbs < adapter->initccbs) {
204 blk_pointer = pci_alloc_consistent(adapter->pci_device,
205 blk_size, &blkp);
206 if (blk_pointer == NULL) {
207 blogic_err("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
208 adapter);
209 return false;
210 }
211 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
212 }
213 return true;
214}
215
216
217
218
219
220
221static void blogic_destroy_ccbs(struct blogic_adapter *adapter)
222{
223 struct blogic_ccb *next_ccb = adapter->all_ccbs, *ccb, *lastccb = NULL;
224 adapter->all_ccbs = NULL;
225 adapter->free_ccbs = NULL;
226 while ((ccb = next_ccb) != NULL) {
227 next_ccb = ccb->next_all;
228 if (ccb->allocgrp_head) {
229 if (lastccb)
230 pci_free_consistent(adapter->pci_device,
231 lastccb->allocgrp_size, lastccb,
232 lastccb->allocgrp_head);
233 lastccb = ccb;
234 }
235 }
236 if (lastccb)
237 pci_free_consistent(adapter->pci_device, lastccb->allocgrp_size,
238 lastccb, lastccb->allocgrp_head);
239}
240
241
242
243
244
245
246
247
248
249static void blogic_create_addlccbs(struct blogic_adapter *adapter,
250 int addl_ccbs, bool print_success)
251{
252 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
253 int prev_alloc = adapter->alloc_ccbs;
254 void *blk_pointer;
255 dma_addr_t blkp;
256 if (addl_ccbs <= 0)
257 return;
258 while (adapter->alloc_ccbs - prev_alloc < addl_ccbs) {
259 blk_pointer = pci_alloc_consistent(adapter->pci_device,
260 blk_size, &blkp);
261 if (blk_pointer == NULL)
262 break;
263 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
264 }
265 if (adapter->alloc_ccbs > prev_alloc) {
266 if (print_success)
267 blogic_notice("Allocated %d additional CCBs (total now %d)\n", adapter, adapter->alloc_ccbs - prev_alloc, adapter->alloc_ccbs);
268 return;
269 }
270 blogic_notice("Failed to allocate additional CCBs\n", adapter);
271 if (adapter->drvr_qdepth > adapter->alloc_ccbs - adapter->tgt_count) {
272 adapter->drvr_qdepth = adapter->alloc_ccbs - adapter->tgt_count;
273 adapter->scsi_host->can_queue = adapter->drvr_qdepth;
274 }
275}
276
277
278
279
280
281
282
283static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
284{
285 static unsigned long serial;
286 struct blogic_ccb *ccb;
287 ccb = adapter->free_ccbs;
288 if (ccb != NULL) {
289 ccb->serial = ++serial;
290 adapter->free_ccbs = ccb->next;
291 ccb->next = NULL;
292 if (adapter->free_ccbs == NULL)
293 blogic_create_addlccbs(adapter, adapter->inc_ccbs,
294 true);
295 return ccb;
296 }
297 blogic_create_addlccbs(adapter, adapter->inc_ccbs, true);
298 ccb = adapter->free_ccbs;
299 if (ccb == NULL)
300 return NULL;
301 ccb->serial = ++serial;
302 adapter->free_ccbs = ccb->next;
303 ccb->next = NULL;
304 return ccb;
305}
306
307
308
309
310
311
312
313
314static void blogic_dealloc_ccb(struct blogic_ccb *ccb)
315{
316 struct blogic_adapter *adapter = ccb->adapter;
317
318 scsi_dma_unmap(ccb->command);
319 pci_unmap_single(adapter->pci_device, ccb->sensedata,
320 ccb->sense_datalen, PCI_DMA_FROMDEVICE);
321
322 ccb->command = NULL;
323 ccb->status = BLOGIC_CCB_FREE;
324 ccb->next = adapter->free_ccbs;
325 adapter->free_ccbs = ccb;
326}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347static int blogic_cmd(struct blogic_adapter *adapter, enum blogic_opcode opcode,
348 void *param, int paramlen, void *reply, int replylen)
349{
350 unsigned char *param_p = (unsigned char *) param;
351 unsigned char *reply_p = (unsigned char *) reply;
352 union blogic_stat_reg statusreg;
353 union blogic_int_reg intreg;
354 unsigned long processor_flag = 0;
355 int reply_b = 0, result;
356 long timeout;
357
358
359
360 if (replylen > 0)
361 memset(reply, 0, replylen);
362
363
364
365
366
367
368
369 if (!adapter->irq_acquired)
370 local_irq_save(processor_flag);
371
372
373
374
375
376 timeout = 10000;
377 while (--timeout >= 0) {
378 statusreg.all = blogic_rdstatus(adapter);
379 if (statusreg.sr.adapter_ready && !statusreg.sr.cmd_param_busy)
380 break;
381 udelay(100);
382 }
383 if (timeout < 0) {
384 blogic_cmd_failure_reason =
385 "Timeout waiting for Host Adapter Ready";
386 result = -2;
387 goto done;
388 }
389
390
391
392 adapter->adapter_cmd_complete = false;
393 blogic_setcmdparam(adapter, opcode);
394
395
396
397 timeout = 10000;
398 while (paramlen > 0 && --timeout >= 0) {
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414 udelay(100);
415 intreg.all = blogic_rdint(adapter);
416 statusreg.all = blogic_rdstatus(adapter);
417 if (intreg.ir.cmd_complete)
418 break;
419 if (adapter->adapter_cmd_complete)
420 break;
421 if (statusreg.sr.datain_ready)
422 break;
423 if (statusreg.sr.cmd_param_busy)
424 continue;
425 blogic_setcmdparam(adapter, *param_p++);
426 paramlen--;
427 }
428 if (timeout < 0) {
429 blogic_cmd_failure_reason =
430 "Timeout waiting for Parameter Acceptance";
431 result = -2;
432 goto done;
433 }
434
435
436
437
438 if (opcode == BLOGIC_MOD_IOADDR) {
439 statusreg.all = blogic_rdstatus(adapter);
440 if (statusreg.sr.cmd_invalid) {
441 blogic_cmd_failure_reason =
442 "Modify I/O Address Invalid";
443 result = -1;
444 goto done;
445 }
446 if (blogic_global_options.trace_config)
447 blogic_notice("blogic_cmd(%02X) Status = %02X: " "(Modify I/O Address)\n", adapter, opcode, statusreg.all);
448 result = 0;
449 goto done;
450 }
451
452
453
454 switch (opcode) {
455 case BLOGIC_INQ_DEV0TO7:
456 case BLOGIC_INQ_DEV8TO15:
457 case BLOGIC_INQ_DEV:
458
459 timeout = 60 * 10000;
460 break;
461 default:
462
463 timeout = 10000;
464 break;
465 }
466
467
468
469
470
471
472 while (--timeout >= 0) {
473 intreg.all = blogic_rdint(adapter);
474 statusreg.all = blogic_rdstatus(adapter);
475 if (intreg.ir.cmd_complete)
476 break;
477 if (adapter->adapter_cmd_complete)
478 break;
479 if (statusreg.sr.datain_ready) {
480 if (++reply_b <= replylen)
481 *reply_p++ = blogic_rddatain(adapter);
482 else
483 blogic_rddatain(adapter);
484 }
485 if (opcode == BLOGIC_FETCH_LOCALRAM &&
486 statusreg.sr.adapter_ready)
487 break;
488 udelay(100);
489 }
490 if (timeout < 0) {
491 blogic_cmd_failure_reason =
492 "Timeout waiting for Command Complete";
493 result = -2;
494 goto done;
495 }
496
497
498
499 blogic_intreset(adapter);
500
501
502
503 if (blogic_global_options.trace_config) {
504 int i;
505 blogic_notice("blogic_cmd(%02X) Status = %02X: %2d ==> %2d:",
506 adapter, opcode, statusreg.all, replylen,
507 reply_b);
508 if (replylen > reply_b)
509 replylen = reply_b;
510 for (i = 0; i < replylen; i++)
511 blogic_notice(" %02X", adapter,
512 ((unsigned char *) reply)[i]);
513 blogic_notice("\n", adapter);
514 }
515
516
517
518 if (statusreg.sr.cmd_invalid) {
519
520
521
522
523
524
525
526
527
528 udelay(1000);
529 statusreg.all = blogic_rdstatus(adapter);
530 if (statusreg.sr.cmd_invalid || statusreg.sr.rsvd ||
531 statusreg.sr.datain_ready ||
532 statusreg.sr.cmd_param_busy ||
533 !statusreg.sr.adapter_ready ||
534 !statusreg.sr.init_reqd ||
535 statusreg.sr.diag_active ||
536 statusreg.sr.diag_failed) {
537 blogic_softreset(adapter);
538 udelay(1000);
539 }
540 blogic_cmd_failure_reason = "Command Invalid";
541 result = -1;
542 goto done;
543 }
544
545
546
547 if (paramlen > 0) {
548 blogic_cmd_failure_reason = "Excess Parameters Supplied";
549 result = -1;
550 goto done;
551 }
552
553
554
555 blogic_cmd_failure_reason = NULL;
556 result = reply_b;
557
558
559
560done:
561 if (!adapter->irq_acquired)
562 local_irq_restore(processor_flag);
563 return result;
564}
565
566
567
568
569
570
571
572
573static void __init blogic_add_probeaddr_isa(unsigned long io_addr)
574{
575 struct blogic_probeinfo *probeinfo;
576 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
577 return;
578 probeinfo = &blogic_probeinfo_list[blogic_probeinfo_count++];
579 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
580 probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
581 probeinfo->io_addr = io_addr;
582 probeinfo->pci_device = NULL;
583}
584
585
586
587
588
589
590
591
592static void __init blogic_init_probeinfo_isa(struct blogic_adapter *adapter)
593{
594
595
596
597
598 if (blogic_probe_options.noprobe_isa)
599 return;
600
601
602
603 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe330)
604 blogic_add_probeaddr_isa(0x330);
605 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe334)
606 blogic_add_probeaddr_isa(0x334);
607 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe230)
608 blogic_add_probeaddr_isa(0x230);
609 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe234)
610 blogic_add_probeaddr_isa(0x234);
611 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe130)
612 blogic_add_probeaddr_isa(0x130);
613 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe134)
614 blogic_add_probeaddr_isa(0x134);
615}
616
617
618#ifdef CONFIG_PCI
619
620
621
622
623
624
625
626static void __init blogic_sort_probeinfo(struct blogic_probeinfo
627 *probeinfo_list, int probeinfo_cnt)
628{
629 int last_exchange = probeinfo_cnt - 1, bound, j;
630
631 while (last_exchange > 0) {
632 bound = last_exchange;
633 last_exchange = 0;
634 for (j = 0; j < bound; j++) {
635 struct blogic_probeinfo *probeinfo1 =
636 &probeinfo_list[j];
637 struct blogic_probeinfo *probeinfo2 =
638 &probeinfo_list[j + 1];
639 if (probeinfo1->bus > probeinfo2->bus ||
640 (probeinfo1->bus == probeinfo2->bus &&
641 (probeinfo1->dev > probeinfo2->dev))) {
642 struct blogic_probeinfo tmp_probeinfo;
643
644 memcpy(&tmp_probeinfo, probeinfo1,
645 sizeof(struct blogic_probeinfo));
646 memcpy(probeinfo1, probeinfo2,
647 sizeof(struct blogic_probeinfo));
648 memcpy(probeinfo2, &tmp_probeinfo,
649 sizeof(struct blogic_probeinfo));
650 last_exchange = j;
651 }
652 }
653 }
654}
655
656
657
658
659
660
661
662
663
664
665static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
666{
667 struct blogic_probeinfo *pr_probeinfo =
668 &blogic_probeinfo_list[blogic_probeinfo_count];
669 int nonpr_mmindex = blogic_probeinfo_count + 1;
670 int nonpr_mmcount = 0, mmcount = 0;
671 bool force_scan_order = false;
672 bool force_scan_order_checked = false;
673 bool addr_seen[6];
674 struct pci_dev *pci_device = NULL;
675 int i;
676 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
677 return 0;
678 blogic_probeinfo_count++;
679 for (i = 0; i < 6; i++)
680 addr_seen[i] = false;
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695 pr_probeinfo->io_addr = 0;
696 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
697 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
698 pci_device)) != NULL) {
699 struct blogic_adapter *adapter = adapter;
700 struct blogic_adapter_info adapter_info;
701 enum blogic_isa_ioport mod_ioaddr_req;
702 unsigned char bus;
703 unsigned char device;
704 unsigned int irq_ch;
705 unsigned long base_addr0;
706 unsigned long base_addr1;
707 unsigned long io_addr;
708 unsigned long pci_addr;
709
710 if (pci_enable_device(pci_device))
711 continue;
712
713 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
714 continue;
715
716 bus = pci_device->bus->number;
717 device = pci_device->devfn >> 3;
718 irq_ch = pci_device->irq;
719 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
720 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
721
722 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
723 blogic_err("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, base_addr0);
724 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
725 continue;
726 }
727 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
728 blogic_err("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, base_addr1);
729 blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
730 continue;
731 }
732 if (irq_ch == 0) {
733 blogic_err("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, irq_ch);
734 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
735 continue;
736 }
737 if (blogic_global_options.trace_probe) {
738 blogic_notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
739 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
740 }
741
742
743
744
745
746
747 adapter->io_addr = io_addr;
748 blogic_intreset(adapter);
749 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
750 &adapter_info, sizeof(adapter_info)) ==
751 sizeof(adapter_info)) {
752 if (adapter_info.isa_port < 6)
753 addr_seen[adapter_info.isa_port] = true;
754 } else
755 adapter_info.isa_port = BLOGIC_IO_DISABLE;
756
757
758
759
760
761
762
763
764 mod_ioaddr_req = BLOGIC_IO_DISABLE;
765 blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
766 sizeof(mod_ioaddr_req), NULL, 0);
767
768
769
770
771
772
773
774
775 if (!force_scan_order_checked) {
776 struct blogic_fetch_localram fetch_localram;
777 struct blogic_autoscsi_byte45 autoscsi_byte45;
778 struct blogic_board_id id;
779
780 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
781 fetch_localram.count = sizeof(autoscsi_byte45);
782 blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM,
783 &fetch_localram, sizeof(fetch_localram),
784 &autoscsi_byte45,
785 sizeof(autoscsi_byte45));
786 blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
787 sizeof(id));
788 if (id.fw_ver_digit1 == '5')
789 force_scan_order =
790 autoscsi_byte45.force_scan_order;
791 force_scan_order_checked = true;
792 }
793
794
795
796
797
798
799
800
801 if (adapter_info.isa_port == BLOGIC_IO_330) {
802 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
803 pr_probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
804 pr_probeinfo->io_addr = io_addr;
805 pr_probeinfo->pci_addr = pci_addr;
806 pr_probeinfo->bus = bus;
807 pr_probeinfo->dev = device;
808 pr_probeinfo->irq_ch = irq_ch;
809 pr_probeinfo->pci_device = pci_dev_get(pci_device);
810 mmcount++;
811 } else if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
812 struct blogic_probeinfo *probeinfo =
813 &blogic_probeinfo_list[blogic_probeinfo_count++];
814 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
815 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
816 probeinfo->io_addr = io_addr;
817 probeinfo->pci_addr = pci_addr;
818 probeinfo->bus = bus;
819 probeinfo->dev = device;
820 probeinfo->irq_ch = irq_ch;
821 probeinfo->pci_device = pci_dev_get(pci_device);
822 nonpr_mmcount++;
823 mmcount++;
824 } else
825 blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
826 }
827
828
829
830
831
832
833
834
835
836
837
838 if (force_scan_order)
839 blogic_sort_probeinfo(&blogic_probeinfo_list[nonpr_mmindex],
840 nonpr_mmcount);
841
842
843
844
845
846 if (!blogic_probe_options.noprobe_isa)
847 if (pr_probeinfo->io_addr == 0 &&
848 (!blogic_probe_options.limited_isa ||
849 blogic_probe_options.probe330)) {
850 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
851 pr_probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
852 pr_probeinfo->io_addr = 0x330;
853 }
854
855
856
857
858 if (!blogic_probe_options.noprobe_isa) {
859 if (!addr_seen[1] &&
860 (!blogic_probe_options.limited_isa ||
861 blogic_probe_options.probe334))
862 blogic_add_probeaddr_isa(0x334);
863 if (!addr_seen[2] &&
864 (!blogic_probe_options.limited_isa ||
865 blogic_probe_options.probe230))
866 blogic_add_probeaddr_isa(0x230);
867 if (!addr_seen[3] &&
868 (!blogic_probe_options.limited_isa ||
869 blogic_probe_options.probe234))
870 blogic_add_probeaddr_isa(0x234);
871 if (!addr_seen[4] &&
872 (!blogic_probe_options.limited_isa ||
873 blogic_probe_options.probe130))
874 blogic_add_probeaddr_isa(0x130);
875 if (!addr_seen[5] &&
876 (!blogic_probe_options.limited_isa ||
877 blogic_probe_options.probe134))
878 blogic_add_probeaddr_isa(0x134);
879 }
880
881
882
883
884 pci_device = NULL;
885 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
886 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
887 pci_device)) != NULL) {
888 unsigned char bus;
889 unsigned char device;
890 unsigned int irq_ch;
891 unsigned long io_addr;
892
893 if (pci_enable_device(pci_device))
894 continue;
895
896 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
897 continue;
898
899 bus = pci_device->bus->number;
900 device = pci_device->devfn >> 3;
901 irq_ch = pci_device->irq;
902 io_addr = pci_resource_start(pci_device, 0);
903
904 if (io_addr == 0 || irq_ch == 0)
905 continue;
906 for (i = 0; i < blogic_probeinfo_count; i++) {
907 struct blogic_probeinfo *probeinfo =
908 &blogic_probeinfo_list[i];
909 if (probeinfo->io_addr == io_addr &&
910 probeinfo->adapter_type == BLOGIC_MULTIMASTER) {
911 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
912 probeinfo->pci_addr = 0;
913 probeinfo->bus = bus;
914 probeinfo->dev = device;
915 probeinfo->irq_ch = irq_ch;
916 probeinfo->pci_device = pci_dev_get(pci_device);
917 break;
918 }
919 }
920 }
921 return mmcount;
922}
923
924
925
926
927
928
929
930
931
932static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
933{
934 int fpindex = blogic_probeinfo_count, fpcount = 0;
935 struct pci_dev *pci_device = NULL;
936
937
938
939 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
940 PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
941 pci_device)) != NULL) {
942 unsigned char bus;
943 unsigned char device;
944 unsigned int irq_ch;
945 unsigned long base_addr0;
946 unsigned long base_addr1;
947 unsigned long io_addr;
948 unsigned long pci_addr;
949
950 if (pci_enable_device(pci_device))
951 continue;
952
953 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
954 continue;
955
956 bus = pci_device->bus->number;
957 device = pci_device->devfn >> 3;
958 irq_ch = pci_device->irq;
959 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
960 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
961#ifdef CONFIG_SCSI_FLASHPOINT
962 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
963 blogic_err("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, base_addr0);
964 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
965 continue;
966 }
967 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
968 blogic_err("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, base_addr1);
969 blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
970 continue;
971 }
972 if (irq_ch == 0) {
973 blogic_err("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, irq_ch);
974 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
975 continue;
976 }
977 if (blogic_global_options.trace_probe) {
978 blogic_notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
979 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
980 }
981 if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
982 struct blogic_probeinfo *probeinfo =
983 &blogic_probeinfo_list[blogic_probeinfo_count++];
984 probeinfo->adapter_type = BLOGIC_FLASHPOINT;
985 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
986 probeinfo->io_addr = io_addr;
987 probeinfo->pci_addr = pci_addr;
988 probeinfo->bus = bus;
989 probeinfo->dev = device;
990 probeinfo->irq_ch = irq_ch;
991 probeinfo->pci_device = pci_dev_get(pci_device);
992 fpcount++;
993 } else
994 blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
995#else
996 blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, bus, device);
997 blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
998 blogic_err("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
999#endif
1000 }
1001
1002
1003
1004
1005
1006 blogic_sort_probeinfo(&blogic_probeinfo_list[fpindex], fpcount);
1007 return fpcount;
1008}
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
1025{
1026
1027
1028
1029
1030
1031 if (!blogic_probe_options.noprobe_pci) {
1032 if (blogic_probe_options.multimaster_first) {
1033 blogic_init_mm_probeinfo(adapter);
1034 blogic_init_fp_probeinfo(adapter);
1035 } else if (blogic_probe_options.flashpoint_first) {
1036 blogic_init_fp_probeinfo(adapter);
1037 blogic_init_mm_probeinfo(adapter);
1038 } else {
1039 int fpcount = blogic_init_fp_probeinfo(adapter);
1040 int mmcount = blogic_init_mm_probeinfo(adapter);
1041 if (fpcount > 0 && mmcount > 0) {
1042 struct blogic_probeinfo *probeinfo =
1043 &blogic_probeinfo_list[fpcount];
1044 struct blogic_adapter *myadapter = adapter;
1045 struct blogic_fetch_localram fetch_localram;
1046 struct blogic_bios_drvmap d0_mapbyte;
1047
1048 while (probeinfo->adapter_bus_type !=
1049 BLOGIC_PCI_BUS)
1050 probeinfo++;
1051 myadapter->io_addr = probeinfo->io_addr;
1052 fetch_localram.offset =
1053 BLOGIC_BIOS_BASE + BLOGIC_BIOS_DRVMAP;
1054 fetch_localram.count = sizeof(d0_mapbyte);
1055 blogic_cmd(myadapter, BLOGIC_FETCH_LOCALRAM,
1056 &fetch_localram,
1057 sizeof(fetch_localram),
1058 &d0_mapbyte,
1059 sizeof(d0_mapbyte));
1060
1061
1062
1063
1064
1065
1066
1067
1068 if (d0_mapbyte.diskgeom != BLOGIC_BIOS_NODISK) {
1069 struct blogic_probeinfo saved_probeinfo[BLOGIC_MAX_ADAPTERS];
1070 int mmcount = blogic_probeinfo_count - fpcount;
1071
1072 memcpy(saved_probeinfo,
1073 blogic_probeinfo_list,
1074 blogic_probeinfo_count * sizeof(struct blogic_probeinfo));
1075 memcpy(&blogic_probeinfo_list[0],
1076 &saved_probeinfo[fpcount],
1077 mmcount * sizeof(struct blogic_probeinfo));
1078 memcpy(&blogic_probeinfo_list[mmcount],
1079 &saved_probeinfo[0],
1080 fpcount * sizeof(struct blogic_probeinfo));
1081 }
1082 }
1083 }
1084 } else {
1085 blogic_init_probeinfo_isa(adapter);
1086 }
1087}
1088
1089
1090#else
1091#define blogic_init_probeinfo_list(adapter) \
1092 blogic_init_probeinfo_isa(adapter)
1093#endif
1094
1095
1096
1097
1098
1099
1100static bool blogic_failure(struct blogic_adapter *adapter, char *msg)
1101{
1102 blogic_announce_drvr(adapter);
1103 if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
1104 blogic_err("While configuring BusLogic PCI Host Adapter at\n",
1105 adapter);
1106 blogic_err("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
1107 } else
1108 blogic_err("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", adapter, adapter->io_addr);
1109 blogic_err("%s FAILED - DETACHING\n", adapter, msg);
1110 if (blogic_cmd_failure_reason != NULL)
1111 blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
1112 blogic_cmd_failure_reason);
1113 return false;
1114}
1115
1116
1117
1118
1119
1120
1121static bool __init blogic_probe(struct blogic_adapter *adapter)
1122{
1123 union blogic_stat_reg statusreg;
1124 union blogic_int_reg intreg;
1125 union blogic_geo_reg georeg;
1126
1127
1128
1129 if (blogic_flashpoint_type(adapter)) {
1130 struct fpoint_info *fpinfo = &adapter->fpinfo;
1131 fpinfo->base_addr = (u32) adapter->io_addr;
1132 fpinfo->irq_ch = adapter->irq_ch;
1133 fpinfo->present = false;
1134 if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
1135 fpinfo->present)) {
1136 blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
1137 blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
1138 blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
1139 return false;
1140 }
1141 if (blogic_global_options.trace_probe)
1142 blogic_notice("BusLogic_Probe(0x%X): FlashPoint Found\n", adapter, adapter->io_addr);
1143
1144
1145
1146 return true;
1147 }
1148
1149
1150
1151
1152
1153
1154
1155 statusreg.all = blogic_rdstatus(adapter);
1156 intreg.all = blogic_rdint(adapter);
1157 georeg.all = blogic_rdgeom(adapter);
1158 if (blogic_global_options.trace_probe)
1159 blogic_notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
1160 if (statusreg.all == 0 || statusreg.sr.diag_active ||
1161 statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
1162 statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
1163 return false;
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180 if (georeg.all == 0xFF)
1181 return false;
1182
1183
1184
1185 return true;
1186}
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197static bool blogic_hwreset(struct blogic_adapter *adapter, bool hard_reset)
1198{
1199 union blogic_stat_reg statusreg;
1200 int timeout;
1201
1202
1203
1204
1205 if (blogic_flashpoint_type(adapter)) {
1206 struct fpoint_info *fpinfo = &adapter->fpinfo;
1207 fpinfo->softreset = !hard_reset;
1208 fpinfo->report_underrun = true;
1209 adapter->cardhandle =
1210 FlashPoint_HardwareResetHostAdapter(fpinfo);
1211 if (adapter->cardhandle == (void *)FPOINT_BADCARD_HANDLE)
1212 return false;
1213
1214
1215
1216 return true;
1217 }
1218
1219
1220
1221
1222
1223 if (hard_reset)
1224 blogic_hardreset(adapter);
1225 else
1226 blogic_softreset(adapter);
1227
1228
1229
1230 timeout = 5 * 10000;
1231 while (--timeout >= 0) {
1232 statusreg.all = blogic_rdstatus(adapter);
1233 if (statusreg.sr.diag_active)
1234 break;
1235 udelay(100);
1236 }
1237 if (blogic_global_options.trace_hw_reset)
1238 blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1239 if (timeout < 0)
1240 return false;
1241
1242
1243
1244
1245
1246 udelay(100);
1247
1248
1249
1250 timeout = 10 * 10000;
1251 while (--timeout >= 0) {
1252 statusreg.all = blogic_rdstatus(adapter);
1253 if (!statusreg.sr.diag_active)
1254 break;
1255 udelay(100);
1256 }
1257 if (blogic_global_options.trace_hw_reset)
1258 blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1259 if (timeout < 0)
1260 return false;
1261
1262
1263
1264
1265 timeout = 10000;
1266 while (--timeout >= 0) {
1267 statusreg.all = blogic_rdstatus(adapter);
1268 if (statusreg.sr.diag_failed || statusreg.sr.adapter_ready ||
1269 statusreg.sr.datain_ready)
1270 break;
1271 udelay(100);
1272 }
1273 if (blogic_global_options.trace_hw_reset)
1274 blogic_notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1275 if (timeout < 0)
1276 return false;
1277
1278
1279
1280
1281
1282
1283 if (statusreg.sr.diag_failed || !statusreg.sr.adapter_ready) {
1284 blogic_cmd_failure_reason = NULL;
1285 blogic_failure(adapter, "HARD RESET DIAGNOSTICS");
1286 blogic_err("HOST ADAPTER STATUS REGISTER = %02X\n", adapter,
1287 statusreg.all);
1288 if (statusreg.sr.datain_ready)
1289 blogic_err("HOST ADAPTER ERROR CODE = %d\n", adapter,
1290 blogic_rddatain(adapter));
1291 return false;
1292 }
1293
1294
1295
1296 return true;
1297}
1298
1299
1300
1301
1302
1303
1304
1305static bool __init blogic_checkadapter(struct blogic_adapter *adapter)
1306{
1307 struct blogic_ext_setup ext_setupinfo;
1308 unsigned char req_replylen;
1309 bool result = true;
1310
1311
1312
1313 if (blogic_flashpoint_type(adapter))
1314 return true;
1315
1316
1317
1318
1319
1320
1321 req_replylen = sizeof(ext_setupinfo);
1322 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1323 sizeof(req_replylen), &ext_setupinfo,
1324 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1325 result = false;
1326
1327
1328
1329 if (blogic_global_options.trace_probe)
1330 blogic_notice("BusLogic_Check(0x%X): MultiMaster %s\n", adapter,
1331 adapter->io_addr,
1332 (result ? "Found" : "Not Found"));
1333 return result;
1334}
1335
1336
1337
1338
1339
1340
1341
1342static bool __init blogic_rdconfig(struct blogic_adapter *adapter)
1343{
1344 struct blogic_board_id id;
1345 struct blogic_config config;
1346 struct blogic_setup_info setupinfo;
1347 struct blogic_ext_setup ext_setupinfo;
1348 unsigned char model[5];
1349 unsigned char fw_ver_digit3;
1350 unsigned char fw_ver_letter;
1351 struct blogic_adapter_info adapter_info;
1352 struct blogic_fetch_localram fetch_localram;
1353 struct blogic_autoscsi autoscsi;
1354 union blogic_geo_reg georeg;
1355 unsigned char req_replylen;
1356 unsigned char *tgt, ch;
1357 int tgt_id, i;
1358
1359
1360
1361
1362
1363
1364 if (blogic_flashpoint_type(adapter)) {
1365 struct fpoint_info *fpinfo = &adapter->fpinfo;
1366 tgt = adapter->model;
1367 *tgt++ = 'B';
1368 *tgt++ = 'T';
1369 *tgt++ = '-';
1370 for (i = 0; i < sizeof(fpinfo->model); i++)
1371 *tgt++ = fpinfo->model[i];
1372 *tgt++ = '\0';
1373 strcpy(adapter->fw_ver, FLASHPOINT_FW_VER);
1374 adapter->scsi_id = fpinfo->scsi_id;
1375 adapter->ext_trans_enable = fpinfo->ext_trans_enable;
1376 adapter->parity = fpinfo->parity;
1377 adapter->reset_enabled = !fpinfo->softreset;
1378 adapter->level_int = true;
1379 adapter->wide = fpinfo->wide;
1380 adapter->differential = false;
1381 adapter->scam = true;
1382 adapter->ultra = true;
1383 adapter->ext_lun = true;
1384 adapter->terminfo_valid = true;
1385 adapter->low_term = fpinfo->low_term;
1386 adapter->high_term = fpinfo->high_term;
1387 adapter->scam_enabled = fpinfo->scam_enabled;
1388 adapter->scam_lev2 = fpinfo->scam_lev2;
1389 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1390 adapter->maxdev = (adapter->wide ? 16 : 8);
1391 adapter->maxlun = 32;
1392 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1393 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1394 adapter->drvr_qdepth = 255;
1395 adapter->adapter_qdepth = adapter->drvr_qdepth;
1396 adapter->sync_ok = fpinfo->sync_ok;
1397 adapter->fast_ok = fpinfo->fast_ok;
1398 adapter->ultra_ok = fpinfo->ultra_ok;
1399 adapter->wide_ok = fpinfo->wide_ok;
1400 adapter->discon_ok = fpinfo->discon_ok;
1401 adapter->tagq_ok = 0xFFFF;
1402 goto common;
1403 }
1404
1405
1406
1407 if (blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
1408 sizeof(id)) != sizeof(id))
1409 return blogic_failure(adapter, "INQUIRE BOARD ID");
1410
1411
1412
1413 if (blogic_cmd(adapter, BLOGIC_INQ_CONFIG, NULL, 0, &config,
1414 sizeof(config))
1415 != sizeof(config))
1416 return blogic_failure(adapter, "INQUIRE CONFIGURATION");
1417
1418
1419
1420 req_replylen = sizeof(setupinfo);
1421 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
1422 sizeof(req_replylen), &setupinfo,
1423 sizeof(setupinfo)) != sizeof(setupinfo))
1424 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
1425
1426
1427
1428 req_replylen = sizeof(ext_setupinfo);
1429 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1430 sizeof(req_replylen), &ext_setupinfo,
1431 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1432 return blogic_failure(adapter,
1433 "INQUIRE EXTENDED SETUP INFORMATION");
1434
1435
1436
1437 fw_ver_digit3 = '\0';
1438 if (id.fw_ver_digit1 > '0')
1439 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_D3, NULL, 0,
1440 &fw_ver_digit3,
1441 sizeof(fw_ver_digit3)) != sizeof(fw_ver_digit3))
1442 return blogic_failure(adapter,
1443 "INQUIRE FIRMWARE 3RD DIGIT");
1444
1445
1446
1447 if (ext_setupinfo.bus_type == 'A' && id.fw_ver_digit1 == '2')
1448
1449 strcpy(model, "542B");
1450 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '2' &&
1451 (id.fw_ver_digit2 <= '1' || (id.fw_ver_digit2 == '2' &&
1452 fw_ver_digit3 == '0')))
1453
1454 strcpy(model, "742A");
1455 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '0')
1456
1457 strcpy(model, "747A");
1458 else {
1459 req_replylen = sizeof(model);
1460 if (blogic_cmd(adapter, BLOGIC_INQ_MODELNO, &req_replylen,
1461 sizeof(req_replylen), &model,
1462 sizeof(model)) != sizeof(model))
1463 return blogic_failure(adapter,
1464 "INQUIRE HOST ADAPTER MODEL NUMBER");
1465 }
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486 tgt = adapter->model;
1487 *tgt++ = 'B';
1488 *tgt++ = 'T';
1489 *tgt++ = '-';
1490 for (i = 0; i < sizeof(model); i++) {
1491 ch = model[i];
1492 if (ch == ' ' || ch == '\0')
1493 break;
1494 *tgt++ = ch;
1495 }
1496 *tgt++ = '\0';
1497
1498
1499
1500 tgt = adapter->fw_ver;
1501 *tgt++ = id.fw_ver_digit1;
1502 *tgt++ = '.';
1503 *tgt++ = id.fw_ver_digit2;
1504 if (fw_ver_digit3 != ' ' && fw_ver_digit3 != '\0')
1505 *tgt++ = fw_ver_digit3;
1506 *tgt = '\0';
1507
1508
1509
1510 if (strcmp(adapter->fw_ver, "3.3") >= 0) {
1511 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_LETTER, NULL, 0,
1512 &fw_ver_letter,
1513 sizeof(fw_ver_letter)) != sizeof(fw_ver_letter))
1514 return blogic_failure(adapter,
1515 "INQUIRE FIRMWARE VERSION LETTER");
1516 if (fw_ver_letter != ' ' && fw_ver_letter != '\0')
1517 *tgt++ = fw_ver_letter;
1518 *tgt = '\0';
1519 }
1520
1521
1522
1523 adapter->scsi_id = config.id;
1524
1525
1526
1527
1528
1529 adapter->adapter_bus_type =
1530 blogic_adater_bus_types[adapter->model[3] - '4'];
1531 if (adapter->irq_ch == 0) {
1532 if (config.irq_ch9)
1533 adapter->irq_ch = 9;
1534 else if (config.irq_ch10)
1535 adapter->irq_ch = 10;
1536 else if (config.irq_ch11)
1537 adapter->irq_ch = 11;
1538 else if (config.irq_ch12)
1539 adapter->irq_ch = 12;
1540 else if (config.irq_ch14)
1541 adapter->irq_ch = 14;
1542 else if (config.irq_ch15)
1543 adapter->irq_ch = 15;
1544 }
1545 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS) {
1546 if (config.dma_ch5)
1547 adapter->dma_ch = 5;
1548 else if (config.dma_ch6)
1549 adapter->dma_ch = 6;
1550 else if (config.dma_ch7)
1551 adapter->dma_ch = 7;
1552 }
1553
1554
1555
1556
1557 georeg.all = blogic_rdgeom(adapter);
1558 adapter->ext_trans_enable = georeg.gr.ext_trans_enable;
1559
1560
1561
1562
1563
1564 adapter->adapter_sglimit = ext_setupinfo.sg_limit;
1565 adapter->drvr_sglimit = adapter->adapter_sglimit;
1566 if (adapter->adapter_sglimit > BLOGIC_SG_LIMIT)
1567 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1568 if (ext_setupinfo.misc.level_int)
1569 adapter->level_int = true;
1570 adapter->wide = ext_setupinfo.wide;
1571 adapter->differential = ext_setupinfo.differential;
1572 adapter->scam = ext_setupinfo.scam;
1573 adapter->ultra = ext_setupinfo.ultra;
1574
1575
1576
1577
1578 if (adapter->fw_ver[0] == '5' || (adapter->fw_ver[0] == '4' &&
1579 adapter->wide))
1580 adapter->ext_lun = true;
1581
1582
1583
1584
1585 if (adapter->fw_ver[0] == '5') {
1586 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
1587 &adapter_info,
1588 sizeof(adapter_info)) != sizeof(adapter_info))
1589 return blogic_failure(adapter,
1590 "INQUIRE PCI HOST ADAPTER INFORMATION");
1591
1592
1593
1594
1595 if (adapter_info.genericinfo_valid) {
1596 adapter->terminfo_valid = true;
1597 adapter->low_term = adapter_info.low_term;
1598 adapter->high_term = adapter_info.high_term;
1599 }
1600 }
1601
1602
1603
1604
1605 if (adapter->fw_ver[0] >= '4') {
1606 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE;
1607 fetch_localram.count = sizeof(autoscsi);
1608 if (blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, &fetch_localram,
1609 sizeof(fetch_localram), &autoscsi,
1610 sizeof(autoscsi)) != sizeof(autoscsi))
1611 return blogic_failure(adapter,
1612 "FETCH HOST ADAPTER LOCAL RAM");
1613
1614
1615
1616
1617 adapter->parity = autoscsi.parity;
1618 adapter->reset_enabled = autoscsi.reset_enabled;
1619 if (adapter->fw_ver[0] == '4') {
1620 adapter->terminfo_valid = true;
1621 adapter->low_term = autoscsi.low_term;
1622 adapter->high_term = autoscsi.high_term;
1623 }
1624
1625
1626
1627
1628
1629 adapter->wide_ok = autoscsi.wide_ok;
1630 adapter->fast_ok = autoscsi.fast_ok;
1631 adapter->sync_ok = autoscsi.sync_ok;
1632 adapter->discon_ok = autoscsi.discon_ok;
1633 if (adapter->ultra)
1634 adapter->ultra_ok = autoscsi.ultra_ok;
1635 if (adapter->scam) {
1636 adapter->scam_enabled = autoscsi.scam_enabled;
1637 adapter->scam_lev2 = autoscsi.scam_lev2;
1638 }
1639 }
1640
1641
1642
1643
1644 if (adapter->fw_ver[0] < '4') {
1645 if (setupinfo.sync) {
1646 adapter->sync_ok = 0xFF;
1647 if (adapter->adapter_bus_type == BLOGIC_EISA_BUS) {
1648 if (ext_setupinfo.misc.fast_on_eisa)
1649 adapter->fast_ok = 0xFF;
1650 if (strcmp(adapter->model, "BT-757") == 0)
1651 adapter->wide_ok = 0xFF;
1652 }
1653 }
1654 adapter->discon_ok = 0xFF;
1655 adapter->parity = setupinfo.parity;
1656 adapter->reset_enabled = true;
1657 }
1658
1659
1660
1661
1662 adapter->maxdev = (adapter->wide ? 16 : 8);
1663 adapter->maxlun = (adapter->ext_lun ? 32 : 8);
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689 if (adapter->fw_ver[0] == '5')
1690 adapter->adapter_qdepth = 192;
1691 else if (adapter->fw_ver[0] == '4')
1692 adapter->adapter_qdepth = (adapter->adapter_bus_type !=
1693 BLOGIC_ISA_BUS ? 100 : 50);
1694 else
1695 adapter->adapter_qdepth = 30;
1696 if (strcmp(adapter->fw_ver, "3.31") >= 0) {
1697 adapter->strict_rr = true;
1698 adapter->mbox_count = BLOGIC_MAX_MAILBOX;
1699 } else {
1700 adapter->strict_rr = false;
1701 adapter->mbox_count = 32;
1702 }
1703 adapter->drvr_qdepth = adapter->mbox_count;
1704 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1705 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1706
1707
1708
1709
1710
1711
1712
1713 adapter->tagq_ok = 0;
1714 switch (adapter->fw_ver[0]) {
1715 case '5':
1716 adapter->tagq_ok = 0xFFFF;
1717 break;
1718 case '4':
1719 if (strcmp(adapter->fw_ver, "4.22") >= 0)
1720 adapter->tagq_ok = 0xFFFF;
1721 break;
1722 case '3':
1723 if (strcmp(adapter->fw_ver, "3.35") >= 0)
1724 adapter->tagq_ok = 0xFFFF;
1725 break;
1726 }
1727
1728
1729
1730
1731
1732 adapter->bios_addr = ext_setupinfo.bios_addr << 12;
1733
1734
1735
1736
1737 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS &&
1738 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1739 adapter->need_bouncebuf = true;
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 if (adapter->bios_addr > 0 && strcmp(adapter->model, "BT-445S") == 0 &&
1750 strcmp(adapter->fw_ver, "3.37") < 0 &&
1751 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1752 adapter->need_bouncebuf = true;
1753
1754
1755
1756
1757common:
1758
1759
1760
1761 strcpy(adapter->full_model, "BusLogic ");
1762 strcat(adapter->full_model, adapter->model);
1763
1764
1765
1766
1767
1768
1769
1770 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
1771 unsigned char qdepth = 0;
1772 if (adapter->drvr_opts != NULL &&
1773 adapter->drvr_opts->qdepth[tgt_id] > 0)
1774 qdepth = adapter->drvr_opts->qdepth[tgt_id];
1775 else if (adapter->need_bouncebuf)
1776 qdepth = BLOGIC_TAG_DEPTH_BB;
1777 adapter->qdepth[tgt_id] = qdepth;
1778 }
1779 if (adapter->need_bouncebuf)
1780 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH_BB;
1781 else
1782 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH;
1783 if (adapter->drvr_opts != NULL)
1784 adapter->common_qdepth = adapter->drvr_opts->common_qdepth;
1785 if (adapter->common_qdepth > 0 &&
1786 adapter->common_qdepth < adapter->untag_qdepth)
1787 adapter->untag_qdepth = adapter->common_qdepth;
1788
1789
1790
1791
1792
1793 adapter->tagq_ok &= adapter->discon_ok;
1794
1795
1796
1797
1798 if (adapter->drvr_opts != NULL)
1799 adapter->tagq_ok = (adapter->drvr_opts->tagq_ok &
1800 adapter->drvr_opts->tagq_ok_mask) |
1801 (adapter->tagq_ok & ~adapter->drvr_opts->tagq_ok_mask);
1802
1803
1804
1805
1806
1807
1808 if (adapter->drvr_opts != NULL &&
1809 adapter->drvr_opts->bus_settle_time > 0)
1810 adapter->bus_settle_time = adapter->drvr_opts->bus_settle_time;
1811 else
1812 adapter->bus_settle_time = BLOGIC_BUS_SETTLE_TIME;
1813
1814
1815
1816
1817 return true;
1818}
1819
1820
1821
1822
1823
1824
1825static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
1826{
1827 unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
1828 unsigned short sync_ok, fast_ok;
1829 unsigned short ultra_ok, wide_ok;
1830 unsigned short discon_ok, tagq_ok;
1831 bool common_syncneg, common_tagq_depth;
1832 char syncstr[BLOGIC_MAXDEV + 1];
1833 char widestr[BLOGIC_MAXDEV + 1];
1834 char discon_str[BLOGIC_MAXDEV + 1];
1835 char tagq_str[BLOGIC_MAXDEV + 1];
1836 char *syncmsg = syncstr;
1837 char *widemsg = widestr;
1838 char *discon_msg = discon_str;
1839 char *tagq_msg = tagq_str;
1840 int tgt_id;
1841
1842 blogic_info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", adapter, adapter->model, blogic_adapter_busnames[adapter->adapter_bus_type], (adapter->wide ? " Wide" : ""), (adapter->differential ? " Differential" : ""), (adapter->ultra ? " Ultra" : ""));
1843 blogic_info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
1844 if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
1845 blogic_info(" DMA Channel: ", adapter);
1846 if (adapter->dma_ch > 0)
1847 blogic_info("%d, ", adapter, adapter->dma_ch);
1848 else
1849 blogic_info("None, ", adapter);
1850 if (adapter->bios_addr > 0)
1851 blogic_info("BIOS Address: 0x%X, ", adapter,
1852 adapter->bios_addr);
1853 else
1854 blogic_info("BIOS Address: None, ", adapter);
1855 } else {
1856 blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
1857 adapter->bus, adapter->dev);
1858 if (adapter->pci_addr > 0)
1859 blogic_info("0x%X, ", adapter, adapter->pci_addr);
1860 else
1861 blogic_info("Unassigned, ", adapter);
1862 }
1863 blogic_info("Host Adapter SCSI ID: %d\n", adapter, adapter->scsi_id);
1864 blogic_info(" Parity Checking: %s, Extended Translation: %s\n",
1865 adapter, (adapter->parity ? "Enabled" : "Disabled"),
1866 (adapter->ext_trans_enable ? "Enabled" : "Disabled"));
1867 alltgt_mask &= ~(1 << adapter->scsi_id);
1868 sync_ok = adapter->sync_ok & alltgt_mask;
1869 fast_ok = adapter->fast_ok & alltgt_mask;
1870 ultra_ok = adapter->ultra_ok & alltgt_mask;
1871 if ((blogic_multimaster_type(adapter) &&
1872 (adapter->fw_ver[0] >= '4' ||
1873 adapter->adapter_bus_type == BLOGIC_EISA_BUS)) ||
1874 blogic_flashpoint_type(adapter)) {
1875 common_syncneg = false;
1876 if (sync_ok == 0) {
1877 syncmsg = "Disabled";
1878 common_syncneg = true;
1879 } else if (sync_ok == alltgt_mask) {
1880 if (fast_ok == 0) {
1881 syncmsg = "Slow";
1882 common_syncneg = true;
1883 } else if (fast_ok == alltgt_mask) {
1884 if (ultra_ok == 0) {
1885 syncmsg = "Fast";
1886 common_syncneg = true;
1887 } else if (ultra_ok == alltgt_mask) {
1888 syncmsg = "Ultra";
1889 common_syncneg = true;
1890 }
1891 }
1892 }
1893 if (!common_syncneg) {
1894 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1895 syncstr[tgt_id] = ((!(sync_ok & (1 << tgt_id))) ? 'N' : (!(fast_ok & (1 << tgt_id)) ? 'S' : (!(ultra_ok & (1 << tgt_id)) ? 'F' : 'U')));
1896 syncstr[adapter->scsi_id] = '#';
1897 syncstr[adapter->maxdev] = '\0';
1898 }
1899 } else
1900 syncmsg = (sync_ok == 0 ? "Disabled" : "Enabled");
1901 wide_ok = adapter->wide_ok & alltgt_mask;
1902 if (wide_ok == 0)
1903 widemsg = "Disabled";
1904 else if (wide_ok == alltgt_mask)
1905 widemsg = "Enabled";
1906 else {
1907 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1908 widestr[tgt_id] = ((wide_ok & (1 << tgt_id)) ? 'Y' : 'N');
1909 widestr[adapter->scsi_id] = '#';
1910 widestr[adapter->maxdev] = '\0';
1911 }
1912 discon_ok = adapter->discon_ok & alltgt_mask;
1913 if (discon_ok == 0)
1914 discon_msg = "Disabled";
1915 else if (discon_ok == alltgt_mask)
1916 discon_msg = "Enabled";
1917 else {
1918 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1919 discon_str[tgt_id] = ((discon_ok & (1 << tgt_id)) ? 'Y' : 'N');
1920 discon_str[adapter->scsi_id] = '#';
1921 discon_str[adapter->maxdev] = '\0';
1922 }
1923 tagq_ok = adapter->tagq_ok & alltgt_mask;
1924 if (tagq_ok == 0)
1925 tagq_msg = "Disabled";
1926 else if (tagq_ok == alltgt_mask)
1927 tagq_msg = "Enabled";
1928 else {
1929 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1930 tagq_str[tgt_id] = ((tagq_ok & (1 << tgt_id)) ? 'Y' : 'N');
1931 tagq_str[adapter->scsi_id] = '#';
1932 tagq_str[adapter->maxdev] = '\0';
1933 }
1934 blogic_info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
1935 adapter, syncmsg, widemsg);
1936 blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
1937 discon_msg, tagq_msg);
1938 if (blogic_multimaster_type(adapter)) {
1939 blogic_info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
1940 blogic_info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
1941 } else
1942 blogic_info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
1943 blogic_info(" Tagged Queue Depth: ", adapter);
1944 common_tagq_depth = true;
1945 for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
1946 if (adapter->qdepth[tgt_id] != adapter->qdepth[0]) {
1947 common_tagq_depth = false;
1948 break;
1949 }
1950 if (common_tagq_depth) {
1951 if (adapter->qdepth[0] > 0)
1952 blogic_info("%d", adapter, adapter->qdepth[0]);
1953 else
1954 blogic_info("Automatic", adapter);
1955 } else
1956 blogic_info("Individual", adapter);
1957 blogic_info(", Untagged Queue Depth: %d\n", adapter,
1958 adapter->untag_qdepth);
1959 if (adapter->terminfo_valid) {
1960 if (adapter->wide)
1961 blogic_info(" SCSI Bus Termination: %s", adapter,
1962 (adapter->low_term ? (adapter->high_term ? "Both Enabled" : "Low Enabled") : (adapter->high_term ? "High Enabled" : "Both Disabled")));
1963 else
1964 blogic_info(" SCSI Bus Termination: %s", adapter,
1965 (adapter->low_term ? "Enabled" : "Disabled"));
1966 if (adapter->scam)
1967 blogic_info(", SCAM: %s", adapter,
1968 (adapter->scam_enabled ? (adapter->scam_lev2 ? "Enabled, Level 2" : "Enabled, Level 1") : "Disabled"));
1969 blogic_info("\n", adapter);
1970 }
1971
1972
1973
1974
1975 return true;
1976}
1977
1978
1979
1980
1981
1982
1983
1984static bool __init blogic_getres(struct blogic_adapter *adapter)
1985{
1986 if (adapter->irq_ch == 0) {
1987 blogic_err("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
1988 adapter);
1989 return false;
1990 }
1991
1992
1993
1994 if (request_irq(adapter->irq_ch, blogic_inthandler, IRQF_SHARED,
1995 adapter->full_model, adapter) < 0) {
1996 blogic_err("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
1997 adapter, adapter->irq_ch);
1998 return false;
1999 }
2000 adapter->irq_acquired = true;
2001
2002
2003
2004 if (adapter->dma_ch > 0) {
2005 if (request_dma(adapter->dma_ch, adapter->full_model) < 0) {
2006 blogic_err("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", adapter, adapter->dma_ch);
2007 return false;
2008 }
2009 set_dma_mode(adapter->dma_ch, DMA_MODE_CASCADE);
2010 enable_dma(adapter->dma_ch);
2011 adapter->dma_chan_acquired = true;
2012 }
2013
2014
2015
2016 return true;
2017}
2018
2019
2020
2021
2022
2023
2024
2025static void blogic_relres(struct blogic_adapter *adapter)
2026{
2027
2028
2029
2030 if (adapter->irq_acquired)
2031 free_irq(adapter->irq_ch, adapter);
2032
2033
2034
2035 if (adapter->dma_chan_acquired)
2036 free_dma(adapter->dma_ch);
2037
2038
2039
2040 if (adapter->mbox_space)
2041 pci_free_consistent(adapter->pci_device, adapter->mbox_sz,
2042 adapter->mbox_space, adapter->mbox_space_handle);
2043 pci_dev_put(adapter->pci_device);
2044 adapter->mbox_space = NULL;
2045 adapter->mbox_space_handle = 0;
2046 adapter->mbox_sz = 0;
2047}
2048
2049
2050
2051
2052
2053
2054
2055
2056static bool blogic_initadapter(struct blogic_adapter *adapter)
2057{
2058 struct blogic_extmbox_req extmbox_req;
2059 enum blogic_rr_req rr_req;
2060 enum blogic_setccb_fmt setccb_fmt;
2061 int tgt_id;
2062
2063
2064
2065
2066
2067 adapter->firstccb = NULL;
2068 adapter->lastccb = NULL;
2069
2070
2071
2072
2073
2074
2075 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
2076 adapter->bdr_pend[tgt_id] = NULL;
2077 adapter->tgt_flags[tgt_id].tagq_active = false;
2078 adapter->tgt_flags[tgt_id].cmd_good = false;
2079 adapter->active_cmds[tgt_id] = 0;
2080 adapter->cmds_since_rst[tgt_id] = 0;
2081 }
2082
2083
2084
2085
2086 if (blogic_flashpoint_type(adapter))
2087 goto done;
2088
2089
2090
2091
2092 adapter->mbox_sz = adapter->mbox_count * (sizeof(struct blogic_outbox) + sizeof(struct blogic_inbox));
2093 adapter->mbox_space = pci_alloc_consistent(adapter->pci_device,
2094 adapter->mbox_sz, &adapter->mbox_space_handle);
2095 if (adapter->mbox_space == NULL)
2096 return blogic_failure(adapter, "MAILBOX ALLOCATION");
2097 adapter->first_outbox = (struct blogic_outbox *) adapter->mbox_space;
2098 adapter->last_outbox = adapter->first_outbox + adapter->mbox_count - 1;
2099 adapter->next_outbox = adapter->first_outbox;
2100 adapter->first_inbox = (struct blogic_inbox *) (adapter->last_outbox + 1);
2101 adapter->last_inbox = adapter->first_inbox + adapter->mbox_count - 1;
2102 adapter->next_inbox = adapter->first_inbox;
2103
2104
2105
2106
2107 memset(adapter->first_outbox, 0,
2108 adapter->mbox_count * sizeof(struct blogic_outbox));
2109 memset(adapter->first_inbox, 0,
2110 adapter->mbox_count * sizeof(struct blogic_inbox));
2111
2112
2113
2114
2115
2116 extmbox_req.mbox_count = adapter->mbox_count;
2117 extmbox_req.base_mbox_addr = (u32) adapter->mbox_space_handle;
2118 if (blogic_cmd(adapter, BLOGIC_INIT_EXT_MBOX, &extmbox_req,
2119 sizeof(extmbox_req), NULL, 0) < 0)
2120 return blogic_failure(adapter, "MAILBOX INITIALIZATION");
2121
2122
2123
2124
2125
2126
2127
2128
2129 if (adapter->strict_rr) {
2130 rr_req = BLOGIC_STRICT_RR_MODE;
2131 if (blogic_cmd(adapter, BLOGIC_STRICT_RR, &rr_req,
2132 sizeof(rr_req), NULL, 0) < 0)
2133 return blogic_failure(adapter,
2134 "ENABLE STRICT ROUND ROBIN MODE");
2135 }
2136
2137
2138
2139
2140
2141 if (adapter->ext_lun) {
2142 setccb_fmt = BLOGIC_EXT_LUN_CCB;
2143 if (blogic_cmd(adapter, BLOGIC_SETCCB_FMT, &setccb_fmt,
2144 sizeof(setccb_fmt), NULL, 0) < 0)
2145 return blogic_failure(adapter, "SET CCB FORMAT");
2146 }
2147
2148
2149
2150
2151done:
2152 if (!adapter->adapter_initd) {
2153 blogic_info("*** %s Initialized Successfully ***\n", adapter,
2154 adapter->full_model);
2155 blogic_info("\n", adapter);
2156 } else
2157 blogic_warn("*** %s Initialized Successfully ***\n", adapter,
2158 adapter->full_model);
2159 adapter->adapter_initd = true;
2160
2161
2162
2163
2164 return true;
2165}
2166
2167
2168
2169
2170
2171
2172
2173static bool __init blogic_inquiry(struct blogic_adapter *adapter)
2174{
2175 u16 installed_devs;
2176 u8 installed_devs0to7[8];
2177 struct blogic_setup_info setupinfo;
2178 u8 sync_period[BLOGIC_MAXDEV];
2179 unsigned char req_replylen;
2180 int tgt_id;
2181
2182
2183
2184
2185
2186
2187
2188 blogic_delay(adapter->bus_settle_time);
2189
2190
2191
2192 if (blogic_flashpoint_type(adapter))
2193 return true;
2194
2195
2196
2197 if (adapter->drvr_opts != NULL && adapter->drvr_opts->stop_tgt_inquiry)
2198 return true;
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209 if (strcmp(adapter->fw_ver, "4.25") >= 0) {
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219 if (blogic_cmd(adapter, BLOGIC_INQ_DEV, NULL, 0,
2220 &installed_devs, sizeof(installed_devs))
2221 != sizeof(installed_devs))
2222 return blogic_failure(adapter, "INQUIRE TARGET DEVICES");
2223 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2224 adapter->tgt_flags[tgt_id].tgt_exists =
2225 (installed_devs & (1 << tgt_id) ? true : false);
2226 } else {
2227
2228
2229
2230
2231
2232
2233
2234
2235 if (blogic_cmd(adapter, BLOGIC_INQ_DEV0TO7, NULL, 0,
2236 &installed_devs0to7, sizeof(installed_devs0to7))
2237 != sizeof(installed_devs0to7))
2238 return blogic_failure(adapter,
2239 "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2240 for (tgt_id = 0; tgt_id < 8; tgt_id++)
2241 adapter->tgt_flags[tgt_id].tgt_exists =
2242 (installed_devs0to7[tgt_id] != 0 ? true : false);
2243 }
2244
2245
2246
2247 req_replylen = sizeof(setupinfo);
2248 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
2249 sizeof(req_replylen), &setupinfo, sizeof(setupinfo))
2250 != sizeof(setupinfo))
2251 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
2252 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2253 adapter->sync_offset[tgt_id] = (tgt_id < 8 ? setupinfo.sync0to7[tgt_id].offset : setupinfo.sync8to15[tgt_id - 8].offset);
2254 if (strcmp(adapter->fw_ver, "5.06L") >= 0)
2255 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2256 adapter->tgt_flags[tgt_id].wide_active = (tgt_id < 8 ? (setupinfo.wide_tx_active0to7 & (1 << tgt_id) ? true : false) : (setupinfo.wide_tx_active8to15 & (1 << (tgt_id - 8)) ? true : false));
2257
2258
2259
2260 if (adapter->fw_ver[0] >= '3') {
2261
2262
2263
2264
2265
2266
2267 req_replylen = sizeof(sync_period);
2268 if (blogic_cmd(adapter, BLOGIC_INQ_SYNC_PERIOD, &req_replylen,
2269 sizeof(req_replylen), &sync_period,
2270 sizeof(sync_period)) != sizeof(sync_period))
2271 return blogic_failure(adapter,
2272 "INQUIRE SYNCHRONOUS PERIOD");
2273 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2274 adapter->sync_period[tgt_id] = sync_period[tgt_id];
2275 } else
2276 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2277 if (setupinfo.sync0to7[tgt_id].offset > 0)
2278 adapter->sync_period[tgt_id] = 20 + 5 * setupinfo.sync0to7[tgt_id].tx_period;
2279
2280
2281
2282 return true;
2283}
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294static void __init blogic_inithoststruct(struct blogic_adapter *adapter,
2295 struct Scsi_Host *host)
2296{
2297 host->max_id = adapter->maxdev;
2298 host->max_lun = adapter->maxlun;
2299 host->max_channel = 0;
2300 host->unique_id = adapter->io_addr;
2301 host->this_id = adapter->scsi_id;
2302 host->can_queue = adapter->drvr_qdepth;
2303 host->sg_tablesize = adapter->drvr_sglimit;
2304 host->unchecked_isa_dma = adapter->need_bouncebuf;
2305 host->cmd_per_lun = adapter->untag_qdepth;
2306}
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316static int blogic_slaveconfig(struct scsi_device *dev)
2317{
2318 struct blogic_adapter *adapter =
2319 (struct blogic_adapter *) dev->host->hostdata;
2320 int tgt_id = dev->id;
2321 int qdepth = adapter->qdepth[tgt_id];
2322
2323 if (adapter->tgt_flags[tgt_id].tagq_ok &&
2324 (adapter->tagq_ok & (1 << tgt_id))) {
2325 if (qdepth == 0)
2326 qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
2327 adapter->qdepth[tgt_id] = qdepth;
2328 scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, qdepth);
2329 } else {
2330 adapter->tagq_ok &= ~(1 << tgt_id);
2331 qdepth = adapter->untag_qdepth;
2332 adapter->qdepth[tgt_id] = qdepth;
2333 scsi_adjust_queue_depth(dev, 0, qdepth);
2334 }
2335 qdepth = 0;
2336 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2337 if (adapter->tgt_flags[tgt_id].tgt_exists)
2338 qdepth += adapter->qdepth[tgt_id];
2339 if (qdepth > adapter->alloc_ccbs)
2340 blogic_create_addlccbs(adapter, qdepth - adapter->alloc_ccbs,
2341 false);
2342 return 0;
2343}
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353static int __init blogic_init(void)
2354{
2355 int adapter_count = 0, drvr_optindex = 0, probeindex;
2356 struct blogic_adapter *adapter;
2357 int ret = 0;
2358
2359#ifdef MODULE
2360 if (BusLogic)
2361 blogic_setup(BusLogic);
2362#endif
2363
2364 if (blogic_probe_options.noprobe)
2365 return -ENODEV;
2366 blogic_probeinfo_list =
2367 kzalloc(BLOGIC_MAX_ADAPTERS * sizeof(struct blogic_probeinfo),
2368 GFP_KERNEL);
2369 if (blogic_probeinfo_list == NULL) {
2370 blogic_err("BusLogic: Unable to allocate Probe Info List\n",
2371 NULL);
2372 return -ENOMEM;
2373 }
2374
2375 adapter = kzalloc(sizeof(struct blogic_adapter), GFP_KERNEL);
2376 if (adapter == NULL) {
2377 kfree(blogic_probeinfo_list);
2378 blogic_err("BusLogic: Unable to allocate Prototype Host Adapter\n", NULL);
2379 return -ENOMEM;
2380 }
2381
2382#ifdef MODULE
2383 if (BusLogic != NULL)
2384 blogic_setup(BusLogic);
2385#endif
2386 blogic_init_probeinfo_list(adapter);
2387 for (probeindex = 0; probeindex < blogic_probeinfo_count; probeindex++) {
2388 struct blogic_probeinfo *probeinfo =
2389 &blogic_probeinfo_list[probeindex];
2390 struct blogic_adapter *myadapter = adapter;
2391 struct Scsi_Host *host;
2392
2393 if (probeinfo->io_addr == 0)
2394 continue;
2395 memset(myadapter, 0, sizeof(struct blogic_adapter));
2396 myadapter->adapter_type = probeinfo->adapter_type;
2397 myadapter->adapter_bus_type = probeinfo->adapter_bus_type;
2398 myadapter->io_addr = probeinfo->io_addr;
2399 myadapter->pci_addr = probeinfo->pci_addr;
2400 myadapter->bus = probeinfo->bus;
2401 myadapter->dev = probeinfo->dev;
2402 myadapter->pci_device = probeinfo->pci_device;
2403 myadapter->irq_ch = probeinfo->irq_ch;
2404 myadapter->addr_count =
2405 blogic_adapter_addr_count[myadapter->adapter_type];
2406
2407
2408
2409
2410 if (!request_region(myadapter->io_addr, myadapter->addr_count,
2411 "BusLogic"))
2412 continue;
2413
2414
2415
2416
2417 if (!blogic_probe(myadapter)) {
2418 release_region(myadapter->io_addr,
2419 myadapter->addr_count);
2420 continue;
2421 }
2422
2423
2424
2425
2426 if (!blogic_hwreset(myadapter, true)) {
2427 release_region(myadapter->io_addr,
2428 myadapter->addr_count);
2429 continue;
2430 }
2431
2432
2433
2434
2435 if (!blogic_checkadapter(myadapter)) {
2436 release_region(myadapter->io_addr,
2437 myadapter->addr_count);
2438 continue;
2439 }
2440
2441
2442
2443 if (drvr_optindex < blogic_drvr_options_count)
2444 myadapter->drvr_opts =
2445 &blogic_drvr_options[drvr_optindex++];
2446
2447
2448
2449
2450 blogic_announce_drvr(myadapter);
2451
2452
2453
2454
2455 host = scsi_host_alloc(&blogic_template,
2456 sizeof(struct blogic_adapter));
2457 if (host == NULL) {
2458 release_region(myadapter->io_addr,
2459 myadapter->addr_count);
2460 continue;
2461 }
2462 myadapter = (struct blogic_adapter *) host->hostdata;
2463 memcpy(myadapter, adapter, sizeof(struct blogic_adapter));
2464 myadapter->scsi_host = host;
2465 myadapter->host_no = host->host_no;
2466
2467
2468
2469
2470 list_add_tail(&myadapter->host_list, &blogic_host_list);
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485 if (blogic_rdconfig(myadapter) &&
2486 blogic_reportconfig(myadapter) &&
2487 blogic_getres(myadapter) &&
2488 blogic_create_initccbs(myadapter) &&
2489 blogic_initadapter(myadapter) &&
2490 blogic_inquiry(myadapter)) {
2491
2492
2493
2494
2495
2496
2497 release_region(myadapter->io_addr,
2498 myadapter->addr_count);
2499 if (!request_region(myadapter->io_addr,
2500 myadapter->addr_count,
2501 myadapter->full_model)) {
2502 printk(KERN_WARNING
2503 "BusLogic: Release and re-register of "
2504 "port 0x%04lx failed \n",
2505 (unsigned long)myadapter->io_addr);
2506 blogic_destroy_ccbs(myadapter);
2507 blogic_relres(myadapter);
2508 list_del(&myadapter->host_list);
2509 scsi_host_put(host);
2510 ret = -ENOMEM;
2511 } else {
2512 blogic_inithoststruct(myadapter,
2513 host);
2514 if (scsi_add_host(host, myadapter->pci_device
2515 ? &myadapter->pci_device->dev
2516 : NULL)) {
2517 printk(KERN_WARNING
2518 "BusLogic: scsi_add_host()"
2519 "failed!\n");
2520 blogic_destroy_ccbs(myadapter);
2521 blogic_relres(myadapter);
2522 list_del(&myadapter->host_list);
2523 scsi_host_put(host);
2524 ret = -ENODEV;
2525 } else {
2526 scsi_scan_host(host);
2527 adapter_count++;
2528 }
2529 }
2530 } else {
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541 blogic_destroy_ccbs(myadapter);
2542 blogic_relres(myadapter);
2543 list_del(&myadapter->host_list);
2544 scsi_host_put(host);
2545 ret = -ENODEV;
2546 }
2547 }
2548 kfree(adapter);
2549 kfree(blogic_probeinfo_list);
2550 blogic_probeinfo_list = NULL;
2551 return ret;
2552}
2553
2554
2555
2556
2557
2558
2559
2560
2561static int __exit blogic_deladapter(struct blogic_adapter *adapter)
2562{
2563 struct Scsi_Host *host = adapter->scsi_host;
2564
2565 scsi_remove_host(host);
2566
2567
2568
2569
2570
2571 if (blogic_flashpoint_type(adapter))
2572 FlashPoint_ReleaseHostAdapter(adapter->cardhandle);
2573
2574
2575
2576
2577 blogic_destroy_ccbs(adapter);
2578 blogic_relres(adapter);
2579
2580
2581
2582 release_region(adapter->io_addr, adapter->addr_count);
2583
2584
2585
2586
2587 list_del(&adapter->host_list);
2588
2589 scsi_host_put(host);
2590 return 0;
2591}
2592
2593
2594
2595
2596
2597
2598static void blogic_qcompleted_ccb(struct blogic_ccb *ccb)
2599{
2600 struct blogic_adapter *adapter = ccb->adapter;
2601
2602 ccb->status = BLOGIC_CCB_COMPLETE;
2603 ccb->next = NULL;
2604 if (adapter->firstccb == NULL) {
2605 adapter->firstccb = ccb;
2606 adapter->lastccb = ccb;
2607 } else {
2608 adapter->lastccb->next = ccb;
2609 adapter->lastccb = ccb;
2610 }
2611 adapter->active_cmds[ccb->tgt_id]--;
2612}
2613
2614
2615
2616
2617
2618
2619
2620static int blogic_resultcode(struct blogic_adapter *adapter,
2621 enum blogic_adapter_status adapter_status,
2622 enum blogic_tgt_status tgt_status)
2623{
2624 int hoststatus;
2625
2626 switch (adapter_status) {
2627 case BLOGIC_CMD_CMPLT_NORMAL:
2628 case BLOGIC_LINK_CMD_CMPLT:
2629 case BLOGIC_LINK_CMD_CMPLT_FLAG:
2630 hoststatus = DID_OK;
2631 break;
2632 case BLOGIC_SELECT_TIMEOUT:
2633 hoststatus = DID_TIME_OUT;
2634 break;
2635 case BLOGIC_INVALID_OUTBOX_CODE:
2636 case BLOGIC_INVALID_CMD_CODE:
2637 case BLOGIC_BAD_CMD_PARAM:
2638 blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
2639 adapter, adapter_status);
2640 case BLOGIC_DATA_UNDERRUN:
2641 case BLOGIC_DATA_OVERRUN:
2642 case BLOGIC_NOEXPECT_BUSFREE:
2643 case BLOGIC_LINKCCB_BADLUN:
2644 case BLOGIC_AUTOREQSENSE_FAIL:
2645 case BLOGIC_TAGQUEUE_REJECT:
2646 case BLOGIC_BAD_MSG_RCVD:
2647 case BLOGIC_HW_FAIL:
2648 case BLOGIC_BAD_RECONNECT:
2649 case BLOGIC_ABRT_QUEUE:
2650 case BLOGIC_ADAPTER_SW_ERROR:
2651 case BLOGIC_HW_TIMEOUT:
2652 case BLOGIC_PARITY_ERR:
2653 hoststatus = DID_ERROR;
2654 break;
2655 case BLOGIC_INVALID_BUSPHASE:
2656 case BLOGIC_NORESPONSE_TO_ATN:
2657 case BLOGIC_HW_RESET:
2658 case BLOGIC_RST_FROM_OTHERDEV:
2659 case BLOGIC_HW_BDR:
2660 hoststatus = DID_RESET;
2661 break;
2662 default:
2663 blogic_warn("Unknown Host Adapter Status 0x%02X\n", adapter,
2664 adapter_status);
2665 hoststatus = DID_ERROR;
2666 break;
2667 }
2668 return (hoststatus << 16) | tgt_status;
2669}
2670
2671
2672
2673
2674
2675
2676
2677static void blogic_scan_inbox(struct blogic_adapter *adapter)
2678{
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692 struct blogic_inbox *next_inbox = adapter->next_inbox;
2693 enum blogic_cmplt_code comp_code;
2694
2695 while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
2696
2697
2698
2699
2700
2701
2702
2703
2704 struct blogic_ccb *ccb =
2705 (struct blogic_ccb *) bus_to_virt(next_inbox->ccb);
2706 if (comp_code != BLOGIC_CMD_NOTFOUND) {
2707 if (ccb->status == BLOGIC_CCB_ACTIVE ||
2708 ccb->status == BLOGIC_CCB_RESET) {
2709
2710
2711
2712
2713 ccb->comp_code = comp_code;
2714 blogic_qcompleted_ccb(ccb);
2715 } else {
2716
2717
2718
2719
2720
2721
2722 blogic_warn("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
2723 }
2724 }
2725 next_inbox->comp_code = BLOGIC_INBOX_FREE;
2726 if (++next_inbox > adapter->last_inbox)
2727 next_inbox = adapter->first_inbox;
2728 }
2729 adapter->next_inbox = next_inbox;
2730}
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740static void blogic_process_ccbs(struct blogic_adapter *adapter)
2741{
2742 if (adapter->processing_ccbs)
2743 return;
2744 adapter->processing_ccbs = true;
2745 while (adapter->firstccb != NULL) {
2746 struct blogic_ccb *ccb = adapter->firstccb;
2747 struct scsi_cmnd *command = ccb->command;
2748 adapter->firstccb = ccb->next;
2749 if (adapter->firstccb == NULL)
2750 adapter->lastccb = NULL;
2751
2752
2753
2754 if (ccb->opcode == BLOGIC_BDR) {
2755 int tgt_id = ccb->tgt_id;
2756
2757 blogic_warn("Bus Device Reset CCB #%ld to Target " "%d Completed\n", adapter, ccb->serial, tgt_id);
2758 blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
2759 adapter->tgt_flags[tgt_id].tagq_active = false;
2760 adapter->cmds_since_rst[tgt_id] = 0;
2761 adapter->last_resetdone[tgt_id] = jiffies;
2762
2763
2764
2765 blogic_dealloc_ccb(ccb);
2766#if 0
2767
2768
2769
2770
2771
2772
2773
2774
2775 while (command != NULL) {
2776 struct scsi_cmnd *nxt_cmd =
2777 command->reset_chain;
2778 command->reset_chain = NULL;
2779 command->result = DID_RESET << 16;
2780 command->scsi_done(command);
2781 command = nxt_cmd;
2782 }
2783#endif
2784
2785
2786
2787
2788
2789 for (ccb = adapter->all_ccbs; ccb != NULL;
2790 ccb = ccb->next_all)
2791 if (ccb->status == BLOGIC_CCB_RESET &&
2792 ccb->tgt_id == tgt_id) {
2793 command = ccb->command;
2794 blogic_dealloc_ccb(ccb);
2795 adapter->active_cmds[tgt_id]--;
2796 command->result = DID_RESET << 16;
2797 command->scsi_done(command);
2798 }
2799 adapter->bdr_pend[tgt_id] = NULL;
2800 } else {
2801
2802
2803
2804
2805
2806 switch (ccb->comp_code) {
2807 case BLOGIC_INBOX_FREE:
2808 case BLOGIC_CMD_NOTFOUND:
2809 case BLOGIC_INVALID_CCB:
2810 blogic_warn("CCB #%ld to Target %d Impossible State\n", adapter, ccb->serial, ccb->tgt_id);
2811 break;
2812 case BLOGIC_CMD_COMPLETE_GOOD:
2813 adapter->tgt_stats[ccb->tgt_id]
2814 .cmds_complete++;
2815 adapter->tgt_flags[ccb->tgt_id]
2816 .cmd_good = true;
2817 command->result = DID_OK << 16;
2818 break;
2819 case BLOGIC_CMD_ABORT_BY_HOST:
2820 blogic_warn("CCB #%ld to Target %d Aborted\n",
2821 adapter, ccb->serial, ccb->tgt_id);
2822 blogic_inc_count(&adapter->tgt_stats[ccb->tgt_id].aborts_done);
2823 command->result = DID_ABORT << 16;
2824 break;
2825 case BLOGIC_CMD_COMPLETE_ERROR:
2826 command->result = blogic_resultcode(adapter,
2827 ccb->adapter_status, ccb->tgt_status);
2828 if (ccb->adapter_status != BLOGIC_SELECT_TIMEOUT) {
2829 adapter->tgt_stats[ccb->tgt_id]
2830 .cmds_complete++;
2831 if (blogic_global_options.trace_err) {
2832 int i;
2833 blogic_notice("CCB #%ld Target %d: Result %X Host "
2834 "Adapter Status %02X " "Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
2835 blogic_notice("CDB ", adapter);
2836 for (i = 0; i < ccb->cdblen; i++)
2837 blogic_notice(" %02X", adapter, ccb->cdb[i]);
2838 blogic_notice("\n", adapter);
2839 blogic_notice("Sense ", adapter);
2840 for (i = 0; i < ccb->sense_datalen; i++)
2841 blogic_notice(" %02X", adapter, command->sense_buffer[i]);
2842 blogic_notice("\n", adapter);
2843 }
2844 }
2845 break;
2846 }
2847
2848
2849
2850
2851
2852 if (ccb->cdb[0] == INQUIRY && ccb->cdb[1] == 0 &&
2853 ccb->adapter_status == BLOGIC_CMD_CMPLT_NORMAL) {
2854 struct blogic_tgt_flags *tgt_flags =
2855 &adapter->tgt_flags[ccb->tgt_id];
2856 struct scsi_inquiry *inquiry =
2857 (struct scsi_inquiry *) scsi_sglist(command);
2858 tgt_flags->tgt_exists = true;
2859 tgt_flags->tagq_ok = inquiry->CmdQue;
2860 tgt_flags->wide_ok = inquiry->WBus16;
2861 }
2862
2863
2864
2865 blogic_dealloc_ccb(ccb);
2866
2867
2868
2869 command->scsi_done(command);
2870 }
2871 }
2872 adapter->processing_ccbs = false;
2873}
2874
2875
2876
2877
2878
2879
2880
2881static irqreturn_t blogic_inthandler(int irq_ch, void *devid)
2882{
2883 struct blogic_adapter *adapter = (struct blogic_adapter *) devid;
2884 unsigned long processor_flag;
2885
2886
2887
2888 spin_lock_irqsave(adapter->scsi_host->host_lock, processor_flag);
2889
2890
2891
2892 if (blogic_multimaster_type(adapter)) {
2893 union blogic_int_reg intreg;
2894
2895
2896
2897 intreg.all = blogic_rdint(adapter);
2898 if (intreg.ir.int_valid) {
2899
2900
2901
2902
2903 blogic_intreset(adapter);
2904
2905
2906
2907
2908
2909
2910 if (intreg.ir.ext_busreset)
2911 adapter->adapter_extreset = true;
2912 else if (intreg.ir.mailin_loaded)
2913 blogic_scan_inbox(adapter);
2914 else if (intreg.ir.cmd_complete)
2915 adapter->adapter_cmd_complete = true;
2916 }
2917 } else {
2918
2919
2920
2921 if (FlashPoint_InterruptPending(adapter->cardhandle))
2922 switch (FlashPoint_HandleInterrupt(adapter->cardhandle)) {
2923 case FPOINT_NORMAL_INT:
2924 break;
2925 case FPOINT_EXT_RESET:
2926 adapter->adapter_extreset = true;
2927 break;
2928 case FPOINT_INTERN_ERR:
2929 blogic_warn("Internal FlashPoint Error detected - Resetting Host Adapter\n", adapter);
2930 adapter->adapter_intern_err = true;
2931 break;
2932 }
2933 }
2934
2935
2936
2937 if (adapter->firstccb != NULL)
2938 blogic_process_ccbs(adapter);
2939
2940
2941
2942 if (adapter->adapter_extreset) {
2943 blogic_warn("Resetting %s due to External SCSI Bus Reset\n", adapter, adapter->full_model);
2944 blogic_inc_count(&adapter->ext_resets);
2945 blogic_resetadapter(adapter, false);
2946 adapter->adapter_extreset = false;
2947 } else if (adapter->adapter_intern_err) {
2948 blogic_warn("Resetting %s due to Host Adapter Internal Error\n", adapter, adapter->full_model);
2949 blogic_inc_count(&adapter->adapter_intern_errors);
2950 blogic_resetadapter(adapter, true);
2951 adapter->adapter_intern_err = false;
2952 }
2953
2954
2955
2956 spin_unlock_irqrestore(adapter->scsi_host->host_lock, processor_flag);
2957 return IRQ_HANDLED;
2958}
2959
2960
2961
2962
2963
2964
2965
2966
2967static bool blogic_write_outbox(struct blogic_adapter *adapter,
2968 enum blogic_action action, struct blogic_ccb *ccb)
2969{
2970 struct blogic_outbox *next_outbox;
2971
2972 next_outbox = adapter->next_outbox;
2973 if (next_outbox->action == BLOGIC_OUTBOX_FREE) {
2974 ccb->status = BLOGIC_CCB_ACTIVE;
2975
2976
2977
2978
2979
2980
2981 next_outbox->ccb = ccb->dma_handle;
2982 next_outbox->action = action;
2983 blogic_execmbox(adapter);
2984 if (++next_outbox > adapter->last_outbox)
2985 next_outbox = adapter->first_outbox;
2986 adapter->next_outbox = next_outbox;
2987 if (action == BLOGIC_MBOX_START) {
2988 adapter->active_cmds[ccb->tgt_id]++;
2989 if (ccb->opcode != BLOGIC_BDR)
2990 adapter->tgt_stats[ccb->tgt_id].cmds_tried++;
2991 }
2992 return true;
2993 }
2994 return false;
2995}
2996
2997
2998
2999static int blogic_hostreset(struct scsi_cmnd *SCpnt)
3000{
3001 struct blogic_adapter *adapter =
3002 (struct blogic_adapter *) SCpnt->device->host->hostdata;
3003
3004 unsigned int id = SCpnt->device->id;
3005 struct blogic_tgt_stats *stats = &adapter->tgt_stats[id];
3006 int rc;
3007
3008 spin_lock_irq(SCpnt->device->host->host_lock);
3009
3010 blogic_inc_count(&stats->adatper_reset_req);
3011
3012 rc = blogic_resetadapter(adapter, false);
3013 spin_unlock_irq(SCpnt->device->host->host_lock);
3014 return rc;
3015}
3016
3017
3018
3019
3020
3021
3022static int blogic_qcmd_lck(struct scsi_cmnd *command,
3023 void (*comp_cb) (struct scsi_cmnd *))
3024{
3025 struct blogic_adapter *adapter =
3026 (struct blogic_adapter *) command->device->host->hostdata;
3027 struct blogic_tgt_flags *tgt_flags =
3028 &adapter->tgt_flags[command->device->id];
3029 struct blogic_tgt_stats *tgt_stats = adapter->tgt_stats;
3030 unsigned char *cdb = command->cmnd;
3031 int cdblen = command->cmd_len;
3032 int tgt_id = command->device->id;
3033 int lun = command->device->lun;
3034 int buflen = scsi_bufflen(command);
3035 int count;
3036 struct blogic_ccb *ccb;
3037
3038
3039
3040
3041
3042
3043
3044 if (cdb[0] == REQUEST_SENSE && command->sense_buffer[0] != 0) {
3045 command->result = DID_OK << 16;
3046 comp_cb(command);
3047 return 0;
3048 }
3049
3050
3051
3052
3053
3054
3055
3056 ccb = blogic_alloc_ccb(adapter);
3057 if (ccb == NULL) {
3058 spin_unlock_irq(adapter->scsi_host->host_lock);
3059 blogic_delay(1);
3060 spin_lock_irq(adapter->scsi_host->host_lock);
3061 ccb = blogic_alloc_ccb(adapter);
3062 if (ccb == NULL) {
3063 command->result = DID_ERROR << 16;
3064 comp_cb(command);
3065 return 0;
3066 }
3067 }
3068
3069
3070
3071
3072 count = scsi_dma_map(command);
3073 BUG_ON(count < 0);
3074 if (count) {
3075 struct scatterlist *sg;
3076 int i;
3077
3078 ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
3079 ccb->datalen = count * sizeof(struct blogic_sg_seg);
3080 if (blogic_multimaster_type(adapter))
3081 ccb->data = (void *)((unsigned int) ccb->dma_handle +
3082 ((unsigned long) &ccb->sglist -
3083 (unsigned long) ccb));
3084 else
3085 ccb->data = ccb->sglist;
3086
3087 scsi_for_each_sg(command, sg, count, i) {
3088 ccb->sglist[i].segbytes = sg_dma_len(sg);
3089 ccb->sglist[i].segdata = sg_dma_address(sg);
3090 }
3091 } else if (!count) {
3092 ccb->opcode = BLOGIC_INITIATOR_CCB;
3093 ccb->datalen = buflen;
3094 ccb->data = 0;
3095 }
3096
3097 switch (cdb[0]) {
3098 case READ_6:
3099 case READ_10:
3100 ccb->datadir = BLOGIC_DATAIN_CHECKED;
3101 tgt_stats[tgt_id].read_cmds++;
3102 blogic_addcount(&tgt_stats[tgt_id].bytesread, buflen);
3103 blogic_incszbucket(tgt_stats[tgt_id].read_sz_buckets, buflen);
3104 break;
3105 case WRITE_6:
3106 case WRITE_10:
3107 ccb->datadir = BLOGIC_DATAOUT_CHECKED;
3108 tgt_stats[tgt_id].write_cmds++;
3109 blogic_addcount(&tgt_stats[tgt_id].byteswritten, buflen);
3110 blogic_incszbucket(tgt_stats[tgt_id].write_sz_buckets, buflen);
3111 break;
3112 default:
3113 ccb->datadir = BLOGIC_UNCHECKED_TX;
3114 break;
3115 }
3116 ccb->cdblen = cdblen;
3117 ccb->adapter_status = 0;
3118 ccb->tgt_status = 0;
3119 ccb->tgt_id = tgt_id;
3120 ccb->lun = lun;
3121 ccb->tag_enable = false;
3122 ccb->legacytag_enable = false;
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139 if (adapter->cmds_since_rst[tgt_id]++ >= BLOGIC_MAX_TAG_DEPTH &&
3140 !tgt_flags->tagq_active &&
3141 adapter->active_cmds[tgt_id] == 0
3142 && tgt_flags->tagq_ok &&
3143 (adapter->tagq_ok & (1 << tgt_id))) {
3144 tgt_flags->tagq_active = true;
3145 blogic_notice("Tagged Queuing now active for Target %d\n",
3146 adapter, tgt_id);
3147 }
3148 if (tgt_flags->tagq_active) {
3149 enum blogic_queuetag queuetag = BLOGIC_SIMPLETAG;
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165 if (adapter->active_cmds[tgt_id] == 0)
3166 adapter->last_seqpoint[tgt_id] = jiffies;
3167 else if (time_after(jiffies,
3168 adapter->last_seqpoint[tgt_id] + 4 * HZ)) {
3169 adapter->last_seqpoint[tgt_id] = jiffies;
3170 queuetag = BLOGIC_ORDEREDTAG;
3171 }
3172 if (adapter->ext_lun) {
3173 ccb->tag_enable = true;
3174 ccb->queuetag = queuetag;
3175 } else {
3176 ccb->legacytag_enable = true;
3177 ccb->legacy_tag = queuetag;
3178 }
3179 }
3180 memcpy(ccb->cdb, cdb, cdblen);
3181 ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
3182 ccb->sensedata = pci_map_single(adapter->pci_device,
3183 command->sense_buffer, ccb->sense_datalen,
3184 PCI_DMA_FROMDEVICE);
3185 ccb->command = command;
3186 command->scsi_done = comp_cb;
3187 if (blogic_multimaster_type(adapter)) {
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
3199 spin_unlock_irq(adapter->scsi_host->host_lock);
3200 blogic_warn("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", adapter);
3201 blogic_delay(1);
3202 spin_lock_irq(adapter->scsi_host->host_lock);
3203 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
3204 ccb)) {
3205 blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter);
3206 blogic_dealloc_ccb(ccb);
3207 command->result = DID_ERROR << 16;
3208 command->scsi_done(command);
3209 }
3210 }
3211 } else {
3212
3213
3214
3215
3216 ccb->status = BLOGIC_CCB_ACTIVE;
3217 adapter->active_cmds[tgt_id]++;
3218 tgt_stats[tgt_id].cmds_tried++;
3219 FlashPoint_StartCCB(adapter->cardhandle, ccb);
3220
3221
3222
3223
3224
3225 if (ccb->status == BLOGIC_CCB_COMPLETE)
3226 blogic_process_ccbs(adapter);
3227 }
3228 return 0;
3229}
3230
3231static DEF_SCSI_QCMD(blogic_qcmd)
3232
3233#if 0
3234
3235
3236
3237
3238static int blogic_abort(struct scsi_cmnd *command)
3239{
3240 struct blogic_adapter *adapter =
3241 (struct blogic_adapter *) command->device->host->hostdata;
3242
3243 int tgt_id = command->device->id;
3244 struct blogic_ccb *ccb;
3245 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_request);
3246
3247
3248
3249
3250
3251 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3252 if (ccb->command == command)
3253 break;
3254 if (ccb == NULL) {
3255 blogic_warn("Unable to Abort Command to Target %d - No CCB Found\n", adapter, tgt_id);
3256 return SUCCESS;
3257 } else if (ccb->status == BLOGIC_CCB_COMPLETE) {
3258 blogic_warn("Unable to Abort Command to Target %d - CCB Completed\n", adapter, tgt_id);
3259 return SUCCESS;
3260 } else if (ccb->status == BLOGIC_CCB_RESET) {
3261 blogic_warn("Unable to Abort Command to Target %d - CCB Reset\n", adapter, tgt_id);
3262 return SUCCESS;
3263 }
3264 if (blogic_multimaster_type(adapter)) {
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277 if (adapter->tgt_flags[tgt_id].tagq_active &&
3278 adapter->fw_ver[0] < '5') {
3279 blogic_warn("Unable to Abort CCB #%ld to Target %d - Abort Tag Not Supported\n", adapter, ccb->serial, tgt_id);
3280 return FAILURE;
3281 } else if (blogic_write_outbox(adapter, BLOGIC_MBOX_ABORT,
3282 ccb)) {
3283 blogic_warn("Aborting CCB #%ld to Target %d\n",
3284 adapter, ccb->serial, tgt_id);
3285 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3286 return SUCCESS;
3287 } else {
3288 blogic_warn("Unable to Abort CCB #%ld to Target %d - No Outgoing Mailboxes\n", adapter, ccb->serial, tgt_id);
3289 return FAILURE;
3290 }
3291 } else {
3292
3293
3294
3295
3296 blogic_warn("Aborting CCB #%ld to Target %d\n", adapter,
3297 ccb->serial, tgt_id);
3298 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3299 FlashPoint_AbortCCB(adapter->cardhandle, ccb);
3300
3301
3302
3303
3304
3305 if (ccb->status == BLOGIC_CCB_COMPLETE)
3306 blogic_process_ccbs(adapter);
3307 return SUCCESS;
3308 }
3309 return SUCCESS;
3310}
3311
3312#endif
3313
3314
3315
3316
3317
3318static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
3319{
3320 struct blogic_ccb *ccb;
3321 int tgt_id;
3322
3323
3324
3325
3326
3327 if (!(blogic_hwreset(adapter, hard_reset) &&
3328 blogic_initadapter(adapter))) {
3329 blogic_err("Resetting %s Failed\n", adapter,
3330 adapter->full_model);
3331 return FAILURE;
3332 }
3333
3334
3335
3336
3337
3338 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3339 if (ccb->status == BLOGIC_CCB_ACTIVE)
3340 blogic_dealloc_ccb(ccb);
3341
3342
3343
3344
3345
3346
3347
3348 if (hard_reset) {
3349 spin_unlock_irq(adapter->scsi_host->host_lock);
3350 blogic_delay(adapter->bus_settle_time);
3351 spin_lock_irq(adapter->scsi_host->host_lock);
3352 }
3353
3354 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
3355 adapter->last_resettried[tgt_id] = jiffies;
3356 adapter->last_resetdone[tgt_id] = jiffies;
3357 }
3358 return SUCCESS;
3359}
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378static int blogic_diskparam(struct scsi_device *sdev, struct block_device *dev,
3379 sector_t capacity, int *params)
3380{
3381 struct blogic_adapter *adapter =
3382 (struct blogic_adapter *) sdev->host->hostdata;
3383 struct bios_diskparam *diskparam = (struct bios_diskparam *) params;
3384 unsigned char *buf;
3385
3386 if (adapter->ext_trans_enable && capacity >= 2 * 1024 * 1024 ) {
3387 if (capacity >= 4 * 1024 * 1024 ) {
3388 diskparam->heads = 255;
3389 diskparam->sectors = 63;
3390 } else {
3391 diskparam->heads = 128;
3392 diskparam->sectors = 32;
3393 }
3394 } else {
3395 diskparam->heads = 64;
3396 diskparam->sectors = 32;
3397 }
3398 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3399 buf = scsi_bios_ptable(dev);
3400 if (buf == NULL)
3401 return 0;
3402
3403
3404
3405
3406
3407 if (*(unsigned short *) (buf + 64) == 0xAA55) {
3408 struct partition *part1_entry = (struct partition *) buf;
3409 struct partition *part_entry = part1_entry;
3410 int saved_cyl = diskparam->cylinders, part_no;
3411 unsigned char part_end_head = 0, part_end_sector = 0;
3412
3413 for (part_no = 0; part_no < 4; part_no++) {
3414 part_end_head = part_entry->end_head;
3415 part_end_sector = part_entry->end_sector & 0x3F;
3416 if (part_end_head == 64 - 1) {
3417 diskparam->heads = 64;
3418 diskparam->sectors = 32;
3419 break;
3420 } else if (part_end_head == 128 - 1) {
3421 diskparam->heads = 128;
3422 diskparam->sectors = 32;
3423 break;
3424 } else if (part_end_head == 255 - 1) {
3425 diskparam->heads = 255;
3426 diskparam->sectors = 63;
3427 break;
3428 }
3429 part_entry++;
3430 }
3431 if (part_no == 4) {
3432 part_end_head = part1_entry->end_head;
3433 part_end_sector = part1_entry->end_sector & 0x3F;
3434 }
3435 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3436 if (part_no < 4 && part_end_sector == diskparam->sectors) {
3437 if (diskparam->cylinders != saved_cyl)
3438 blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
3439 } else if (part_end_head > 0 || part_end_sector > 0) {
3440 blogic_warn("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
3441 blogic_warn("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
3442 }
3443 }
3444 kfree(buf);
3445 return 0;
3446}
3447
3448
3449
3450
3451
3452
3453static int blogic_write_info(struct Scsi_Host *shost, char *procbuf,
3454 int bytes_avail)
3455{
3456 struct blogic_adapter *adapter =
3457 (struct blogic_adapter *) shost->hostdata;
3458 struct blogic_tgt_stats *tgt_stats;
3459
3460 tgt_stats = adapter->tgt_stats;
3461 adapter->ext_resets = 0;
3462 adapter->adapter_intern_errors = 0;
3463 memset(tgt_stats, 0, BLOGIC_MAXDEV * sizeof(struct blogic_tgt_stats));
3464 return 0;
3465}
3466
3467static int blogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
3468{
3469 struct blogic_adapter *adapter = (struct blogic_adapter *) shost->hostdata;
3470 struct blogic_tgt_stats *tgt_stats;
3471 int tgt;
3472
3473 tgt_stats = adapter->tgt_stats;
3474 seq_write(m, adapter->msgbuf, adapter->msgbuflen);
3475 seq_printf(m, "\n\
3476Current Driver Queue Depth: %d\n\
3477Currently Allocated CCBs: %d\n", adapter->drvr_qdepth, adapter->alloc_ccbs);
3478 seq_printf(m, "\n\n\
3479 DATA TRANSFER STATISTICS\n\
3480\n\
3481Target Tagged Queuing Queue Depth Active Attempted Completed\n\
3482====== ============== =========== ====== ========= =========\n");
3483 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3484 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3485 if (!tgt_flags->tgt_exists)
3486 continue;
3487 seq_printf(m, " %2d %s", tgt, (tgt_flags->tagq_ok ? (tgt_flags->tagq_active ? " Active" : (adapter->tagq_ok & (1 << tgt)
3488 ? " Permitted" : " Disabled"))
3489 : "Not Supported"));
3490 seq_printf(m,
3491 " %3d %3u %9u %9u\n", adapter->qdepth[tgt], adapter->active_cmds[tgt], tgt_stats[tgt].cmds_tried, tgt_stats[tgt].cmds_complete);
3492 }
3493 seq_printf(m, "\n\
3494Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
3495====== ============= ============== =================== ===================\n");
3496 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3497 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3498 if (!tgt_flags->tgt_exists)
3499 continue;
3500 seq_printf(m, " %2d %9u %9u", tgt, tgt_stats[tgt].read_cmds, tgt_stats[tgt].write_cmds);
3501 if (tgt_stats[tgt].bytesread.billions > 0)
3502 seq_printf(m, " %9u%09u", tgt_stats[tgt].bytesread.billions, tgt_stats[tgt].bytesread.units);
3503 else
3504 seq_printf(m, " %9u", tgt_stats[tgt].bytesread.units);
3505 if (tgt_stats[tgt].byteswritten.billions > 0)
3506 seq_printf(m, " %9u%09u\n", tgt_stats[tgt].byteswritten.billions, tgt_stats[tgt].byteswritten.units);
3507 else
3508 seq_printf(m, " %9u\n", tgt_stats[tgt].byteswritten.units);
3509 }
3510 seq_printf(m, "\n\
3511Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
3512====== ======= ========= ========= ========= ========= =========\n");
3513 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3514 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3515 if (!tgt_flags->tgt_exists)
3516 continue;
3517 seq_printf(m,
3518 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3519 tgt_stats[tgt].read_sz_buckets[0],
3520 tgt_stats[tgt].read_sz_buckets[1], tgt_stats[tgt].read_sz_buckets[2], tgt_stats[tgt].read_sz_buckets[3], tgt_stats[tgt].read_sz_buckets[4]);
3521 seq_printf(m,
3522 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3523 tgt_stats[tgt].write_sz_buckets[0],
3524 tgt_stats[tgt].write_sz_buckets[1], tgt_stats[tgt].write_sz_buckets[2], tgt_stats[tgt].write_sz_buckets[3], tgt_stats[tgt].write_sz_buckets[4]);
3525 }
3526 seq_printf(m, "\n\
3527Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
3528====== ======= ========= ========= ========= ========= =========\n");
3529 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3530 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3531 if (!tgt_flags->tgt_exists)
3532 continue;
3533 seq_printf(m,
3534 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3535 tgt_stats[tgt].read_sz_buckets[5],
3536 tgt_stats[tgt].read_sz_buckets[6], tgt_stats[tgt].read_sz_buckets[7], tgt_stats[tgt].read_sz_buckets[8], tgt_stats[tgt].read_sz_buckets[9]);
3537 seq_printf(m,
3538 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3539 tgt_stats[tgt].write_sz_buckets[5],
3540 tgt_stats[tgt].write_sz_buckets[6], tgt_stats[tgt].write_sz_buckets[7], tgt_stats[tgt].write_sz_buckets[8], tgt_stats[tgt].write_sz_buckets[9]);
3541 }
3542 seq_printf(m, "\n\n\
3543 ERROR RECOVERY STATISTICS\n\
3544\n\
3545 Command Aborts Bus Device Resets Host Adapter Resets\n\
3546Target Requested Completed Requested Completed Requested Completed\n\
3547 ID \\\\\\\\ Attempted
3548====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
3549 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3550 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3551 if (!tgt_flags->tgt_exists)
3552 continue;
3553 seq_printf(m, "\
3554 %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", tgt, tgt_stats[tgt].aborts_request, tgt_stats[tgt].aborts_tried, tgt_stats[tgt].aborts_done, tgt_stats[tgt].bdr_request, tgt_stats[tgt].bdr_tried, tgt_stats[tgt].bdr_done, tgt_stats[tgt].adatper_reset_req, tgt_stats[tgt].adapter_reset_attempt, tgt_stats[tgt].adapter_reset_done);
3555 }
3556 seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
3557 seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
3558 return 0;
3559}
3560
3561
3562
3563
3564
3565
3566static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
3567 struct blogic_adapter *adapter, ...)
3568{
3569 static char buf[BLOGIC_LINEBUF_SIZE];
3570 static bool begin = true;
3571 va_list args;
3572 int len = 0;
3573
3574 va_start(args, adapter);
3575 len = vsprintf(buf, fmt, args);
3576 va_end(args);
3577 if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
3578 static int msglines = 0;
3579 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3580 adapter->msgbuflen += len;
3581 if (++msglines <= 2)
3582 printk("%sscsi: %s", blogic_msglevelmap[msglevel], buf);
3583 } else if (msglevel == BLOGIC_INFO_LEVEL) {
3584 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3585 adapter->msgbuflen += len;
3586 if (begin) {
3587 if (buf[0] != '\n' || len > 1)
3588 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
3589 } else
3590 printk("%s", buf);
3591 } else {
3592 if (begin) {
3593 if (adapter != NULL && adapter->adapter_initd)
3594 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
3595 else
3596 printk("%s%s", blogic_msglevelmap[msglevel], buf);
3597 } else
3598 printk("%s", buf);
3599 }
3600 begin = (buf[len - 1] == '\n');
3601}
3602
3603
3604
3605
3606
3607
3608
3609static bool __init blogic_parse(char **str, char *keyword)
3610{
3611 char *pointer = *str;
3612 while (*keyword != '\0') {
3613 char strch = *pointer++;
3614 char keywordch = *keyword++;
3615 if (strch >= 'A' && strch <= 'Z')
3616 strch += 'a' - 'Z';
3617 if (keywordch >= 'A' && keywordch <= 'Z')
3618 keywordch += 'a' - 'Z';
3619 if (strch != keywordch)
3620 return false;
3621 }
3622 *str = pointer;
3623 return true;
3624}
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644static int __init blogic_parseopts(char *options)
3645{
3646 while (true) {
3647 struct blogic_drvr_options *drvr_opts =
3648 &blogic_drvr_options[blogic_drvr_options_count++];
3649 int tgt_id;
3650
3651 memset(drvr_opts, 0, sizeof(struct blogic_drvr_options));
3652 while (*options != '\0' && *options != ';') {
3653
3654 if (blogic_parse(&options, "IO:")) {
3655 unsigned long io_addr = simple_strtoul(options,
3656 &options, 0);
3657 blogic_probe_options.limited_isa = true;
3658 switch (io_addr) {
3659 case 0x330:
3660 blogic_probe_options.probe330 = true;
3661 break;
3662 case 0x334:
3663 blogic_probe_options.probe334 = true;
3664 break;
3665 case 0x230:
3666 blogic_probe_options.probe230 = true;
3667 break;
3668 case 0x234:
3669 blogic_probe_options.probe234 = true;
3670 break;
3671 case 0x130:
3672 blogic_probe_options.probe130 = true;
3673 break;
3674 case 0x134:
3675 blogic_probe_options.probe134 = true;
3676 break;
3677 default:
3678 blogic_err("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, io_addr);
3679 return 0;
3680 }
3681 } else if (blogic_parse(&options, "NoProbeISA"))
3682 blogic_probe_options.noprobe_isa = true;
3683 else if (blogic_parse(&options, "NoProbePCI"))
3684 blogic_probe_options.noprobe_pci = true;
3685 else if (blogic_parse(&options, "NoProbe"))
3686 blogic_probe_options.noprobe = true;
3687 else if (blogic_parse(&options, "NoSortPCI"))
3688 blogic_probe_options.nosort_pci = true;
3689 else if (blogic_parse(&options, "MultiMasterFirst"))
3690 blogic_probe_options.multimaster_first = true;
3691 else if (blogic_parse(&options, "FlashPointFirst"))
3692 blogic_probe_options.flashpoint_first = true;
3693
3694 else if (blogic_parse(&options, "QueueDepth:[") ||
3695 blogic_parse(&options, "QD:[")) {
3696 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
3697 unsigned short qdepth = simple_strtoul(options, &options, 0);
3698 if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
3699 blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
3700 return 0;
3701 }
3702 drvr_opts->qdepth[tgt_id] = qdepth;
3703 if (*options == ',')
3704 options++;
3705 else if (*options == ']')
3706 break;
3707 else {
3708 blogic_err("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, options);
3709 return 0;
3710 }
3711 }
3712 if (*options != ']') {
3713 blogic_err("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, options);
3714 return 0;
3715 } else
3716 options++;
3717 } else if (blogic_parse(&options, "QueueDepth:") || blogic_parse(&options, "QD:")) {
3718 unsigned short qdepth = simple_strtoul(options, &options, 0);
3719 if (qdepth == 0 ||
3720 qdepth > BLOGIC_MAX_TAG_DEPTH) {
3721 blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
3722 return 0;
3723 }
3724 drvr_opts->common_qdepth = qdepth;
3725 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3726 drvr_opts->qdepth[tgt_id] = qdepth;
3727 } else if (blogic_parse(&options, "TaggedQueuing:") ||
3728 blogic_parse(&options, "TQ:")) {
3729 if (blogic_parse(&options, "Default")) {
3730 drvr_opts->tagq_ok = 0x0000;
3731 drvr_opts->tagq_ok_mask = 0x0000;
3732 } else if (blogic_parse(&options, "Enable")) {
3733 drvr_opts->tagq_ok = 0xFFFF;
3734 drvr_opts->tagq_ok_mask = 0xFFFF;
3735 } else if (blogic_parse(&options, "Disable")) {
3736 drvr_opts->tagq_ok = 0x0000;
3737 drvr_opts->tagq_ok_mask = 0xFFFF;
3738 } else {
3739 unsigned short tgt_bit;
3740 for (tgt_id = 0, tgt_bit = 1;
3741 tgt_id < BLOGIC_MAXDEV;
3742 tgt_id++, tgt_bit <<= 1)
3743 switch (*options++) {
3744 case 'Y':
3745 drvr_opts->tagq_ok |= tgt_bit;
3746 drvr_opts->tagq_ok_mask |= tgt_bit;
3747 break;
3748 case 'N':
3749 drvr_opts->tagq_ok &= ~tgt_bit;
3750 drvr_opts->tagq_ok_mask |= tgt_bit;
3751 break;
3752 case 'X':
3753 break;
3754 default:
3755 options--;
3756 tgt_id = BLOGIC_MAXDEV;
3757 break;
3758 }
3759 }
3760 }
3761
3762 else if (blogic_parse(&options, "BusSettleTime:") ||
3763 blogic_parse(&options, "BST:")) {
3764 unsigned short bus_settle_time =
3765 simple_strtoul(options, &options, 0);
3766 if (bus_settle_time > 5 * 60) {
3767 blogic_err("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
3768 return 0;
3769 }
3770 drvr_opts->bus_settle_time = bus_settle_time;
3771 } else if (blogic_parse(&options,
3772 "InhibitTargetInquiry"))
3773 drvr_opts->stop_tgt_inquiry = true;
3774
3775 else if (blogic_parse(&options, "TraceProbe"))
3776 blogic_global_options.trace_probe = true;
3777 else if (blogic_parse(&options, "TraceHardwareReset"))
3778 blogic_global_options.trace_hw_reset = true;
3779 else if (blogic_parse(&options, "TraceConfiguration"))
3780 blogic_global_options.trace_config = true;
3781 else if (blogic_parse(&options, "TraceErrors"))
3782 blogic_global_options.trace_err = true;
3783 else if (blogic_parse(&options, "Debug")) {
3784 blogic_global_options.trace_probe = true;
3785 blogic_global_options.trace_hw_reset = true;
3786 blogic_global_options.trace_config = true;
3787 blogic_global_options.trace_err = true;
3788 }
3789 if (*options == ',')
3790 options++;
3791 else if (*options != ';' && *options != '\0') {
3792 blogic_err("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, options);
3793 *options = '\0';
3794 }
3795 }
3796 if (!(blogic_drvr_options_count == 0 ||
3797 blogic_probeinfo_count == 0 ||
3798 blogic_drvr_options_count == blogic_probeinfo_count)) {
3799 blogic_err("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
3800 return 0;
3801 }
3802
3803
3804
3805
3806 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3807 if (drvr_opts->qdepth[tgt_id] == 1) {
3808 unsigned short tgt_bit = 1 << tgt_id;
3809 drvr_opts->tagq_ok &= ~tgt_bit;
3810 drvr_opts->tagq_ok_mask |= tgt_bit;
3811 }
3812 if (*options == ';')
3813 options++;
3814 if (*options == '\0')
3815 return 0;
3816 }
3817 return 1;
3818}
3819
3820
3821
3822
3823
3824static struct scsi_host_template blogic_template = {
3825 .module = THIS_MODULE,
3826 .proc_name = "BusLogic",
3827 .write_info = blogic_write_info,
3828 .show_info = blogic_show_info,
3829 .name = "BusLogic",
3830 .info = blogic_drvr_info,
3831 .queuecommand = blogic_qcmd,
3832 .slave_configure = blogic_slaveconfig,
3833 .bios_param = blogic_diskparam,
3834 .eh_host_reset_handler = blogic_hostreset,
3835#if 0
3836 .eh_abort_handler = blogic_abort,
3837#endif
3838 .unchecked_isa_dma = 1,
3839 .max_sectors = 128,
3840 .use_clustering = ENABLE_CLUSTERING,
3841};
3842
3843
3844
3845
3846
3847static int __init blogic_setup(char *str)
3848{
3849 int ints[3];
3850
3851 (void) get_options(str, ARRAY_SIZE(ints), ints);
3852
3853 if (ints[0] != 0) {
3854 blogic_err("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
3855 return 0;
3856 }
3857 if (str == NULL || *str == '\0')
3858 return 0;
3859 return blogic_parseopts(str);
3860}
3861
3862
3863
3864
3865
3866static void __exit blogic_exit(void)
3867{
3868 struct blogic_adapter *ha, *next;
3869
3870 list_for_each_entry_safe(ha, next, &blogic_host_list, host_list)
3871 blogic_deladapter(ha);
3872}
3873
3874__setup("BusLogic=", blogic_setup);
3875
3876#ifdef MODULE
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = {
3887 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
3888 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
3889 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
3890 {0, },
3891};
3892#endif
3893MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
3894
3895module_init(blogic_init);
3896module_exit(blogic_exit);
3897