0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #define blogic_drvr_version "2.1.17"
0023 #define blogic_drvr_date "12 September 2013"
0024
0025 #include <linux/module.h>
0026 #include <linux/init.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/types.h>
0029 #include <linux/blkdev.h>
0030 #include <linux/delay.h>
0031 #include <linux/ioport.h>
0032 #include <linux/mm.h>
0033 #include <linux/stat.h>
0034 #include <linux/pci.h>
0035 #include <linux/spinlock.h>
0036 #include <linux/jiffies.h>
0037 #include <linux/dma-mapping.h>
0038 #include <linux/slab.h>
0039 #include <linux/msdos_partition.h>
0040 #include <scsi/scsicam.h>
0041
0042 #include <asm/dma.h>
0043 #include <asm/io.h>
0044
0045 #include <scsi/scsi.h>
0046 #include <scsi/scsi_cmnd.h>
0047 #include <scsi/scsi_device.h>
0048 #include <scsi/scsi_host.h>
0049 #include <scsi/scsi_tcq.h>
0050 #include "BusLogic.h"
0051 #include "FlashPoint.c"
0052
0053 #ifndef FAILURE
0054 #define FAILURE (-1)
0055 #endif
0056
0057 static struct scsi_host_template blogic_template;
0058
0059
0060
0061
0062
0063
0064
0065 static int blogic_drvr_options_count;
0066
0067
0068
0069
0070
0071
0072
0073
0074 static struct blogic_drvr_options blogic_drvr_options[BLOGIC_MAX_ADAPTERS];
0075
0076
0077
0078
0079
0080
0081 MODULE_LICENSE("GPL");
0082 #ifdef MODULE
0083 static char *BusLogic;
0084 module_param(BusLogic, charp, 0);
0085 #endif
0086
0087
0088
0089
0090
0091
0092
0093 static struct blogic_probe_options blogic_probe_options;
0094
0095
0096
0097
0098
0099
0100
0101 static struct blogic_global_options blogic_global_options;
0102
0103 static LIST_HEAD(blogic_host_list);
0104
0105
0106
0107
0108
0109 static int blogic_probeinfo_count;
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 static struct blogic_probeinfo *blogic_probeinfo_list;
0120
0121
0122
0123
0124
0125
0126
0127
0128 static char *blogic_cmd_failure_reason;
0129
0130
0131
0132
0133
0134
0135 static void blogic_announce_drvr(struct blogic_adapter *adapter)
0136 {
0137 blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
0138 blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>\n", adapter);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147 static const char *blogic_drvr_info(struct Scsi_Host *host)
0148 {
0149 struct blogic_adapter *adapter =
0150 (struct blogic_adapter *) host->hostdata;
0151 return adapter->full_model;
0152 }
0153
0154
0155
0156
0157
0158
0159
0160 static void blogic_init_ccbs(struct blogic_adapter *adapter, void *blk_pointer,
0161 int blk_size, dma_addr_t blkp)
0162 {
0163 struct blogic_ccb *ccb = (struct blogic_ccb *) blk_pointer;
0164 unsigned int offset = 0;
0165 memset(blk_pointer, 0, blk_size);
0166 ccb->allocgrp_head = blkp;
0167 ccb->allocgrp_size = blk_size;
0168 while ((blk_size -= sizeof(struct blogic_ccb)) >= 0) {
0169 ccb->status = BLOGIC_CCB_FREE;
0170 ccb->adapter = adapter;
0171 ccb->dma_handle = (u32) blkp + offset;
0172 if (blogic_flashpoint_type(adapter)) {
0173 ccb->callback = blogic_qcompleted_ccb;
0174 ccb->base_addr = adapter->fpinfo.base_addr;
0175 }
0176 ccb->next = adapter->free_ccbs;
0177 ccb->next_all = adapter->all_ccbs;
0178 adapter->free_ccbs = ccb;
0179 adapter->all_ccbs = ccb;
0180 adapter->alloc_ccbs++;
0181 ccb++;
0182 offset += sizeof(struct blogic_ccb);
0183 }
0184 }
0185
0186
0187
0188
0189
0190
0191 static bool __init blogic_create_initccbs(struct blogic_adapter *adapter)
0192 {
0193 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
0194 void *blk_pointer;
0195 dma_addr_t blkp;
0196
0197 while (adapter->alloc_ccbs < adapter->initccbs) {
0198 blk_pointer = dma_alloc_coherent(&adapter->pci_device->dev,
0199 blk_size, &blkp, GFP_KERNEL);
0200 if (blk_pointer == NULL) {
0201 blogic_err("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
0202 adapter);
0203 return false;
0204 }
0205 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
0206 }
0207 return true;
0208 }
0209
0210
0211
0212
0213
0214
0215 static void blogic_destroy_ccbs(struct blogic_adapter *adapter)
0216 {
0217 struct blogic_ccb *next_ccb = adapter->all_ccbs, *ccb, *lastccb = NULL;
0218 adapter->all_ccbs = NULL;
0219 adapter->free_ccbs = NULL;
0220 while ((ccb = next_ccb) != NULL) {
0221 next_ccb = ccb->next_all;
0222 if (ccb->allocgrp_head) {
0223 if (lastccb)
0224 dma_free_coherent(&adapter->pci_device->dev,
0225 lastccb->allocgrp_size, lastccb,
0226 lastccb->allocgrp_head);
0227 lastccb = ccb;
0228 }
0229 }
0230 if (lastccb)
0231 dma_free_coherent(&adapter->pci_device->dev,
0232 lastccb->allocgrp_size, lastccb,
0233 lastccb->allocgrp_head);
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 static void blogic_create_addlccbs(struct blogic_adapter *adapter,
0245 int addl_ccbs, bool print_success)
0246 {
0247 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
0248 int prev_alloc = adapter->alloc_ccbs;
0249 void *blk_pointer;
0250 dma_addr_t blkp;
0251 if (addl_ccbs <= 0)
0252 return;
0253 while (adapter->alloc_ccbs - prev_alloc < addl_ccbs) {
0254 blk_pointer = dma_alloc_coherent(&adapter->pci_device->dev,
0255 blk_size, &blkp, GFP_KERNEL);
0256 if (blk_pointer == NULL)
0257 break;
0258 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
0259 }
0260 if (adapter->alloc_ccbs > prev_alloc) {
0261 if (print_success)
0262 blogic_notice("Allocated %d additional CCBs (total now %d)\n", adapter, adapter->alloc_ccbs - prev_alloc, adapter->alloc_ccbs);
0263 return;
0264 }
0265 blogic_notice("Failed to allocate additional CCBs\n", adapter);
0266 if (adapter->drvr_qdepth > adapter->alloc_ccbs - adapter->tgt_count) {
0267 adapter->drvr_qdepth = adapter->alloc_ccbs - adapter->tgt_count;
0268 adapter->scsi_host->can_queue = adapter->drvr_qdepth;
0269 }
0270 }
0271
0272
0273
0274
0275
0276
0277
0278 static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
0279 {
0280 static unsigned long serial;
0281 struct blogic_ccb *ccb;
0282 ccb = adapter->free_ccbs;
0283 if (ccb != NULL) {
0284 ccb->serial = ++serial;
0285 adapter->free_ccbs = ccb->next;
0286 ccb->next = NULL;
0287 if (adapter->free_ccbs == NULL)
0288 blogic_create_addlccbs(adapter, adapter->inc_ccbs,
0289 true);
0290 return ccb;
0291 }
0292 blogic_create_addlccbs(adapter, adapter->inc_ccbs, true);
0293 ccb = adapter->free_ccbs;
0294 if (ccb == NULL)
0295 return NULL;
0296 ccb->serial = ++serial;
0297 adapter->free_ccbs = ccb->next;
0298 ccb->next = NULL;
0299 return ccb;
0300 }
0301
0302
0303
0304
0305
0306
0307
0308
0309 static void blogic_dealloc_ccb(struct blogic_ccb *ccb, int dma_unmap)
0310 {
0311 struct blogic_adapter *adapter = ccb->adapter;
0312
0313 if (ccb->command != NULL)
0314 scsi_dma_unmap(ccb->command);
0315 if (dma_unmap)
0316 dma_unmap_single(&adapter->pci_device->dev, ccb->sensedata,
0317 ccb->sense_datalen, DMA_FROM_DEVICE);
0318
0319 ccb->command = NULL;
0320 ccb->status = BLOGIC_CCB_FREE;
0321 ccb->next = adapter->free_ccbs;
0322 adapter->free_ccbs = ccb;
0323 }
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344 static int blogic_cmd(struct blogic_adapter *adapter, enum blogic_opcode opcode,
0345 void *param, int paramlen, void *reply, int replylen)
0346 {
0347 unsigned char *param_p = (unsigned char *) param;
0348 unsigned char *reply_p = (unsigned char *) reply;
0349 union blogic_stat_reg statusreg;
0350 union blogic_int_reg intreg;
0351 unsigned long processor_flag = 0;
0352 int reply_b = 0, result;
0353 long timeout;
0354
0355
0356
0357 if (replylen > 0)
0358 memset(reply, 0, replylen);
0359
0360
0361
0362
0363
0364
0365
0366 if (!adapter->irq_acquired)
0367 local_irq_save(processor_flag);
0368
0369
0370
0371
0372
0373 timeout = 10000;
0374 while (--timeout >= 0) {
0375 statusreg.all = blogic_rdstatus(adapter);
0376 if (statusreg.sr.adapter_ready && !statusreg.sr.cmd_param_busy)
0377 break;
0378 udelay(100);
0379 }
0380 if (timeout < 0) {
0381 blogic_cmd_failure_reason =
0382 "Timeout waiting for Host Adapter Ready";
0383 result = -2;
0384 goto done;
0385 }
0386
0387
0388
0389 adapter->adapter_cmd_complete = false;
0390 blogic_setcmdparam(adapter, opcode);
0391
0392
0393
0394 timeout = 10000;
0395 while (paramlen > 0 && --timeout >= 0) {
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 udelay(100);
0412 intreg.all = blogic_rdint(adapter);
0413 statusreg.all = blogic_rdstatus(adapter);
0414 if (intreg.ir.cmd_complete)
0415 break;
0416 if (adapter->adapter_cmd_complete)
0417 break;
0418 if (statusreg.sr.datain_ready)
0419 break;
0420 if (statusreg.sr.cmd_param_busy)
0421 continue;
0422 blogic_setcmdparam(adapter, *param_p++);
0423 paramlen--;
0424 }
0425 if (timeout < 0) {
0426 blogic_cmd_failure_reason =
0427 "Timeout waiting for Parameter Acceptance";
0428 result = -2;
0429 goto done;
0430 }
0431
0432
0433
0434
0435 if (opcode == BLOGIC_MOD_IOADDR) {
0436 statusreg.all = blogic_rdstatus(adapter);
0437 if (statusreg.sr.cmd_invalid) {
0438 blogic_cmd_failure_reason =
0439 "Modify I/O Address Invalid";
0440 result = -1;
0441 goto done;
0442 }
0443 if (blogic_global_options.trace_config)
0444 blogic_notice("blogic_cmd(%02X) Status = %02X: (Modify I/O Address)\n", adapter, opcode, statusreg.all);
0445 result = 0;
0446 goto done;
0447 }
0448
0449
0450
0451 switch (opcode) {
0452 case BLOGIC_INQ_DEV0TO7:
0453 case BLOGIC_INQ_DEV8TO15:
0454 case BLOGIC_INQ_DEV:
0455
0456 timeout = 60 * 10000;
0457 break;
0458 default:
0459
0460 timeout = 10000;
0461 break;
0462 }
0463
0464
0465
0466
0467
0468
0469 while (--timeout >= 0) {
0470 intreg.all = blogic_rdint(adapter);
0471 statusreg.all = blogic_rdstatus(adapter);
0472 if (intreg.ir.cmd_complete)
0473 break;
0474 if (adapter->adapter_cmd_complete)
0475 break;
0476 if (statusreg.sr.datain_ready) {
0477 if (++reply_b <= replylen)
0478 *reply_p++ = blogic_rddatain(adapter);
0479 else
0480 blogic_rddatain(adapter);
0481 }
0482 if (opcode == BLOGIC_FETCH_LOCALRAM &&
0483 statusreg.sr.adapter_ready)
0484 break;
0485 udelay(100);
0486 }
0487 if (timeout < 0) {
0488 blogic_cmd_failure_reason =
0489 "Timeout waiting for Command Complete";
0490 result = -2;
0491 goto done;
0492 }
0493
0494
0495
0496 blogic_intreset(adapter);
0497
0498
0499
0500 if (blogic_global_options.trace_config) {
0501 int i;
0502 blogic_notice("blogic_cmd(%02X) Status = %02X: %2d ==> %2d:",
0503 adapter, opcode, statusreg.all, replylen,
0504 reply_b);
0505 if (replylen > reply_b)
0506 replylen = reply_b;
0507 for (i = 0; i < replylen; i++)
0508 blogic_notice(" %02X", adapter,
0509 ((unsigned char *) reply)[i]);
0510 blogic_notice("\n", adapter);
0511 }
0512
0513
0514
0515 if (statusreg.sr.cmd_invalid) {
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 udelay(1000);
0526 statusreg.all = blogic_rdstatus(adapter);
0527 if (statusreg.sr.cmd_invalid || statusreg.sr.rsvd ||
0528 statusreg.sr.datain_ready ||
0529 statusreg.sr.cmd_param_busy ||
0530 !statusreg.sr.adapter_ready ||
0531 !statusreg.sr.init_reqd ||
0532 statusreg.sr.diag_active ||
0533 statusreg.sr.diag_failed) {
0534 blogic_softreset(adapter);
0535 udelay(1000);
0536 }
0537 blogic_cmd_failure_reason = "Command Invalid";
0538 result = -1;
0539 goto done;
0540 }
0541
0542
0543
0544 if (paramlen > 0) {
0545 blogic_cmd_failure_reason = "Excess Parameters Supplied";
0546 result = -1;
0547 goto done;
0548 }
0549
0550
0551
0552 blogic_cmd_failure_reason = NULL;
0553 result = reply_b;
0554
0555
0556
0557 done:
0558 if (!adapter->irq_acquired)
0559 local_irq_restore(processor_flag);
0560 return result;
0561 }
0562
0563
0564
0565
0566
0567
0568
0569 static void __init blogic_sort_probeinfo(struct blogic_probeinfo
0570 *probeinfo_list, int probeinfo_cnt)
0571 {
0572 int last_exchange = probeinfo_cnt - 1, bound, j;
0573
0574 while (last_exchange > 0) {
0575 bound = last_exchange;
0576 last_exchange = 0;
0577 for (j = 0; j < bound; j++) {
0578 struct blogic_probeinfo *probeinfo1 =
0579 &probeinfo_list[j];
0580 struct blogic_probeinfo *probeinfo2 =
0581 &probeinfo_list[j + 1];
0582 if (probeinfo1->bus > probeinfo2->bus ||
0583 (probeinfo1->bus == probeinfo2->bus &&
0584 (probeinfo1->dev > probeinfo2->dev))) {
0585 struct blogic_probeinfo tmp_probeinfo;
0586
0587 memcpy(&tmp_probeinfo, probeinfo1,
0588 sizeof(struct blogic_probeinfo));
0589 memcpy(probeinfo1, probeinfo2,
0590 sizeof(struct blogic_probeinfo));
0591 memcpy(probeinfo2, &tmp_probeinfo,
0592 sizeof(struct blogic_probeinfo));
0593 last_exchange = j;
0594 }
0595 }
0596 }
0597 }
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608 static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
0609 {
0610 struct blogic_probeinfo *pr_probeinfo =
0611 &blogic_probeinfo_list[blogic_probeinfo_count];
0612 int nonpr_mmindex = blogic_probeinfo_count + 1;
0613 int nonpr_mmcount = 0, mmcount = 0;
0614 bool force_scan_order = false;
0615 bool force_scan_order_checked = false;
0616 struct pci_dev *pci_device = NULL;
0617 int i;
0618 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
0619 return 0;
0620 blogic_probeinfo_count++;
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635 pr_probeinfo->io_addr = 0;
0636 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
0637 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
0638 pci_device)) != NULL) {
0639 struct blogic_adapter *host_adapter = adapter;
0640 struct blogic_adapter_info adapter_info;
0641 enum blogic_isa_ioport mod_ioaddr_req;
0642 unsigned char bus;
0643 unsigned char device;
0644 unsigned int irq_ch;
0645 unsigned long base_addr0;
0646 unsigned long base_addr1;
0647 unsigned long io_addr;
0648 unsigned long pci_addr;
0649
0650 if (pci_enable_device(pci_device))
0651 continue;
0652
0653 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
0654 continue;
0655
0656 bus = pci_device->bus->number;
0657 device = pci_device->devfn >> 3;
0658 irq_ch = pci_device->irq;
0659 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
0660 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
0661
0662 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
0663 blogic_err("BusLogic: Base Address0 0x%lX not I/O for MultiMaster Host Adapter\n", NULL, base_addr0);
0664 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
0665 continue;
0666 }
0667 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
0668 blogic_err("BusLogic: Base Address1 0x%lX not Memory for MultiMaster Host Adapter\n", NULL, base_addr1);
0669 blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
0670 continue;
0671 }
0672 if (irq_ch == 0) {
0673 blogic_err("BusLogic: IRQ Channel %d invalid for MultiMaster Host Adapter\n", NULL, irq_ch);
0674 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
0675 continue;
0676 }
0677 if (blogic_global_options.trace_probe) {
0678 blogic_notice("BusLogic: PCI MultiMaster Host Adapter detected at\n", NULL);
0679 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX\n", NULL, bus, device, io_addr, pci_addr);
0680 }
0681
0682
0683
0684
0685
0686
0687 host_adapter->io_addr = io_addr;
0688 blogic_intreset(host_adapter);
0689 if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
0690 &adapter_info, sizeof(adapter_info)) !=
0691 sizeof(adapter_info))
0692 adapter_info.isa_port = BLOGIC_IO_DISABLE;
0693
0694
0695
0696
0697
0698
0699
0700
0701 mod_ioaddr_req = BLOGIC_IO_DISABLE;
0702 blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
0703 sizeof(mod_ioaddr_req), NULL, 0);
0704
0705
0706
0707
0708
0709
0710
0711
0712 if (!force_scan_order_checked) {
0713 struct blogic_fetch_localram fetch_localram;
0714 struct blogic_autoscsi_byte45 autoscsi_byte45;
0715 struct blogic_board_id id;
0716
0717 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
0718 fetch_localram.count = sizeof(autoscsi_byte45);
0719 blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM,
0720 &fetch_localram, sizeof(fetch_localram),
0721 &autoscsi_byte45,
0722 sizeof(autoscsi_byte45));
0723 blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0,
0724 &id, sizeof(id));
0725 if (id.fw_ver_digit1 == '5')
0726 force_scan_order =
0727 autoscsi_byte45.force_scan_order;
0728 force_scan_order_checked = true;
0729 }
0730
0731
0732
0733
0734
0735
0736
0737
0738 if (adapter_info.isa_port == BLOGIC_IO_330) {
0739 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
0740 pr_probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
0741 pr_probeinfo->io_addr = io_addr;
0742 pr_probeinfo->pci_addr = pci_addr;
0743 pr_probeinfo->bus = bus;
0744 pr_probeinfo->dev = device;
0745 pr_probeinfo->irq_ch = irq_ch;
0746 pr_probeinfo->pci_device = pci_dev_get(pci_device);
0747 mmcount++;
0748 } else if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
0749 struct blogic_probeinfo *probeinfo =
0750 &blogic_probeinfo_list[blogic_probeinfo_count++];
0751 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
0752 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
0753 probeinfo->io_addr = io_addr;
0754 probeinfo->pci_addr = pci_addr;
0755 probeinfo->bus = bus;
0756 probeinfo->dev = device;
0757 probeinfo->irq_ch = irq_ch;
0758 probeinfo->pci_device = pci_dev_get(pci_device);
0759 nonpr_mmcount++;
0760 mmcount++;
0761 } else
0762 blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
0763 }
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775 if (force_scan_order)
0776 blogic_sort_probeinfo(&blogic_probeinfo_list[nonpr_mmindex],
0777 nonpr_mmcount);
0778
0779
0780
0781
0782 pci_device = NULL;
0783 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
0784 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
0785 pci_device)) != NULL) {
0786 unsigned char bus;
0787 unsigned char device;
0788 unsigned int irq_ch;
0789 unsigned long io_addr;
0790
0791 if (pci_enable_device(pci_device))
0792 continue;
0793
0794 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
0795 continue;
0796
0797 bus = pci_device->bus->number;
0798 device = pci_device->devfn >> 3;
0799 irq_ch = pci_device->irq;
0800 io_addr = pci_resource_start(pci_device, 0);
0801
0802 if (io_addr == 0 || irq_ch == 0)
0803 continue;
0804 for (i = 0; i < blogic_probeinfo_count; i++) {
0805 struct blogic_probeinfo *probeinfo =
0806 &blogic_probeinfo_list[i];
0807 if (probeinfo->io_addr == io_addr &&
0808 probeinfo->adapter_type == BLOGIC_MULTIMASTER) {
0809 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
0810 probeinfo->pci_addr = 0;
0811 probeinfo->bus = bus;
0812 probeinfo->dev = device;
0813 probeinfo->irq_ch = irq_ch;
0814 probeinfo->pci_device = pci_dev_get(pci_device);
0815 break;
0816 }
0817 }
0818 }
0819 return mmcount;
0820 }
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830 static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
0831 {
0832 int fpindex = blogic_probeinfo_count, fpcount = 0;
0833 struct pci_dev *pci_device = NULL;
0834
0835
0836
0837 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
0838 PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
0839 pci_device)) != NULL) {
0840 unsigned char bus;
0841 unsigned char device;
0842 unsigned int irq_ch;
0843 unsigned long base_addr0;
0844 unsigned long base_addr1;
0845 unsigned long io_addr;
0846 unsigned long pci_addr;
0847
0848 if (pci_enable_device(pci_device))
0849 continue;
0850
0851 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
0852 continue;
0853
0854 bus = pci_device->bus->number;
0855 device = pci_device->devfn >> 3;
0856 irq_ch = pci_device->irq;
0857 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
0858 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
0859 #ifdef CONFIG_SCSI_FLASHPOINT
0860 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
0861 blogic_err("BusLogic: Base Address0 0x%lX not I/O for FlashPoint Host Adapter\n", NULL, base_addr0);
0862 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
0863 continue;
0864 }
0865 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
0866 blogic_err("BusLogic: Base Address1 0x%lX not Memory for FlashPoint Host Adapter\n", NULL, base_addr1);
0867 blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
0868 continue;
0869 }
0870 if (irq_ch == 0) {
0871 blogic_err("BusLogic: IRQ Channel %d invalid for FlashPoint Host Adapter\n", NULL, irq_ch);
0872 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
0873 continue;
0874 }
0875 if (blogic_global_options.trace_probe) {
0876 blogic_notice("BusLogic: FlashPoint Host Adapter detected at\n", NULL);
0877 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX\n", NULL, bus, device, io_addr, pci_addr);
0878 }
0879 if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
0880 struct blogic_probeinfo *probeinfo =
0881 &blogic_probeinfo_list[blogic_probeinfo_count++];
0882 probeinfo->adapter_type = BLOGIC_FLASHPOINT;
0883 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
0884 probeinfo->io_addr = io_addr;
0885 probeinfo->pci_addr = pci_addr;
0886 probeinfo->bus = bus;
0887 probeinfo->dev = device;
0888 probeinfo->irq_ch = irq_ch;
0889 probeinfo->pci_device = pci_dev_get(pci_device);
0890 fpcount++;
0891 } else
0892 blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
0893 #else
0894 blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", NULL, bus, device);
0895 blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, irq %d, but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
0896 blogic_err("BusLogic: support was omitted in this kernel configuration.\n", NULL);
0897 #endif
0898 }
0899
0900
0901
0902
0903
0904 blogic_sort_probeinfo(&blogic_probeinfo_list[fpindex], fpcount);
0905 return fpcount;
0906 }
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922 static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
0923 {
0924
0925
0926
0927
0928
0929 if (!blogic_probe_options.noprobe_pci) {
0930 if (blogic_probe_options.multimaster_first) {
0931 blogic_init_mm_probeinfo(adapter);
0932 blogic_init_fp_probeinfo(adapter);
0933 } else if (blogic_probe_options.flashpoint_first) {
0934 blogic_init_fp_probeinfo(adapter);
0935 blogic_init_mm_probeinfo(adapter);
0936 } else {
0937 int fpcount = blogic_init_fp_probeinfo(adapter);
0938 int mmcount = blogic_init_mm_probeinfo(adapter);
0939 if (fpcount > 0 && mmcount > 0) {
0940 struct blogic_probeinfo *probeinfo =
0941 &blogic_probeinfo_list[fpcount];
0942 struct blogic_adapter *myadapter = adapter;
0943 struct blogic_fetch_localram fetch_localram;
0944 struct blogic_bios_drvmap d0_mapbyte;
0945
0946 while (probeinfo->adapter_bus_type !=
0947 BLOGIC_PCI_BUS)
0948 probeinfo++;
0949 myadapter->io_addr = probeinfo->io_addr;
0950 fetch_localram.offset =
0951 BLOGIC_BIOS_BASE + BLOGIC_BIOS_DRVMAP;
0952 fetch_localram.count = sizeof(d0_mapbyte);
0953 blogic_cmd(myadapter, BLOGIC_FETCH_LOCALRAM,
0954 &fetch_localram,
0955 sizeof(fetch_localram),
0956 &d0_mapbyte,
0957 sizeof(d0_mapbyte));
0958
0959
0960
0961
0962
0963
0964
0965
0966 if (d0_mapbyte.diskgeom != BLOGIC_BIOS_NODISK) {
0967 struct blogic_probeinfo saved_probeinfo[BLOGIC_MAX_ADAPTERS];
0968 int mmcount = blogic_probeinfo_count - fpcount;
0969
0970 memcpy(saved_probeinfo,
0971 blogic_probeinfo_list,
0972 blogic_probeinfo_count * sizeof(struct blogic_probeinfo));
0973 memcpy(&blogic_probeinfo_list[0],
0974 &saved_probeinfo[fpcount],
0975 mmcount * sizeof(struct blogic_probeinfo));
0976 memcpy(&blogic_probeinfo_list[mmcount],
0977 &saved_probeinfo[0],
0978 fpcount * sizeof(struct blogic_probeinfo));
0979 }
0980 }
0981 }
0982 }
0983 }
0984
0985
0986
0987
0988
0989
0990 static bool blogic_failure(struct blogic_adapter *adapter, char *msg)
0991 {
0992 blogic_announce_drvr(adapter);
0993 if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
0994 blogic_err("While configuring BusLogic PCI Host Adapter at\n",
0995 adapter);
0996 blogic_err("Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
0997 } else
0998 blogic_err("While configuring BusLogic Host Adapter at I/O Address 0x%lX:\n", adapter, adapter->io_addr);
0999 blogic_err("%s FAILED - DETACHING\n", adapter, msg);
1000 if (blogic_cmd_failure_reason != NULL)
1001 blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
1002 blogic_cmd_failure_reason);
1003 return false;
1004 }
1005
1006
1007
1008
1009
1010
1011 static bool __init blogic_probe(struct blogic_adapter *adapter)
1012 {
1013 union blogic_stat_reg statusreg;
1014 union blogic_int_reg intreg;
1015 union blogic_geo_reg georeg;
1016
1017
1018
1019 if (blogic_flashpoint_type(adapter)) {
1020 struct fpoint_info *fpinfo = &adapter->fpinfo;
1021 fpinfo->base_addr = (u32) adapter->io_addr;
1022 fpinfo->irq_ch = adapter->irq_ch;
1023 fpinfo->present = false;
1024 if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
1025 fpinfo->present)) {
1026 blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
1027 blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
1028 blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
1029 return false;
1030 }
1031 if (blogic_global_options.trace_probe)
1032 blogic_notice("BusLogic_Probe(0x%lX): FlashPoint Found\n", adapter, adapter->io_addr);
1033
1034
1035
1036 return true;
1037 }
1038
1039
1040
1041
1042
1043
1044
1045 statusreg.all = blogic_rdstatus(adapter);
1046 intreg.all = blogic_rdint(adapter);
1047 georeg.all = blogic_rdgeom(adapter);
1048 if (blogic_global_options.trace_probe)
1049 blogic_notice("BusLogic_Probe(0x%lX): Status 0x%02X, Interrupt 0x%02X, Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
1050 if (statusreg.all == 0 || statusreg.sr.diag_active ||
1051 statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
1052 statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
1053 return false;
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 if (georeg.all == 0xFF)
1071 return false;
1072
1073
1074
1075 return true;
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 static bool blogic_hwreset(struct blogic_adapter *adapter, bool hard_reset)
1088 {
1089 union blogic_stat_reg statusreg;
1090 int timeout;
1091
1092
1093
1094
1095 if (blogic_flashpoint_type(adapter)) {
1096 struct fpoint_info *fpinfo = &adapter->fpinfo;
1097 fpinfo->softreset = !hard_reset;
1098 fpinfo->report_underrun = true;
1099 adapter->cardhandle =
1100 FlashPoint_HardwareResetHostAdapter(fpinfo);
1101 if (adapter->cardhandle == (void *)FPOINT_BADCARD_HANDLE)
1102 return false;
1103
1104
1105
1106 return true;
1107 }
1108
1109
1110
1111
1112
1113 if (hard_reset)
1114 blogic_hardreset(adapter);
1115 else
1116 blogic_softreset(adapter);
1117
1118
1119
1120 timeout = 5 * 10000;
1121 while (--timeout >= 0) {
1122 statusreg.all = blogic_rdstatus(adapter);
1123 if (statusreg.sr.diag_active)
1124 break;
1125 udelay(100);
1126 }
1127 if (blogic_global_options.trace_hw_reset)
1128 blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Active, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1129 if (timeout < 0)
1130 return false;
1131
1132
1133
1134
1135
1136 udelay(100);
1137
1138
1139
1140 timeout = 10 * 10000;
1141 while (--timeout >= 0) {
1142 statusreg.all = blogic_rdstatus(adapter);
1143 if (!statusreg.sr.diag_active)
1144 break;
1145 udelay(100);
1146 }
1147 if (blogic_global_options.trace_hw_reset)
1148 blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Completed, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1149 if (timeout < 0)
1150 return false;
1151
1152
1153
1154
1155 timeout = 10000;
1156 while (--timeout >= 0) {
1157 statusreg.all = blogic_rdstatus(adapter);
1158 if (statusreg.sr.diag_failed || statusreg.sr.adapter_ready ||
1159 statusreg.sr.datain_ready)
1160 break;
1161 udelay(100);
1162 }
1163 if (blogic_global_options.trace_hw_reset)
1164 blogic_notice("BusLogic_HardwareReset(0x%lX): Host Adapter Ready, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1165 if (timeout < 0)
1166 return false;
1167
1168
1169
1170
1171
1172
1173 if (statusreg.sr.diag_failed || !statusreg.sr.adapter_ready) {
1174 blogic_cmd_failure_reason = NULL;
1175 blogic_failure(adapter, "HARD RESET DIAGNOSTICS");
1176 blogic_err("HOST ADAPTER STATUS REGISTER = %02X\n", adapter,
1177 statusreg.all);
1178 if (statusreg.sr.datain_ready)
1179 blogic_err("HOST ADAPTER ERROR CODE = %d\n", adapter,
1180 blogic_rddatain(adapter));
1181 return false;
1182 }
1183
1184
1185
1186 return true;
1187 }
1188
1189
1190
1191
1192
1193
1194
1195 static bool __init blogic_checkadapter(struct blogic_adapter *adapter)
1196 {
1197 struct blogic_ext_setup ext_setupinfo;
1198 unsigned char req_replylen;
1199 bool result = true;
1200
1201
1202
1203 if (blogic_flashpoint_type(adapter))
1204 return true;
1205
1206
1207
1208
1209
1210
1211 req_replylen = sizeof(ext_setupinfo);
1212 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1213 sizeof(req_replylen), &ext_setupinfo,
1214 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1215 result = false;
1216
1217
1218
1219 if (blogic_global_options.trace_probe)
1220 blogic_notice("BusLogic_Check(0x%lX): MultiMaster %s\n", adapter,
1221 adapter->io_addr,
1222 (result ? "Found" : "Not Found"));
1223 return result;
1224 }
1225
1226
1227
1228
1229
1230
1231
1232 static bool __init blogic_rdconfig(struct blogic_adapter *adapter)
1233 {
1234 struct blogic_board_id id;
1235 struct blogic_config config;
1236 struct blogic_setup_info setupinfo;
1237 struct blogic_ext_setup ext_setupinfo;
1238 unsigned char model[5];
1239 unsigned char fw_ver_digit3;
1240 unsigned char fw_ver_letter;
1241 struct blogic_adapter_info adapter_info;
1242 struct blogic_fetch_localram fetch_localram;
1243 struct blogic_autoscsi autoscsi;
1244 union blogic_geo_reg georeg;
1245 unsigned char req_replylen;
1246 unsigned char *tgt, ch;
1247 int tgt_id, i;
1248
1249
1250
1251
1252
1253
1254 if (blogic_flashpoint_type(adapter)) {
1255 struct fpoint_info *fpinfo = &adapter->fpinfo;
1256 tgt = adapter->model;
1257 *tgt++ = 'B';
1258 *tgt++ = 'T';
1259 *tgt++ = '-';
1260 for (i = 0; i < sizeof(fpinfo->model); i++)
1261 *tgt++ = fpinfo->model[i];
1262 *tgt++ = '\0';
1263 strcpy(adapter->fw_ver, FLASHPOINT_FW_VER);
1264 adapter->scsi_id = fpinfo->scsi_id;
1265 adapter->ext_trans_enable = fpinfo->ext_trans_enable;
1266 adapter->parity = fpinfo->parity;
1267 adapter->reset_enabled = !fpinfo->softreset;
1268 adapter->level_int = true;
1269 adapter->wide = fpinfo->wide;
1270 adapter->differential = false;
1271 adapter->scam = true;
1272 adapter->ultra = true;
1273 adapter->ext_lun = true;
1274 adapter->terminfo_valid = true;
1275 adapter->low_term = fpinfo->low_term;
1276 adapter->high_term = fpinfo->high_term;
1277 adapter->scam_enabled = fpinfo->scam_enabled;
1278 adapter->scam_lev2 = fpinfo->scam_lev2;
1279 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1280 adapter->maxdev = (adapter->wide ? 16 : 8);
1281 adapter->maxlun = 32;
1282 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1283 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1284 adapter->drvr_qdepth = 255;
1285 adapter->adapter_qdepth = adapter->drvr_qdepth;
1286 adapter->sync_ok = fpinfo->sync_ok;
1287 adapter->fast_ok = fpinfo->fast_ok;
1288 adapter->ultra_ok = fpinfo->ultra_ok;
1289 adapter->wide_ok = fpinfo->wide_ok;
1290 adapter->discon_ok = fpinfo->discon_ok;
1291 adapter->tagq_ok = 0xFFFF;
1292 goto common;
1293 }
1294
1295
1296
1297 if (blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
1298 sizeof(id)) != sizeof(id))
1299 return blogic_failure(adapter, "INQUIRE BOARD ID");
1300
1301
1302
1303 if (blogic_cmd(adapter, BLOGIC_INQ_CONFIG, NULL, 0, &config,
1304 sizeof(config))
1305 != sizeof(config))
1306 return blogic_failure(adapter, "INQUIRE CONFIGURATION");
1307
1308
1309
1310 req_replylen = sizeof(setupinfo);
1311 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
1312 sizeof(req_replylen), &setupinfo,
1313 sizeof(setupinfo)) != sizeof(setupinfo))
1314 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
1315
1316
1317
1318 req_replylen = sizeof(ext_setupinfo);
1319 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1320 sizeof(req_replylen), &ext_setupinfo,
1321 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1322 return blogic_failure(adapter,
1323 "INQUIRE EXTENDED SETUP INFORMATION");
1324
1325
1326
1327 fw_ver_digit3 = '\0';
1328 if (id.fw_ver_digit1 > '0')
1329 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_D3, NULL, 0,
1330 &fw_ver_digit3,
1331 sizeof(fw_ver_digit3)) != sizeof(fw_ver_digit3))
1332 return blogic_failure(adapter,
1333 "INQUIRE FIRMWARE 3RD DIGIT");
1334
1335
1336
1337 if (ext_setupinfo.bus_type == 'A' && id.fw_ver_digit1 == '2')
1338
1339 strcpy(model, "542B");
1340 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '2' &&
1341 (id.fw_ver_digit2 <= '1' || (id.fw_ver_digit2 == '2' &&
1342 fw_ver_digit3 == '0')))
1343
1344 strcpy(model, "742A");
1345 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '0')
1346
1347 strcpy(model, "747A");
1348 else {
1349 req_replylen = sizeof(model);
1350 if (blogic_cmd(adapter, BLOGIC_INQ_MODELNO, &req_replylen,
1351 sizeof(req_replylen), &model,
1352 sizeof(model)) != sizeof(model))
1353 return blogic_failure(adapter,
1354 "INQUIRE HOST ADAPTER MODEL NUMBER");
1355 }
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376 tgt = adapter->model;
1377 *tgt++ = 'B';
1378 *tgt++ = 'T';
1379 *tgt++ = '-';
1380 for (i = 0; i < sizeof(model); i++) {
1381 ch = model[i];
1382 if (ch == ' ' || ch == '\0')
1383 break;
1384 *tgt++ = ch;
1385 }
1386 *tgt++ = '\0';
1387
1388
1389
1390 tgt = adapter->fw_ver;
1391 *tgt++ = id.fw_ver_digit1;
1392 *tgt++ = '.';
1393 *tgt++ = id.fw_ver_digit2;
1394 if (fw_ver_digit3 != ' ' && fw_ver_digit3 != '\0')
1395 *tgt++ = fw_ver_digit3;
1396 *tgt = '\0';
1397
1398
1399
1400 if (strcmp(adapter->fw_ver, "3.3") >= 0) {
1401 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_LETTER, NULL, 0,
1402 &fw_ver_letter,
1403 sizeof(fw_ver_letter)) != sizeof(fw_ver_letter))
1404 return blogic_failure(adapter,
1405 "INQUIRE FIRMWARE VERSION LETTER");
1406 if (fw_ver_letter != ' ' && fw_ver_letter != '\0')
1407 *tgt++ = fw_ver_letter;
1408 *tgt = '\0';
1409 }
1410
1411
1412
1413 adapter->scsi_id = config.id;
1414
1415
1416
1417
1418
1419 adapter->adapter_bus_type =
1420 blogic_adater_bus_types[adapter->model[3] - '4'];
1421 if (adapter->irq_ch == 0) {
1422 if (config.irq_ch9)
1423 adapter->irq_ch = 9;
1424 else if (config.irq_ch10)
1425 adapter->irq_ch = 10;
1426 else if (config.irq_ch11)
1427 adapter->irq_ch = 11;
1428 else if (config.irq_ch12)
1429 adapter->irq_ch = 12;
1430 else if (config.irq_ch14)
1431 adapter->irq_ch = 14;
1432 else if (config.irq_ch15)
1433 adapter->irq_ch = 15;
1434 }
1435
1436
1437
1438
1439 georeg.all = blogic_rdgeom(adapter);
1440 adapter->ext_trans_enable = georeg.gr.ext_trans_enable;
1441
1442
1443
1444
1445
1446 adapter->adapter_sglimit = ext_setupinfo.sg_limit;
1447 adapter->drvr_sglimit = adapter->adapter_sglimit;
1448 if (adapter->adapter_sglimit > BLOGIC_SG_LIMIT)
1449 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1450 if (ext_setupinfo.misc.level_int)
1451 adapter->level_int = true;
1452 adapter->wide = ext_setupinfo.wide;
1453 adapter->differential = ext_setupinfo.differential;
1454 adapter->scam = ext_setupinfo.scam;
1455 adapter->ultra = ext_setupinfo.ultra;
1456
1457
1458
1459
1460 if (adapter->fw_ver[0] == '5' || (adapter->fw_ver[0] == '4' &&
1461 adapter->wide))
1462 adapter->ext_lun = true;
1463
1464
1465
1466
1467 if (adapter->fw_ver[0] == '5') {
1468 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
1469 &adapter_info,
1470 sizeof(adapter_info)) != sizeof(adapter_info))
1471 return blogic_failure(adapter,
1472 "INQUIRE PCI HOST ADAPTER INFORMATION");
1473
1474
1475
1476
1477 if (adapter_info.genericinfo_valid) {
1478 adapter->terminfo_valid = true;
1479 adapter->low_term = adapter_info.low_term;
1480 adapter->high_term = adapter_info.high_term;
1481 }
1482 }
1483
1484
1485
1486
1487 if (adapter->fw_ver[0] >= '4') {
1488 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE;
1489 fetch_localram.count = sizeof(autoscsi);
1490 if (blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, &fetch_localram,
1491 sizeof(fetch_localram), &autoscsi,
1492 sizeof(autoscsi)) != sizeof(autoscsi))
1493 return blogic_failure(adapter,
1494 "FETCH HOST ADAPTER LOCAL RAM");
1495
1496
1497
1498
1499 adapter->parity = autoscsi.parity;
1500 adapter->reset_enabled = autoscsi.reset_enabled;
1501 if (adapter->fw_ver[0] == '4') {
1502 adapter->terminfo_valid = true;
1503 adapter->low_term = autoscsi.low_term;
1504 adapter->high_term = autoscsi.high_term;
1505 }
1506
1507
1508
1509
1510
1511 adapter->wide_ok = autoscsi.wide_ok;
1512 adapter->fast_ok = autoscsi.fast_ok;
1513 adapter->sync_ok = autoscsi.sync_ok;
1514 adapter->discon_ok = autoscsi.discon_ok;
1515 if (adapter->ultra)
1516 adapter->ultra_ok = autoscsi.ultra_ok;
1517 if (adapter->scam) {
1518 adapter->scam_enabled = autoscsi.scam_enabled;
1519 adapter->scam_lev2 = autoscsi.scam_lev2;
1520 }
1521 }
1522
1523
1524
1525
1526 if (adapter->fw_ver[0] < '4') {
1527 if (setupinfo.sync) {
1528 adapter->sync_ok = 0xFF;
1529 if (adapter->adapter_bus_type == BLOGIC_EISA_BUS) {
1530 if (ext_setupinfo.misc.fast_on_eisa)
1531 adapter->fast_ok = 0xFF;
1532 if (strcmp(adapter->model, "BT-757") == 0)
1533 adapter->wide_ok = 0xFF;
1534 }
1535 }
1536 adapter->discon_ok = 0xFF;
1537 adapter->parity = setupinfo.parity;
1538 adapter->reset_enabled = true;
1539 }
1540
1541
1542
1543
1544 adapter->maxdev = (adapter->wide ? 16 : 8);
1545 adapter->maxlun = (adapter->ext_lun ? 32 : 8);
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571 if (adapter->fw_ver[0] == '5')
1572 adapter->adapter_qdepth = 192;
1573 else if (adapter->fw_ver[0] == '4')
1574 adapter->adapter_qdepth = 100;
1575 else
1576 adapter->adapter_qdepth = 30;
1577 if (strcmp(adapter->fw_ver, "3.31") >= 0) {
1578 adapter->strict_rr = true;
1579 adapter->mbox_count = BLOGIC_MAX_MAILBOX;
1580 } else {
1581 adapter->strict_rr = false;
1582 adapter->mbox_count = 32;
1583 }
1584 adapter->drvr_qdepth = adapter->mbox_count;
1585 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1586 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1587
1588
1589
1590
1591
1592
1593
1594 adapter->tagq_ok = 0;
1595 switch (adapter->fw_ver[0]) {
1596 case '5':
1597 adapter->tagq_ok = 0xFFFF;
1598 break;
1599 case '4':
1600 if (strcmp(adapter->fw_ver, "4.22") >= 0)
1601 adapter->tagq_ok = 0xFFFF;
1602 break;
1603 case '3':
1604 if (strcmp(adapter->fw_ver, "3.35") >= 0)
1605 adapter->tagq_ok = 0xFFFF;
1606 break;
1607 }
1608
1609
1610
1611
1612
1613 adapter->bios_addr = ext_setupinfo.bios_addr << 12;
1614
1615
1616
1617
1618
1619
1620
1621 if (adapter->bios_addr > 0 &&
1622 strcmp(adapter->model, "BT-445S") == 0 &&
1623 strcmp(adapter->fw_ver, "3.37") < 0)
1624 return blogic_failure(adapter, "Too old firmware");
1625
1626
1627
1628
1629 common:
1630
1631
1632
1633 strcpy(adapter->full_model, "BusLogic ");
1634 strcat(adapter->full_model, adapter->model);
1635
1636
1637
1638
1639
1640
1641
1642 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
1643 unsigned char qdepth = 0;
1644 if (adapter->drvr_opts != NULL &&
1645 adapter->drvr_opts->qdepth[tgt_id] > 0)
1646 qdepth = adapter->drvr_opts->qdepth[tgt_id];
1647 adapter->qdepth[tgt_id] = qdepth;
1648 }
1649 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH;
1650 if (adapter->drvr_opts != NULL)
1651 adapter->common_qdepth = adapter->drvr_opts->common_qdepth;
1652 if (adapter->common_qdepth > 0 &&
1653 adapter->common_qdepth < adapter->untag_qdepth)
1654 adapter->untag_qdepth = adapter->common_qdepth;
1655
1656
1657
1658
1659
1660 adapter->tagq_ok &= adapter->discon_ok;
1661
1662
1663
1664
1665 if (adapter->drvr_opts != NULL)
1666 adapter->tagq_ok = (adapter->drvr_opts->tagq_ok &
1667 adapter->drvr_opts->tagq_ok_mask) |
1668 (adapter->tagq_ok & ~adapter->drvr_opts->tagq_ok_mask);
1669
1670
1671
1672
1673
1674
1675 if (adapter->drvr_opts != NULL &&
1676 adapter->drvr_opts->bus_settle_time > 0)
1677 adapter->bus_settle_time = adapter->drvr_opts->bus_settle_time;
1678 else
1679 adapter->bus_settle_time = BLOGIC_BUS_SETTLE_TIME;
1680
1681
1682
1683
1684 return true;
1685 }
1686
1687
1688
1689
1690
1691
1692 static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
1693 {
1694 unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
1695 unsigned short sync_ok, fast_ok;
1696 unsigned short ultra_ok, wide_ok;
1697 unsigned short discon_ok, tagq_ok;
1698 bool common_syncneg, common_tagq_depth;
1699 char syncstr[BLOGIC_MAXDEV + 1];
1700 char widestr[BLOGIC_MAXDEV + 1];
1701 char discon_str[BLOGIC_MAXDEV + 1];
1702 char tagq_str[BLOGIC_MAXDEV + 1];
1703 char *syncmsg = syncstr;
1704 char *widemsg = widestr;
1705 char *discon_msg = discon_str;
1706 char *tagq_msg = tagq_str;
1707 int tgt_id;
1708
1709 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" : ""));
1710 blogic_info(" Firmware Version: %s, I/O Address: 0x%lX, IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
1711 if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
1712 blogic_info(" DMA Channel: None, ", adapter);
1713 if (adapter->bios_addr > 0)
1714 blogic_info("BIOS Address: 0x%X, ", adapter,
1715 adapter->bios_addr);
1716 else
1717 blogic_info("BIOS Address: None, ", adapter);
1718 } else {
1719 blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
1720 adapter->bus, adapter->dev);
1721 if (adapter->pci_addr > 0)
1722 blogic_info("0x%lX, ", adapter, adapter->pci_addr);
1723 else
1724 blogic_info("Unassigned, ", adapter);
1725 }
1726 blogic_info("Host Adapter SCSI ID: %d\n", adapter, adapter->scsi_id);
1727 blogic_info(" Parity Checking: %s, Extended Translation: %s\n",
1728 adapter, (adapter->parity ? "Enabled" : "Disabled"),
1729 (adapter->ext_trans_enable ? "Enabled" : "Disabled"));
1730 alltgt_mask &= ~(1 << adapter->scsi_id);
1731 sync_ok = adapter->sync_ok & alltgt_mask;
1732 fast_ok = adapter->fast_ok & alltgt_mask;
1733 ultra_ok = adapter->ultra_ok & alltgt_mask;
1734 if ((blogic_multimaster_type(adapter) &&
1735 (adapter->fw_ver[0] >= '4' ||
1736 adapter->adapter_bus_type == BLOGIC_EISA_BUS)) ||
1737 blogic_flashpoint_type(adapter)) {
1738 common_syncneg = false;
1739 if (sync_ok == 0) {
1740 syncmsg = "Disabled";
1741 common_syncneg = true;
1742 } else if (sync_ok == alltgt_mask) {
1743 if (fast_ok == 0) {
1744 syncmsg = "Slow";
1745 common_syncneg = true;
1746 } else if (fast_ok == alltgt_mask) {
1747 if (ultra_ok == 0) {
1748 syncmsg = "Fast";
1749 common_syncneg = true;
1750 } else if (ultra_ok == alltgt_mask) {
1751 syncmsg = "Ultra";
1752 common_syncneg = true;
1753 }
1754 }
1755 }
1756 if (!common_syncneg) {
1757 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1758 syncstr[tgt_id] = ((!(sync_ok & (1 << tgt_id))) ? 'N' : (!(fast_ok & (1 << tgt_id)) ? 'S' : (!(ultra_ok & (1 << tgt_id)) ? 'F' : 'U')));
1759 syncstr[adapter->scsi_id] = '#';
1760 syncstr[adapter->maxdev] = '\0';
1761 }
1762 } else
1763 syncmsg = (sync_ok == 0 ? "Disabled" : "Enabled");
1764 wide_ok = adapter->wide_ok & alltgt_mask;
1765 if (wide_ok == 0)
1766 widemsg = "Disabled";
1767 else if (wide_ok == alltgt_mask)
1768 widemsg = "Enabled";
1769 else {
1770 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1771 widestr[tgt_id] = ((wide_ok & (1 << tgt_id)) ? 'Y' : 'N');
1772 widestr[adapter->scsi_id] = '#';
1773 widestr[adapter->maxdev] = '\0';
1774 }
1775 discon_ok = adapter->discon_ok & alltgt_mask;
1776 if (discon_ok == 0)
1777 discon_msg = "Disabled";
1778 else if (discon_ok == alltgt_mask)
1779 discon_msg = "Enabled";
1780 else {
1781 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1782 discon_str[tgt_id] = ((discon_ok & (1 << tgt_id)) ? 'Y' : 'N');
1783 discon_str[adapter->scsi_id] = '#';
1784 discon_str[adapter->maxdev] = '\0';
1785 }
1786 tagq_ok = adapter->tagq_ok & alltgt_mask;
1787 if (tagq_ok == 0)
1788 tagq_msg = "Disabled";
1789 else if (tagq_ok == alltgt_mask)
1790 tagq_msg = "Enabled";
1791 else {
1792 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1793 tagq_str[tgt_id] = ((tagq_ok & (1 << tgt_id)) ? 'Y' : 'N');
1794 tagq_str[adapter->scsi_id] = '#';
1795 tagq_str[adapter->maxdev] = '\0';
1796 }
1797 blogic_info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
1798 adapter, syncmsg, widemsg);
1799 blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
1800 discon_msg, tagq_msg);
1801 if (blogic_multimaster_type(adapter)) {
1802 blogic_info(" Scatter/Gather Limit: %d of %d segments, Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
1803 blogic_info(" Driver Queue Depth: %d, Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
1804 } else
1805 blogic_info(" Driver Queue Depth: %d, Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
1806 blogic_info(" Tagged Queue Depth: ", adapter);
1807 common_tagq_depth = true;
1808 for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
1809 if (adapter->qdepth[tgt_id] != adapter->qdepth[0]) {
1810 common_tagq_depth = false;
1811 break;
1812 }
1813 if (common_tagq_depth) {
1814 if (adapter->qdepth[0] > 0)
1815 blogic_info("%d", adapter, adapter->qdepth[0]);
1816 else
1817 blogic_info("Automatic", adapter);
1818 } else
1819 blogic_info("Individual", adapter);
1820 blogic_info(", Untagged Queue Depth: %d\n", adapter,
1821 adapter->untag_qdepth);
1822 if (adapter->terminfo_valid) {
1823 if (adapter->wide)
1824 blogic_info(" SCSI Bus Termination: %s", adapter,
1825 (adapter->low_term ? (adapter->high_term ? "Both Enabled" : "Low Enabled") : (adapter->high_term ? "High Enabled" : "Both Disabled")));
1826 else
1827 blogic_info(" SCSI Bus Termination: %s", adapter,
1828 (adapter->low_term ? "Enabled" : "Disabled"));
1829 if (adapter->scam)
1830 blogic_info(", SCAM: %s", adapter,
1831 (adapter->scam_enabled ? (adapter->scam_lev2 ? "Enabled, Level 2" : "Enabled, Level 1") : "Disabled"));
1832 blogic_info("\n", adapter);
1833 }
1834
1835
1836
1837
1838 return true;
1839 }
1840
1841
1842
1843
1844
1845
1846
1847 static bool __init blogic_getres(struct blogic_adapter *adapter)
1848 {
1849 if (adapter->irq_ch == 0) {
1850 blogic_err("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
1851 adapter);
1852 return false;
1853 }
1854
1855
1856
1857 if (request_irq(adapter->irq_ch, blogic_inthandler, IRQF_SHARED,
1858 adapter->full_model, adapter) < 0) {
1859 blogic_err("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
1860 adapter, adapter->irq_ch);
1861 return false;
1862 }
1863 adapter->irq_acquired = true;
1864
1865
1866
1867 return true;
1868 }
1869
1870
1871
1872
1873
1874
1875
1876 static void blogic_relres(struct blogic_adapter *adapter)
1877 {
1878
1879
1880
1881 if (adapter->irq_acquired)
1882 free_irq(adapter->irq_ch, adapter);
1883
1884
1885
1886 if (adapter->mbox_space)
1887 dma_free_coherent(&adapter->pci_device->dev, adapter->mbox_sz,
1888 adapter->mbox_space, adapter->mbox_space_handle);
1889 pci_dev_put(adapter->pci_device);
1890 adapter->mbox_space = NULL;
1891 adapter->mbox_space_handle = 0;
1892 adapter->mbox_sz = 0;
1893 }
1894
1895
1896
1897
1898
1899
1900
1901
1902 static bool blogic_initadapter(struct blogic_adapter *adapter)
1903 {
1904 struct blogic_extmbox_req extmbox_req;
1905 enum blogic_rr_req rr_req;
1906 enum blogic_setccb_fmt setccb_fmt;
1907 int tgt_id;
1908
1909
1910
1911
1912
1913 adapter->firstccb = NULL;
1914 adapter->lastccb = NULL;
1915
1916
1917
1918
1919
1920
1921 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
1922 adapter->bdr_pend[tgt_id] = NULL;
1923 adapter->tgt_flags[tgt_id].tagq_active = false;
1924 adapter->tgt_flags[tgt_id].cmd_good = false;
1925 adapter->active_cmds[tgt_id] = 0;
1926 adapter->cmds_since_rst[tgt_id] = 0;
1927 }
1928
1929
1930
1931
1932 if (blogic_flashpoint_type(adapter))
1933 goto done;
1934
1935
1936
1937
1938 adapter->mbox_sz = adapter->mbox_count * (sizeof(struct blogic_outbox) + sizeof(struct blogic_inbox));
1939 adapter->mbox_space = dma_alloc_coherent(&adapter->pci_device->dev,
1940 adapter->mbox_sz, &adapter->mbox_space_handle,
1941 GFP_KERNEL);
1942 if (adapter->mbox_space == NULL)
1943 return blogic_failure(adapter, "MAILBOX ALLOCATION");
1944 adapter->first_outbox = (struct blogic_outbox *) adapter->mbox_space;
1945 adapter->last_outbox = adapter->first_outbox + adapter->mbox_count - 1;
1946 adapter->next_outbox = adapter->first_outbox;
1947 adapter->first_inbox = (struct blogic_inbox *) (adapter->last_outbox + 1);
1948 adapter->last_inbox = adapter->first_inbox + adapter->mbox_count - 1;
1949 adapter->next_inbox = adapter->first_inbox;
1950
1951
1952
1953
1954 memset(adapter->first_outbox, 0,
1955 adapter->mbox_count * sizeof(struct blogic_outbox));
1956 memset(adapter->first_inbox, 0,
1957 adapter->mbox_count * sizeof(struct blogic_inbox));
1958
1959
1960
1961
1962
1963 extmbox_req.mbox_count = adapter->mbox_count;
1964 extmbox_req.base_mbox_addr = (u32) adapter->mbox_space_handle;
1965 if (blogic_cmd(adapter, BLOGIC_INIT_EXT_MBOX, &extmbox_req,
1966 sizeof(extmbox_req), NULL, 0) < 0)
1967 return blogic_failure(adapter, "MAILBOX INITIALIZATION");
1968
1969
1970
1971
1972
1973
1974
1975
1976 if (adapter->strict_rr) {
1977 rr_req = BLOGIC_STRICT_RR_MODE;
1978 if (blogic_cmd(adapter, BLOGIC_STRICT_RR, &rr_req,
1979 sizeof(rr_req), NULL, 0) < 0)
1980 return blogic_failure(adapter,
1981 "ENABLE STRICT ROUND ROBIN MODE");
1982 }
1983
1984
1985
1986
1987
1988 if (adapter->ext_lun) {
1989 setccb_fmt = BLOGIC_EXT_LUN_CCB;
1990 if (blogic_cmd(adapter, BLOGIC_SETCCB_FMT, &setccb_fmt,
1991 sizeof(setccb_fmt), NULL, 0) < 0)
1992 return blogic_failure(adapter, "SET CCB FORMAT");
1993 }
1994
1995
1996
1997
1998 done:
1999 if (!adapter->adapter_initd) {
2000 blogic_info("*** %s Initialized Successfully ***\n", adapter,
2001 adapter->full_model);
2002 blogic_info("\n", adapter);
2003 } else
2004 blogic_warn("*** %s Initialized Successfully ***\n", adapter,
2005 adapter->full_model);
2006 adapter->adapter_initd = true;
2007
2008
2009
2010
2011 return true;
2012 }
2013
2014
2015
2016
2017
2018
2019
2020 static bool __init blogic_inquiry(struct blogic_adapter *adapter)
2021 {
2022 u16 installed_devs;
2023 u8 installed_devs0to7[8];
2024 struct blogic_setup_info setupinfo;
2025 u8 sync_period[BLOGIC_MAXDEV];
2026 unsigned char req_replylen;
2027 int tgt_id;
2028
2029
2030
2031
2032
2033
2034
2035 blogic_delay(adapter->bus_settle_time);
2036
2037
2038
2039 if (blogic_flashpoint_type(adapter))
2040 return true;
2041
2042
2043
2044 if (adapter->drvr_opts != NULL && adapter->drvr_opts->stop_tgt_inquiry)
2045 return true;
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056 if (strcmp(adapter->fw_ver, "4.25") >= 0) {
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066 if (blogic_cmd(adapter, BLOGIC_INQ_DEV, NULL, 0,
2067 &installed_devs, sizeof(installed_devs))
2068 != sizeof(installed_devs))
2069 return blogic_failure(adapter, "INQUIRE TARGET DEVICES");
2070 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2071 adapter->tgt_flags[tgt_id].tgt_exists =
2072 (installed_devs & (1 << tgt_id) ? true : false);
2073 } else {
2074
2075
2076
2077
2078
2079
2080
2081
2082 if (blogic_cmd(adapter, BLOGIC_INQ_DEV0TO7, NULL, 0,
2083 &installed_devs0to7, sizeof(installed_devs0to7))
2084 != sizeof(installed_devs0to7))
2085 return blogic_failure(adapter,
2086 "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2087 for (tgt_id = 0; tgt_id < 8; tgt_id++)
2088 adapter->tgt_flags[tgt_id].tgt_exists =
2089 installed_devs0to7[tgt_id] != 0;
2090 }
2091
2092
2093
2094 req_replylen = sizeof(setupinfo);
2095 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
2096 sizeof(req_replylen), &setupinfo, sizeof(setupinfo))
2097 != sizeof(setupinfo))
2098 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
2099 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2100 adapter->sync_offset[tgt_id] = (tgt_id < 8 ? setupinfo.sync0to7[tgt_id].offset : setupinfo.sync8to15[tgt_id - 8].offset);
2101 if (strcmp(adapter->fw_ver, "5.06L") >= 0)
2102 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2103 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));
2104
2105
2106
2107 if (adapter->fw_ver[0] >= '3') {
2108
2109
2110
2111
2112
2113
2114 req_replylen = sizeof(sync_period);
2115 if (blogic_cmd(adapter, BLOGIC_INQ_SYNC_PERIOD, &req_replylen,
2116 sizeof(req_replylen), &sync_period,
2117 sizeof(sync_period)) != sizeof(sync_period))
2118 return blogic_failure(adapter,
2119 "INQUIRE SYNCHRONOUS PERIOD");
2120 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2121 adapter->sync_period[tgt_id] = sync_period[tgt_id];
2122 } else
2123 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2124 if (setupinfo.sync0to7[tgt_id].offset > 0)
2125 adapter->sync_period[tgt_id] = 20 + 5 * setupinfo.sync0to7[tgt_id].tx_period;
2126
2127
2128
2129 return true;
2130 }
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141 static void __init blogic_inithoststruct(struct blogic_adapter *adapter,
2142 struct Scsi_Host *host)
2143 {
2144 host->max_id = adapter->maxdev;
2145 host->max_lun = adapter->maxlun;
2146 host->max_channel = 0;
2147 host->unique_id = adapter->io_addr;
2148 host->this_id = adapter->scsi_id;
2149 host->can_queue = adapter->drvr_qdepth;
2150 host->sg_tablesize = adapter->drvr_sglimit;
2151 host->cmd_per_lun = adapter->untag_qdepth;
2152 }
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162 static int blogic_slaveconfig(struct scsi_device *dev)
2163 {
2164 struct blogic_adapter *adapter =
2165 (struct blogic_adapter *) dev->host->hostdata;
2166 int tgt_id = dev->id;
2167 int qdepth = adapter->qdepth[tgt_id];
2168
2169 if (adapter->tgt_flags[tgt_id].tagq_ok &&
2170 (adapter->tagq_ok & (1 << tgt_id))) {
2171 if (qdepth == 0)
2172 qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
2173 adapter->qdepth[tgt_id] = qdepth;
2174 scsi_change_queue_depth(dev, qdepth);
2175 } else {
2176 adapter->tagq_ok &= ~(1 << tgt_id);
2177 qdepth = adapter->untag_qdepth;
2178 adapter->qdepth[tgt_id] = qdepth;
2179 scsi_change_queue_depth(dev, qdepth);
2180 }
2181 qdepth = 0;
2182 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2183 if (adapter->tgt_flags[tgt_id].tgt_exists)
2184 qdepth += adapter->qdepth[tgt_id];
2185 if (qdepth > adapter->alloc_ccbs)
2186 blogic_create_addlccbs(adapter, qdepth - adapter->alloc_ccbs,
2187 false);
2188 return 0;
2189 }
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199 static int __init blogic_init(void)
2200 {
2201 int adapter_count = 0, drvr_optindex = 0, probeindex;
2202 struct blogic_adapter *adapter;
2203 int ret = 0;
2204
2205 #ifdef MODULE
2206 if (BusLogic)
2207 blogic_setup(BusLogic);
2208 #endif
2209
2210 if (blogic_probe_options.noprobe)
2211 return -ENODEV;
2212 blogic_probeinfo_list =
2213 kcalloc(BLOGIC_MAX_ADAPTERS, sizeof(struct blogic_probeinfo),
2214 GFP_KERNEL);
2215 if (blogic_probeinfo_list == NULL) {
2216 blogic_err("BusLogic: Unable to allocate Probe Info List\n",
2217 NULL);
2218 return -ENOMEM;
2219 }
2220
2221 adapter = kzalloc(sizeof(struct blogic_adapter), GFP_KERNEL);
2222 if (adapter == NULL) {
2223 kfree(blogic_probeinfo_list);
2224 blogic_err("BusLogic: Unable to allocate Prototype Host Adapter\n", NULL);
2225 return -ENOMEM;
2226 }
2227
2228 #ifdef MODULE
2229 if (BusLogic != NULL)
2230 blogic_setup(BusLogic);
2231 #endif
2232 blogic_init_probeinfo_list(adapter);
2233 for (probeindex = 0; probeindex < blogic_probeinfo_count; probeindex++) {
2234 struct blogic_probeinfo *probeinfo =
2235 &blogic_probeinfo_list[probeindex];
2236 struct blogic_adapter *myadapter = adapter;
2237 struct Scsi_Host *host;
2238
2239 if (probeinfo->io_addr == 0)
2240 continue;
2241 memset(myadapter, 0, sizeof(struct blogic_adapter));
2242 myadapter->adapter_type = probeinfo->adapter_type;
2243 myadapter->adapter_bus_type = probeinfo->adapter_bus_type;
2244 myadapter->io_addr = probeinfo->io_addr;
2245 myadapter->pci_addr = probeinfo->pci_addr;
2246 myadapter->bus = probeinfo->bus;
2247 myadapter->dev = probeinfo->dev;
2248 myadapter->pci_device = probeinfo->pci_device;
2249 myadapter->irq_ch = probeinfo->irq_ch;
2250 myadapter->addr_count =
2251 blogic_adapter_addr_count[myadapter->adapter_type];
2252
2253
2254
2255
2256 if (!request_region(myadapter->io_addr, myadapter->addr_count,
2257 "BusLogic"))
2258 continue;
2259
2260
2261
2262
2263 if (!blogic_probe(myadapter)) {
2264 release_region(myadapter->io_addr,
2265 myadapter->addr_count);
2266 continue;
2267 }
2268
2269
2270
2271
2272 if (!blogic_hwreset(myadapter, true)) {
2273 release_region(myadapter->io_addr,
2274 myadapter->addr_count);
2275 continue;
2276 }
2277
2278
2279
2280
2281 if (!blogic_checkadapter(myadapter)) {
2282 release_region(myadapter->io_addr,
2283 myadapter->addr_count);
2284 continue;
2285 }
2286
2287
2288
2289 if (drvr_optindex < blogic_drvr_options_count)
2290 myadapter->drvr_opts =
2291 &blogic_drvr_options[drvr_optindex++];
2292
2293
2294
2295
2296 blogic_announce_drvr(myadapter);
2297
2298
2299
2300
2301 host = scsi_host_alloc(&blogic_template,
2302 sizeof(struct blogic_adapter));
2303 if (host == NULL) {
2304 release_region(myadapter->io_addr,
2305 myadapter->addr_count);
2306 continue;
2307 }
2308 myadapter = (struct blogic_adapter *) host->hostdata;
2309 memcpy(myadapter, adapter, sizeof(struct blogic_adapter));
2310 myadapter->scsi_host = host;
2311 myadapter->host_no = host->host_no;
2312
2313
2314
2315
2316 list_add_tail(&myadapter->host_list, &blogic_host_list);
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331 if (blogic_rdconfig(myadapter) &&
2332 blogic_reportconfig(myadapter) &&
2333 blogic_getres(myadapter) &&
2334 blogic_create_initccbs(myadapter) &&
2335 blogic_initadapter(myadapter) &&
2336 blogic_inquiry(myadapter)) {
2337
2338
2339
2340
2341
2342
2343 release_region(myadapter->io_addr,
2344 myadapter->addr_count);
2345 if (!request_region(myadapter->io_addr,
2346 myadapter->addr_count,
2347 myadapter->full_model)) {
2348 printk(KERN_WARNING
2349 "BusLogic: Release and re-register of "
2350 "port 0x%04lx failed \n",
2351 (unsigned long)myadapter->io_addr);
2352 blogic_destroy_ccbs(myadapter);
2353 blogic_relres(myadapter);
2354 list_del(&myadapter->host_list);
2355 scsi_host_put(host);
2356 ret = -ENOMEM;
2357 } else {
2358 blogic_inithoststruct(myadapter,
2359 host);
2360 if (scsi_add_host(host, myadapter->pci_device
2361 ? &myadapter->pci_device->dev
2362 : NULL)) {
2363 printk(KERN_WARNING
2364 "BusLogic: scsi_add_host()"
2365 "failed!\n");
2366 blogic_destroy_ccbs(myadapter);
2367 blogic_relres(myadapter);
2368 list_del(&myadapter->host_list);
2369 scsi_host_put(host);
2370 ret = -ENODEV;
2371 } else {
2372 scsi_scan_host(host);
2373 adapter_count++;
2374 }
2375 }
2376 } else {
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387 blogic_destroy_ccbs(myadapter);
2388 blogic_relres(myadapter);
2389 list_del(&myadapter->host_list);
2390 scsi_host_put(host);
2391 ret = -ENODEV;
2392 }
2393 }
2394 kfree(adapter);
2395 kfree(blogic_probeinfo_list);
2396 blogic_probeinfo_list = NULL;
2397 return ret;
2398 }
2399
2400
2401
2402
2403
2404
2405
2406
2407 static int __exit blogic_deladapter(struct blogic_adapter *adapter)
2408 {
2409 struct Scsi_Host *host = adapter->scsi_host;
2410
2411 scsi_remove_host(host);
2412
2413
2414
2415
2416
2417 if (blogic_flashpoint_type(adapter))
2418 FlashPoint_ReleaseHostAdapter(adapter->cardhandle);
2419
2420
2421
2422
2423 blogic_destroy_ccbs(adapter);
2424 blogic_relres(adapter);
2425
2426
2427
2428 release_region(adapter->io_addr, adapter->addr_count);
2429
2430
2431
2432
2433 list_del(&adapter->host_list);
2434
2435 scsi_host_put(host);
2436 return 0;
2437 }
2438
2439
2440
2441
2442
2443
2444 static void blogic_qcompleted_ccb(struct blogic_ccb *ccb)
2445 {
2446 struct blogic_adapter *adapter = ccb->adapter;
2447
2448 ccb->status = BLOGIC_CCB_COMPLETE;
2449 ccb->next = NULL;
2450 if (adapter->firstccb == NULL) {
2451 adapter->firstccb = ccb;
2452 adapter->lastccb = ccb;
2453 } else {
2454 adapter->lastccb->next = ccb;
2455 adapter->lastccb = ccb;
2456 }
2457 adapter->active_cmds[ccb->tgt_id]--;
2458 }
2459
2460
2461
2462
2463
2464
2465
2466 static int blogic_resultcode(struct blogic_adapter *adapter,
2467 enum blogic_adapter_status adapter_status,
2468 enum blogic_tgt_status tgt_status)
2469 {
2470 int hoststatus;
2471
2472 switch (adapter_status) {
2473 case BLOGIC_CMD_CMPLT_NORMAL:
2474 case BLOGIC_LINK_CMD_CMPLT:
2475 case BLOGIC_LINK_CMD_CMPLT_FLAG:
2476 hoststatus = DID_OK;
2477 break;
2478 case BLOGIC_SELECT_TIMEOUT:
2479 hoststatus = DID_TIME_OUT;
2480 break;
2481 case BLOGIC_INVALID_OUTBOX_CODE:
2482 case BLOGIC_INVALID_CMD_CODE:
2483 case BLOGIC_BAD_CMD_PARAM:
2484 blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
2485 adapter, adapter_status);
2486 fallthrough;
2487 case BLOGIC_DATA_UNDERRUN:
2488 case BLOGIC_DATA_OVERRUN:
2489 case BLOGIC_NOEXPECT_BUSFREE:
2490 case BLOGIC_LINKCCB_BADLUN:
2491 case BLOGIC_AUTOREQSENSE_FAIL:
2492 case BLOGIC_TAGQUEUE_REJECT:
2493 case BLOGIC_BAD_MSG_RCVD:
2494 case BLOGIC_HW_FAIL:
2495 case BLOGIC_BAD_RECONNECT:
2496 case BLOGIC_ABRT_QUEUE:
2497 case BLOGIC_ADAPTER_SW_ERROR:
2498 case BLOGIC_HW_TIMEOUT:
2499 case BLOGIC_PARITY_ERR:
2500 hoststatus = DID_ERROR;
2501 break;
2502 case BLOGIC_INVALID_BUSPHASE:
2503 case BLOGIC_NORESPONSE_TO_ATN:
2504 case BLOGIC_HW_RESET:
2505 case BLOGIC_RST_FROM_OTHERDEV:
2506 case BLOGIC_HW_BDR:
2507 hoststatus = DID_RESET;
2508 break;
2509 default:
2510 blogic_warn("Unknown Host Adapter Status 0x%02X\n", adapter,
2511 adapter_status);
2512 hoststatus = DID_ERROR;
2513 break;
2514 }
2515 return (hoststatus << 16) | tgt_status;
2516 }
2517
2518
2519
2520
2521
2522 static struct blogic_ccb *
2523 blogic_inbox_to_ccb(struct blogic_adapter *adapter, struct blogic_inbox *inbox)
2524 {
2525 struct blogic_ccb *ccb;
2526
2527 for (ccb = adapter->all_ccbs; ccb; ccb = ccb->next_all)
2528 if (inbox->ccb == ccb->dma_handle)
2529 break;
2530
2531 return ccb;
2532 }
2533
2534
2535
2536
2537
2538 static void blogic_scan_inbox(struct blogic_adapter *adapter)
2539 {
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553 struct blogic_inbox *next_inbox = adapter->next_inbox;
2554 enum blogic_cmplt_code comp_code;
2555
2556 while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
2557 struct blogic_ccb *ccb = blogic_inbox_to_ccb(adapter, next_inbox);
2558 if (!ccb) {
2559
2560
2561
2562
2563 blogic_warn("Could not find CCB for dma address %x\n", adapter, next_inbox->ccb);
2564 } else if (comp_code != BLOGIC_CMD_NOTFOUND) {
2565 if (ccb->status == BLOGIC_CCB_ACTIVE ||
2566 ccb->status == BLOGIC_CCB_RESET) {
2567
2568
2569
2570
2571 ccb->comp_code = comp_code;
2572 blogic_qcompleted_ccb(ccb);
2573 } else {
2574
2575
2576
2577
2578
2579
2580 blogic_warn("Illegal CCB #%ld status %d in Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
2581 }
2582 }
2583 next_inbox->comp_code = BLOGIC_INBOX_FREE;
2584 if (++next_inbox > adapter->last_inbox)
2585 next_inbox = adapter->first_inbox;
2586 }
2587 adapter->next_inbox = next_inbox;
2588 }
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598 static void blogic_process_ccbs(struct blogic_adapter *adapter)
2599 {
2600 if (adapter->processing_ccbs)
2601 return;
2602 adapter->processing_ccbs = true;
2603 while (adapter->firstccb != NULL) {
2604 struct blogic_ccb *ccb = adapter->firstccb;
2605 struct scsi_cmnd *command = ccb->command;
2606 adapter->firstccb = ccb->next;
2607 if (adapter->firstccb == NULL)
2608 adapter->lastccb = NULL;
2609
2610
2611
2612 if (ccb->opcode == BLOGIC_BDR) {
2613 int tgt_id = ccb->tgt_id;
2614
2615 blogic_warn("Bus Device Reset CCB #%ld to Target %d Completed\n", adapter, ccb->serial, tgt_id);
2616 blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
2617 adapter->tgt_flags[tgt_id].tagq_active = false;
2618 adapter->cmds_since_rst[tgt_id] = 0;
2619 adapter->last_resetdone[tgt_id] = jiffies;
2620
2621
2622
2623 blogic_dealloc_ccb(ccb, 1);
2624 #if 0
2625
2626
2627
2628
2629
2630
2631
2632
2633 while (command != NULL) {
2634 struct scsi_cmnd *nxt_cmd =
2635 command->reset_chain;
2636 command->reset_chain = NULL;
2637 command->result = DID_RESET << 16;
2638 scsi_done(command);
2639 command = nxt_cmd;
2640 }
2641 #endif
2642
2643
2644
2645
2646
2647 for (ccb = adapter->all_ccbs; ccb != NULL;
2648 ccb = ccb->next_all)
2649 if (ccb->status == BLOGIC_CCB_RESET &&
2650 ccb->tgt_id == tgt_id) {
2651 command = ccb->command;
2652 blogic_dealloc_ccb(ccb, 1);
2653 adapter->active_cmds[tgt_id]--;
2654 command->result = DID_RESET << 16;
2655 scsi_done(command);
2656 }
2657 adapter->bdr_pend[tgt_id] = NULL;
2658 } else {
2659
2660
2661
2662
2663
2664 switch (ccb->comp_code) {
2665 case BLOGIC_INBOX_FREE:
2666 case BLOGIC_CMD_NOTFOUND:
2667 case BLOGIC_INVALID_CCB:
2668 blogic_warn("CCB #%ld to Target %d Impossible State\n", adapter, ccb->serial, ccb->tgt_id);
2669 break;
2670 case BLOGIC_CMD_COMPLETE_GOOD:
2671 adapter->tgt_stats[ccb->tgt_id]
2672 .cmds_complete++;
2673 adapter->tgt_flags[ccb->tgt_id]
2674 .cmd_good = true;
2675 command->result = DID_OK << 16;
2676 break;
2677 case BLOGIC_CMD_ABORT_BY_HOST:
2678 blogic_warn("CCB #%ld to Target %d Aborted\n",
2679 adapter, ccb->serial, ccb->tgt_id);
2680 blogic_inc_count(&adapter->tgt_stats[ccb->tgt_id].aborts_done);
2681 command->result = DID_ABORT << 16;
2682 break;
2683 case BLOGIC_CMD_COMPLETE_ERROR:
2684 command->result = blogic_resultcode(adapter,
2685 ccb->adapter_status, ccb->tgt_status);
2686 if (ccb->adapter_status != BLOGIC_SELECT_TIMEOUT) {
2687 adapter->tgt_stats[ccb->tgt_id]
2688 .cmds_complete++;
2689 if (blogic_global_options.trace_err) {
2690 int i;
2691 blogic_notice("CCB #%ld Target %d: Result %X Host "
2692 "Adapter Status %02X Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
2693 blogic_notice("CDB ", adapter);
2694 for (i = 0; i < ccb->cdblen; i++)
2695 blogic_notice(" %02X", adapter, ccb->cdb[i]);
2696 blogic_notice("\n", adapter);
2697 blogic_notice("Sense ", adapter);
2698 for (i = 0; i < ccb->sense_datalen; i++)
2699 blogic_notice(" %02X", adapter, command->sense_buffer[i]);
2700 blogic_notice("\n", adapter);
2701 }
2702 }
2703 break;
2704 }
2705
2706
2707
2708
2709
2710 if (ccb->cdb[0] == INQUIRY && ccb->cdb[1] == 0 &&
2711 ccb->adapter_status == BLOGIC_CMD_CMPLT_NORMAL) {
2712 struct blogic_tgt_flags *tgt_flags =
2713 &adapter->tgt_flags[ccb->tgt_id];
2714 struct scsi_inquiry *inquiry =
2715 (struct scsi_inquiry *) scsi_sglist(command);
2716 tgt_flags->tgt_exists = true;
2717 tgt_flags->tagq_ok = inquiry->CmdQue;
2718 tgt_flags->wide_ok = inquiry->WBus16;
2719 }
2720
2721
2722
2723 blogic_dealloc_ccb(ccb, 1);
2724
2725
2726
2727 scsi_done(command);
2728 }
2729 }
2730 adapter->processing_ccbs = false;
2731 }
2732
2733
2734
2735
2736
2737
2738
2739 static irqreturn_t blogic_inthandler(int irq_ch, void *devid)
2740 {
2741 struct blogic_adapter *adapter = (struct blogic_adapter *) devid;
2742 unsigned long processor_flag;
2743
2744
2745
2746 spin_lock_irqsave(adapter->scsi_host->host_lock, processor_flag);
2747
2748
2749
2750 if (blogic_multimaster_type(adapter)) {
2751 union blogic_int_reg intreg;
2752
2753
2754
2755 intreg.all = blogic_rdint(adapter);
2756 if (intreg.ir.int_valid) {
2757
2758
2759
2760
2761 blogic_intreset(adapter);
2762
2763
2764
2765
2766
2767
2768 if (intreg.ir.ext_busreset)
2769 adapter->adapter_extreset = true;
2770 else if (intreg.ir.mailin_loaded)
2771 blogic_scan_inbox(adapter);
2772 else if (intreg.ir.cmd_complete)
2773 adapter->adapter_cmd_complete = true;
2774 }
2775 } else {
2776
2777
2778
2779 if (FlashPoint_InterruptPending(adapter->cardhandle))
2780 switch (FlashPoint_HandleInterrupt(adapter->cardhandle)) {
2781 case FPOINT_NORMAL_INT:
2782 break;
2783 case FPOINT_EXT_RESET:
2784 adapter->adapter_extreset = true;
2785 break;
2786 case FPOINT_INTERN_ERR:
2787 blogic_warn("Internal FlashPoint Error detected - Resetting Host Adapter\n", adapter);
2788 adapter->adapter_intern_err = true;
2789 break;
2790 }
2791 }
2792
2793
2794
2795 if (adapter->firstccb != NULL)
2796 blogic_process_ccbs(adapter);
2797
2798
2799
2800 if (adapter->adapter_extreset) {
2801 blogic_warn("Resetting %s due to External SCSI Bus Reset\n", adapter, adapter->full_model);
2802 blogic_inc_count(&adapter->ext_resets);
2803 blogic_resetadapter(adapter, false);
2804 adapter->adapter_extreset = false;
2805 } else if (adapter->adapter_intern_err) {
2806 blogic_warn("Resetting %s due to Host Adapter Internal Error\n", adapter, adapter->full_model);
2807 blogic_inc_count(&adapter->adapter_intern_errors);
2808 blogic_resetadapter(adapter, true);
2809 adapter->adapter_intern_err = false;
2810 }
2811
2812
2813
2814 spin_unlock_irqrestore(adapter->scsi_host->host_lock, processor_flag);
2815 return IRQ_HANDLED;
2816 }
2817
2818
2819
2820
2821
2822
2823
2824
2825 static bool blogic_write_outbox(struct blogic_adapter *adapter,
2826 enum blogic_action action, struct blogic_ccb *ccb)
2827 {
2828 struct blogic_outbox *next_outbox;
2829
2830 next_outbox = adapter->next_outbox;
2831 if (next_outbox->action == BLOGIC_OUTBOX_FREE) {
2832 ccb->status = BLOGIC_CCB_ACTIVE;
2833
2834
2835
2836
2837
2838
2839 next_outbox->ccb = ccb->dma_handle;
2840 next_outbox->action = action;
2841 blogic_execmbox(adapter);
2842 if (++next_outbox > adapter->last_outbox)
2843 next_outbox = adapter->first_outbox;
2844 adapter->next_outbox = next_outbox;
2845 if (action == BLOGIC_MBOX_START) {
2846 adapter->active_cmds[ccb->tgt_id]++;
2847 if (ccb->opcode != BLOGIC_BDR)
2848 adapter->tgt_stats[ccb->tgt_id].cmds_tried++;
2849 }
2850 return true;
2851 }
2852 return false;
2853 }
2854
2855
2856
2857 static int blogic_hostreset(struct scsi_cmnd *SCpnt)
2858 {
2859 struct blogic_adapter *adapter =
2860 (struct blogic_adapter *) SCpnt->device->host->hostdata;
2861
2862 unsigned int id = SCpnt->device->id;
2863 struct blogic_tgt_stats *stats = &adapter->tgt_stats[id];
2864 int rc;
2865
2866 spin_lock_irq(SCpnt->device->host->host_lock);
2867
2868 blogic_inc_count(&stats->adapter_reset_req);
2869
2870 rc = blogic_resetadapter(adapter, false);
2871 spin_unlock_irq(SCpnt->device->host->host_lock);
2872 return rc;
2873 }
2874
2875
2876
2877
2878
2879
2880 static int blogic_qcmd_lck(struct scsi_cmnd *command)
2881 {
2882 void (*comp_cb)(struct scsi_cmnd *) = scsi_done;
2883 struct blogic_adapter *adapter =
2884 (struct blogic_adapter *) command->device->host->hostdata;
2885 struct blogic_tgt_flags *tgt_flags =
2886 &adapter->tgt_flags[command->device->id];
2887 struct blogic_tgt_stats *tgt_stats = adapter->tgt_stats;
2888 unsigned char *cdb = command->cmnd;
2889 int cdblen = command->cmd_len;
2890 int tgt_id = command->device->id;
2891 int lun = command->device->lun;
2892 int buflen = scsi_bufflen(command);
2893 int count;
2894 struct blogic_ccb *ccb;
2895 dma_addr_t sense_buf;
2896
2897
2898
2899
2900
2901
2902
2903 if (cdb[0] == REQUEST_SENSE && command->sense_buffer[0] != 0) {
2904 command->result = DID_OK << 16;
2905 comp_cb(command);
2906 return 0;
2907 }
2908
2909
2910
2911
2912
2913
2914
2915 ccb = blogic_alloc_ccb(adapter);
2916 if (ccb == NULL) {
2917 spin_unlock_irq(adapter->scsi_host->host_lock);
2918 blogic_delay(1);
2919 spin_lock_irq(adapter->scsi_host->host_lock);
2920 ccb = blogic_alloc_ccb(adapter);
2921 if (ccb == NULL) {
2922 command->result = DID_ERROR << 16;
2923 comp_cb(command);
2924 return 0;
2925 }
2926 }
2927
2928
2929
2930
2931 count = scsi_dma_map(command);
2932 BUG_ON(count < 0);
2933 if (count) {
2934 struct scatterlist *sg;
2935 int i;
2936
2937 ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
2938 ccb->datalen = count * sizeof(struct blogic_sg_seg);
2939 if (blogic_multimaster_type(adapter))
2940 ccb->data = (unsigned int) ccb->dma_handle +
2941 ((unsigned long) &ccb->sglist -
2942 (unsigned long) ccb);
2943 else
2944 ccb->data = virt_to_32bit_virt(ccb->sglist);
2945
2946 scsi_for_each_sg(command, sg, count, i) {
2947 ccb->sglist[i].segbytes = sg_dma_len(sg);
2948 ccb->sglist[i].segdata = sg_dma_address(sg);
2949 }
2950 } else if (!count) {
2951 ccb->opcode = BLOGIC_INITIATOR_CCB;
2952 ccb->datalen = buflen;
2953 ccb->data = 0;
2954 }
2955
2956 switch (cdb[0]) {
2957 case READ_6:
2958 case READ_10:
2959 ccb->datadir = BLOGIC_DATAIN_CHECKED;
2960 tgt_stats[tgt_id].read_cmds++;
2961 blogic_addcount(&tgt_stats[tgt_id].bytesread, buflen);
2962 blogic_incszbucket(tgt_stats[tgt_id].read_sz_buckets, buflen);
2963 break;
2964 case WRITE_6:
2965 case WRITE_10:
2966 ccb->datadir = BLOGIC_DATAOUT_CHECKED;
2967 tgt_stats[tgt_id].write_cmds++;
2968 blogic_addcount(&tgt_stats[tgt_id].byteswritten, buflen);
2969 blogic_incszbucket(tgt_stats[tgt_id].write_sz_buckets, buflen);
2970 break;
2971 default:
2972 ccb->datadir = BLOGIC_UNCHECKED_TX;
2973 break;
2974 }
2975 ccb->cdblen = cdblen;
2976 ccb->adapter_status = 0;
2977 ccb->tgt_status = 0;
2978 ccb->tgt_id = tgt_id;
2979 ccb->lun = lun;
2980 ccb->tag_enable = false;
2981 ccb->legacytag_enable = false;
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998 if (adapter->cmds_since_rst[tgt_id]++ >= BLOGIC_MAX_TAG_DEPTH &&
2999 !tgt_flags->tagq_active &&
3000 adapter->active_cmds[tgt_id] == 0
3001 && tgt_flags->tagq_ok &&
3002 (adapter->tagq_ok & (1 << tgt_id))) {
3003 tgt_flags->tagq_active = true;
3004 blogic_notice("Tagged Queuing now active for Target %d\n",
3005 adapter, tgt_id);
3006 }
3007 if (tgt_flags->tagq_active) {
3008 enum blogic_queuetag queuetag = BLOGIC_SIMPLETAG;
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024 if (adapter->active_cmds[tgt_id] == 0)
3025 adapter->last_seqpoint[tgt_id] = jiffies;
3026 else if (time_after(jiffies,
3027 adapter->last_seqpoint[tgt_id] + 4 * HZ)) {
3028 adapter->last_seqpoint[tgt_id] = jiffies;
3029 queuetag = BLOGIC_ORDEREDTAG;
3030 }
3031 if (adapter->ext_lun) {
3032 ccb->tag_enable = true;
3033 ccb->queuetag = queuetag;
3034 } else {
3035 ccb->legacytag_enable = true;
3036 ccb->legacy_tag = queuetag;
3037 }
3038 }
3039 memcpy(ccb->cdb, cdb, cdblen);
3040 ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
3041 ccb->command = command;
3042 sense_buf = dma_map_single(&adapter->pci_device->dev,
3043 command->sense_buffer, ccb->sense_datalen,
3044 DMA_FROM_DEVICE);
3045 if (dma_mapping_error(&adapter->pci_device->dev, sense_buf)) {
3046 blogic_err("DMA mapping for sense data buffer failed\n",
3047 adapter);
3048 blogic_dealloc_ccb(ccb, 0);
3049 return SCSI_MLQUEUE_HOST_BUSY;
3050 }
3051 ccb->sensedata = sense_buf;
3052 if (blogic_multimaster_type(adapter)) {
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
3064 spin_unlock_irq(adapter->scsi_host->host_lock);
3065 blogic_warn("Unable to write Outgoing Mailbox - Pausing for 1 second\n", adapter);
3066 blogic_delay(1);
3067 spin_lock_irq(adapter->scsi_host->host_lock);
3068 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
3069 ccb)) {
3070 blogic_warn("Still unable to write Outgoing Mailbox - Host Adapter Dead?\n", adapter);
3071 blogic_dealloc_ccb(ccb, 1);
3072 command->result = DID_ERROR << 16;
3073 scsi_done(command);
3074 }
3075 }
3076 } else {
3077
3078
3079
3080
3081 ccb->status = BLOGIC_CCB_ACTIVE;
3082 adapter->active_cmds[tgt_id]++;
3083 tgt_stats[tgt_id].cmds_tried++;
3084 FlashPoint_StartCCB(adapter->cardhandle, ccb);
3085
3086
3087
3088
3089
3090 if (ccb->status == BLOGIC_CCB_COMPLETE)
3091 blogic_process_ccbs(adapter);
3092 }
3093 return 0;
3094 }
3095
3096 static DEF_SCSI_QCMD(blogic_qcmd)
3097
3098 #if 0
3099
3100
3101
3102
3103 static int blogic_abort(struct scsi_cmnd *command)
3104 {
3105 struct blogic_adapter *adapter =
3106 (struct blogic_adapter *) command->device->host->hostdata;
3107
3108 int tgt_id = command->device->id;
3109 struct blogic_ccb *ccb;
3110 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_request);
3111
3112
3113
3114
3115
3116 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3117 if (ccb->command == command)
3118 break;
3119 if (ccb == NULL) {
3120 blogic_warn("Unable to Abort Command to Target %d - No CCB Found\n", adapter, tgt_id);
3121 return SUCCESS;
3122 } else if (ccb->status == BLOGIC_CCB_COMPLETE) {
3123 blogic_warn("Unable to Abort Command to Target %d - CCB Completed\n", adapter, tgt_id);
3124 return SUCCESS;
3125 } else if (ccb->status == BLOGIC_CCB_RESET) {
3126 blogic_warn("Unable to Abort Command to Target %d - CCB Reset\n", adapter, tgt_id);
3127 return SUCCESS;
3128 }
3129 if (blogic_multimaster_type(adapter)) {
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142 if (adapter->tgt_flags[tgt_id].tagq_active &&
3143 adapter->fw_ver[0] < '5') {
3144 blogic_warn("Unable to Abort CCB #%ld to Target %d - Abort Tag Not Supported\n", adapter, ccb->serial, tgt_id);
3145 return FAILURE;
3146 } else if (blogic_write_outbox(adapter, BLOGIC_MBOX_ABORT,
3147 ccb)) {
3148 blogic_warn("Aborting CCB #%ld to Target %d\n",
3149 adapter, ccb->serial, tgt_id);
3150 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3151 return SUCCESS;
3152 } else {
3153 blogic_warn("Unable to Abort CCB #%ld to Target %d - No Outgoing Mailboxes\n", adapter, ccb->serial, tgt_id);
3154 return FAILURE;
3155 }
3156 } else {
3157
3158
3159
3160
3161 blogic_warn("Aborting CCB #%ld to Target %d\n", adapter,
3162 ccb->serial, tgt_id);
3163 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3164 FlashPoint_AbortCCB(adapter->cardhandle, ccb);
3165
3166
3167
3168
3169
3170 if (ccb->status == BLOGIC_CCB_COMPLETE)
3171 blogic_process_ccbs(adapter);
3172 return SUCCESS;
3173 }
3174 return SUCCESS;
3175 }
3176
3177 #endif
3178
3179
3180
3181
3182
3183 static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
3184 {
3185 struct blogic_ccb *ccb;
3186 int tgt_id;
3187
3188
3189
3190
3191
3192 if (!(blogic_hwreset(adapter, hard_reset) &&
3193 blogic_initadapter(adapter))) {
3194 blogic_err("Resetting %s Failed\n", adapter,
3195 adapter->full_model);
3196 return FAILURE;
3197 }
3198
3199
3200
3201
3202
3203 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3204 if (ccb->status == BLOGIC_CCB_ACTIVE)
3205 blogic_dealloc_ccb(ccb, 1);
3206
3207
3208
3209
3210
3211
3212
3213 if (hard_reset) {
3214 spin_unlock_irq(adapter->scsi_host->host_lock);
3215 blogic_delay(adapter->bus_settle_time);
3216 spin_lock_irq(adapter->scsi_host->host_lock);
3217 }
3218
3219 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
3220 adapter->last_resettried[tgt_id] = jiffies;
3221 adapter->last_resetdone[tgt_id] = jiffies;
3222 }
3223 return SUCCESS;
3224 }
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243 static int blogic_diskparam(struct scsi_device *sdev, struct block_device *dev,
3244 sector_t capacity, int *params)
3245 {
3246 struct blogic_adapter *adapter =
3247 (struct blogic_adapter *) sdev->host->hostdata;
3248 struct bios_diskparam *diskparam = (struct bios_diskparam *) params;
3249 unsigned char *buf;
3250
3251 if (adapter->ext_trans_enable && capacity >= 2 * 1024 * 1024 ) {
3252 if (capacity >= 4 * 1024 * 1024 ) {
3253 diskparam->heads = 255;
3254 diskparam->sectors = 63;
3255 } else {
3256 diskparam->heads = 128;
3257 diskparam->sectors = 32;
3258 }
3259 } else {
3260 diskparam->heads = 64;
3261 diskparam->sectors = 32;
3262 }
3263 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3264 buf = scsi_bios_ptable(dev);
3265 if (buf == NULL)
3266 return 0;
3267
3268
3269
3270
3271
3272 if (*(unsigned short *) (buf + 64) == MSDOS_LABEL_MAGIC) {
3273 struct msdos_partition *part1_entry =
3274 (struct msdos_partition *)buf;
3275 struct msdos_partition *part_entry = part1_entry;
3276 int saved_cyl = diskparam->cylinders, part_no;
3277 unsigned char part_end_head = 0, part_end_sector = 0;
3278
3279 for (part_no = 0; part_no < 4; part_no++) {
3280 part_end_head = part_entry->end_head;
3281 part_end_sector = part_entry->end_sector & 0x3F;
3282 if (part_end_head == 64 - 1) {
3283 diskparam->heads = 64;
3284 diskparam->sectors = 32;
3285 break;
3286 } else if (part_end_head == 128 - 1) {
3287 diskparam->heads = 128;
3288 diskparam->sectors = 32;
3289 break;
3290 } else if (part_end_head == 255 - 1) {
3291 diskparam->heads = 255;
3292 diskparam->sectors = 63;
3293 break;
3294 }
3295 part_entry++;
3296 }
3297 if (part_no == 4) {
3298 part_end_head = part1_entry->end_head;
3299 part_end_sector = part1_entry->end_sector & 0x3F;
3300 }
3301 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3302 if (part_no < 4 && part_end_sector == diskparam->sectors) {
3303 if (diskparam->cylinders != saved_cyl)
3304 blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
3305 } else if (part_end_head > 0 || part_end_sector > 0) {
3306 blogic_warn("Warning: Partition Table appears to have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
3307 blogic_warn("not compatible with current BusLogic Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
3308 }
3309 }
3310 kfree(buf);
3311 return 0;
3312 }
3313
3314
3315
3316
3317
3318
3319 static int blogic_write_info(struct Scsi_Host *shost, char *procbuf,
3320 int bytes_avail)
3321 {
3322 struct blogic_adapter *adapter =
3323 (struct blogic_adapter *) shost->hostdata;
3324 struct blogic_tgt_stats *tgt_stats;
3325
3326 tgt_stats = adapter->tgt_stats;
3327 adapter->ext_resets = 0;
3328 adapter->adapter_intern_errors = 0;
3329 memset(tgt_stats, 0, BLOGIC_MAXDEV * sizeof(struct blogic_tgt_stats));
3330 return 0;
3331 }
3332
3333 static int blogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
3334 {
3335 struct blogic_adapter *adapter = (struct blogic_adapter *) shost->hostdata;
3336 struct blogic_tgt_stats *tgt_stats;
3337 int tgt;
3338
3339 tgt_stats = adapter->tgt_stats;
3340 seq_write(m, adapter->msgbuf, adapter->msgbuflen);
3341 seq_printf(m, "\n\
3342 Current Driver Queue Depth: %d\n\
3343 Currently Allocated CCBs: %d\n", adapter->drvr_qdepth, adapter->alloc_ccbs);
3344 seq_puts(m, "\n\n\
3345 DATA TRANSFER STATISTICS\n\
3346 \n\
3347 Target Tagged Queuing Queue Depth Active Attempted Completed\n\
3348 ====== ============== =========== ====== ========= =========\n");
3349 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3350 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3351 if (!tgt_flags->tgt_exists)
3352 continue;
3353 seq_printf(m, " %2d %s", tgt, (tgt_flags->tagq_ok ? (tgt_flags->tagq_active ? " Active" : (adapter->tagq_ok & (1 << tgt)
3354 ? " Permitted" : " Disabled"))
3355 : "Not Supported"));
3356 seq_printf(m,
3357 " %3d %3u %9u %9u\n", adapter->qdepth[tgt], adapter->active_cmds[tgt], tgt_stats[tgt].cmds_tried, tgt_stats[tgt].cmds_complete);
3358 }
3359 seq_puts(m, "\n\
3360 Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
3361 ====== ============= ============== =================== ===================\n");
3362 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3363 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3364 if (!tgt_flags->tgt_exists)
3365 continue;
3366 seq_printf(m, " %2d %9u %9u", tgt, tgt_stats[tgt].read_cmds, tgt_stats[tgt].write_cmds);
3367 if (tgt_stats[tgt].bytesread.billions > 0)
3368 seq_printf(m, " %9u%09u", tgt_stats[tgt].bytesread.billions, tgt_stats[tgt].bytesread.units);
3369 else
3370 seq_printf(m, " %9u", tgt_stats[tgt].bytesread.units);
3371 if (tgt_stats[tgt].byteswritten.billions > 0)
3372 seq_printf(m, " %9u%09u\n", tgt_stats[tgt].byteswritten.billions, tgt_stats[tgt].byteswritten.units);
3373 else
3374 seq_printf(m, " %9u\n", tgt_stats[tgt].byteswritten.units);
3375 }
3376 seq_puts(m, "\n\
3377 Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
3378 ====== ======= ========= ========= ========= ========= =========\n");
3379 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3380 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3381 if (!tgt_flags->tgt_exists)
3382 continue;
3383 seq_printf(m,
3384 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3385 tgt_stats[tgt].read_sz_buckets[0],
3386 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]);
3387 seq_printf(m,
3388 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3389 tgt_stats[tgt].write_sz_buckets[0],
3390 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]);
3391 }
3392 seq_puts(m, "\n\
3393 Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
3394 ====== ======= ========= ========= ========= ========= =========\n");
3395 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3396 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3397 if (!tgt_flags->tgt_exists)
3398 continue;
3399 seq_printf(m,
3400 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3401 tgt_stats[tgt].read_sz_buckets[5],
3402 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]);
3403 seq_printf(m,
3404 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3405 tgt_stats[tgt].write_sz_buckets[5],
3406 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]);
3407 }
3408 seq_puts(m, "\n\n\
3409 ERROR RECOVERY STATISTICS\n\
3410 \n\
3411 Command Aborts Bus Device Resets Host Adapter Resets\n\
3412 Target Requested Completed Requested Completed Requested Completed\n\
3413 ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
3414 ====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
3415 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3416 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3417 if (!tgt_flags->tgt_exists)
3418 continue;
3419 seq_printf(m, " %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n",
3420 tgt, tgt_stats[tgt].aborts_request,
3421 tgt_stats[tgt].aborts_tried,
3422 tgt_stats[tgt].aborts_done,
3423 tgt_stats[tgt].bdr_request,
3424 tgt_stats[tgt].bdr_tried,
3425 tgt_stats[tgt].bdr_done,
3426 tgt_stats[tgt].adapter_reset_req,
3427 tgt_stats[tgt].adapter_reset_attempt,
3428 tgt_stats[tgt].adapter_reset_done);
3429 }
3430 seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
3431 seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
3432 return 0;
3433 }
3434
3435
3436
3437
3438
3439 __printf(2, 4)
3440 static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
3441 struct blogic_adapter *adapter, ...)
3442 {
3443 static char buf[BLOGIC_LINEBUF_SIZE];
3444 static bool begin = true;
3445 va_list args;
3446 int len = 0;
3447
3448 va_start(args, adapter);
3449 len = vscnprintf(buf, sizeof(buf), fmt, args);
3450 va_end(args);
3451 if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
3452 static int msglines = 0;
3453 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3454 adapter->msgbuflen += len;
3455 if (++msglines <= 2)
3456 printk("%sscsi: %s", blogic_msglevelmap[msglevel], buf);
3457 } else if (msglevel == BLOGIC_INFO_LEVEL) {
3458 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3459 adapter->msgbuflen += len;
3460 if (begin) {
3461 if (buf[0] != '\n' || len > 1)
3462 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
3463 } else
3464 pr_cont("%s", buf);
3465 } else {
3466 if (begin) {
3467 if (adapter != NULL && adapter->adapter_initd)
3468 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
3469 else
3470 printk("%s%s", blogic_msglevelmap[msglevel], buf);
3471 } else
3472 pr_cont("%s", buf);
3473 }
3474 begin = (buf[len - 1] == '\n');
3475 }
3476
3477
3478
3479
3480
3481
3482
3483 static bool __init blogic_parse(char **str, char *keyword)
3484 {
3485 char *pointer = *str;
3486 while (*keyword != '\0') {
3487 char strch = *pointer++;
3488 char keywordch = *keyword++;
3489 if (strch >= 'A' && strch <= 'Z')
3490 strch += 'a' - 'Z';
3491 if (keywordch >= 'A' && keywordch <= 'Z')
3492 keywordch += 'a' - 'Z';
3493 if (strch != keywordch)
3494 return false;
3495 }
3496 *str = pointer;
3497 return true;
3498 }
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518 static int __init blogic_parseopts(char *options)
3519 {
3520 while (true) {
3521 struct blogic_drvr_options *drvr_opts =
3522 &blogic_drvr_options[blogic_drvr_options_count++];
3523 int tgt_id;
3524
3525 memset(drvr_opts, 0, sizeof(struct blogic_drvr_options));
3526 while (*options != '\0' && *options != ';') {
3527 if (blogic_parse(&options, "NoProbePCI"))
3528 blogic_probe_options.noprobe_pci = true;
3529 else if (blogic_parse(&options, "NoProbe"))
3530 blogic_probe_options.noprobe = true;
3531 else if (blogic_parse(&options, "NoSortPCI"))
3532 blogic_probe_options.nosort_pci = true;
3533 else if (blogic_parse(&options, "MultiMasterFirst"))
3534 blogic_probe_options.multimaster_first = true;
3535 else if (blogic_parse(&options, "FlashPointFirst"))
3536 blogic_probe_options.flashpoint_first = true;
3537
3538 else if (blogic_parse(&options, "QueueDepth:[") ||
3539 blogic_parse(&options, "QD:[")) {
3540 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
3541 unsigned short qdepth = simple_strtoul(options, &options, 0);
3542 if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
3543 blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
3544 return 0;
3545 }
3546 drvr_opts->qdepth[tgt_id] = qdepth;
3547 if (*options == ',')
3548 options++;
3549 else if (*options == ']')
3550 break;
3551 else {
3552 blogic_err("BusLogic: Invalid Driver Options (',' or ']' expected at '%s')\n", NULL, options);
3553 return 0;
3554 }
3555 }
3556 if (*options != ']') {
3557 blogic_err("BusLogic: Invalid Driver Options (']' expected at '%s')\n", NULL, options);
3558 return 0;
3559 } else
3560 options++;
3561 } else if (blogic_parse(&options, "QueueDepth:") || blogic_parse(&options, "QD:")) {
3562 unsigned short qdepth = simple_strtoul(options, &options, 0);
3563 if (qdepth == 0 ||
3564 qdepth > BLOGIC_MAX_TAG_DEPTH) {
3565 blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
3566 return 0;
3567 }
3568 drvr_opts->common_qdepth = qdepth;
3569 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3570 drvr_opts->qdepth[tgt_id] = qdepth;
3571 } else if (blogic_parse(&options, "TaggedQueuing:") ||
3572 blogic_parse(&options, "TQ:")) {
3573 if (blogic_parse(&options, "Default")) {
3574 drvr_opts->tagq_ok = 0x0000;
3575 drvr_opts->tagq_ok_mask = 0x0000;
3576 } else if (blogic_parse(&options, "Enable")) {
3577 drvr_opts->tagq_ok = 0xFFFF;
3578 drvr_opts->tagq_ok_mask = 0xFFFF;
3579 } else if (blogic_parse(&options, "Disable")) {
3580 drvr_opts->tagq_ok = 0x0000;
3581 drvr_opts->tagq_ok_mask = 0xFFFF;
3582 } else {
3583 unsigned short tgt_bit;
3584 for (tgt_id = 0, tgt_bit = 1;
3585 tgt_id < BLOGIC_MAXDEV;
3586 tgt_id++, tgt_bit <<= 1)
3587 switch (*options++) {
3588 case 'Y':
3589 drvr_opts->tagq_ok |= tgt_bit;
3590 drvr_opts->tagq_ok_mask |= tgt_bit;
3591 break;
3592 case 'N':
3593 drvr_opts->tagq_ok &= ~tgt_bit;
3594 drvr_opts->tagq_ok_mask |= tgt_bit;
3595 break;
3596 case 'X':
3597 break;
3598 default:
3599 options--;
3600 tgt_id = BLOGIC_MAXDEV;
3601 break;
3602 }
3603 }
3604 }
3605
3606 else if (blogic_parse(&options, "BusSettleTime:") ||
3607 blogic_parse(&options, "BST:")) {
3608 unsigned short bus_settle_time =
3609 simple_strtoul(options, &options, 0);
3610 if (bus_settle_time > 5 * 60) {
3611 blogic_err("BusLogic: Invalid Driver Options (invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
3612 return 0;
3613 }
3614 drvr_opts->bus_settle_time = bus_settle_time;
3615 } else if (blogic_parse(&options,
3616 "InhibitTargetInquiry"))
3617 drvr_opts->stop_tgt_inquiry = true;
3618
3619 else if (blogic_parse(&options, "TraceProbe"))
3620 blogic_global_options.trace_probe = true;
3621 else if (blogic_parse(&options, "TraceHardwareReset"))
3622 blogic_global_options.trace_hw_reset = true;
3623 else if (blogic_parse(&options, "TraceConfiguration"))
3624 blogic_global_options.trace_config = true;
3625 else if (blogic_parse(&options, "TraceErrors"))
3626 blogic_global_options.trace_err = true;
3627 else if (blogic_parse(&options, "Debug")) {
3628 blogic_global_options.trace_probe = true;
3629 blogic_global_options.trace_hw_reset = true;
3630 blogic_global_options.trace_config = true;
3631 blogic_global_options.trace_err = true;
3632 }
3633 if (*options == ',')
3634 options++;
3635 else if (*options != ';' && *options != '\0') {
3636 blogic_err("BusLogic: Unexpected Driver Option '%s' ignored\n", NULL, options);
3637 *options = '\0';
3638 }
3639 }
3640 if (!(blogic_drvr_options_count == 0 ||
3641 blogic_probeinfo_count == 0 ||
3642 blogic_drvr_options_count == blogic_probeinfo_count)) {
3643 blogic_err("BusLogic: Invalid Driver Options (all or no I/O Addresses must be specified)\n", NULL);
3644 return 0;
3645 }
3646
3647
3648
3649
3650 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3651 if (drvr_opts->qdepth[tgt_id] == 1) {
3652 unsigned short tgt_bit = 1 << tgt_id;
3653 drvr_opts->tagq_ok &= ~tgt_bit;
3654 drvr_opts->tagq_ok_mask |= tgt_bit;
3655 }
3656 if (*options == ';')
3657 options++;
3658 if (*options == '\0')
3659 return 0;
3660 }
3661 return 1;
3662 }
3663
3664
3665
3666
3667
3668 static struct scsi_host_template blogic_template = {
3669 .module = THIS_MODULE,
3670 .proc_name = "BusLogic",
3671 .write_info = blogic_write_info,
3672 .show_info = blogic_show_info,
3673 .name = "BusLogic",
3674 .info = blogic_drvr_info,
3675 .queuecommand = blogic_qcmd,
3676 .slave_configure = blogic_slaveconfig,
3677 .bios_param = blogic_diskparam,
3678 .eh_host_reset_handler = blogic_hostreset,
3679 #if 0
3680 .eh_abort_handler = blogic_abort,
3681 #endif
3682 .max_sectors = 128,
3683 };
3684
3685
3686
3687
3688
3689 static int __init blogic_setup(char *str)
3690 {
3691 int ints[3];
3692
3693 (void) get_options(str, ARRAY_SIZE(ints), ints);
3694
3695 if (ints[0] != 0) {
3696 blogic_err("BusLogic: Obsolete Command Line Entry Format Ignored\n", NULL);
3697 return 0;
3698 }
3699 if (str == NULL || *str == '\0')
3700 return 0;
3701 return blogic_parseopts(str);
3702 }
3703
3704
3705
3706
3707
3708 static void __exit blogic_exit(void)
3709 {
3710 struct blogic_adapter *ha, *next;
3711
3712 list_for_each_entry_safe(ha, next, &blogic_host_list, host_list)
3713 blogic_deladapter(ha);
3714 }
3715
3716 __setup("BusLogic=", blogic_setup);
3717
3718 #ifdef MODULE
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728 static const struct pci_device_id blogic_pci_tbl[] = {
3729 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
3730 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
3731 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
3732 {0, },
3733 };
3734 #endif
3735 MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
3736
3737 module_init(blogic_init);
3738 module_exit(blogic_exit);