blob: 39ef0740699717f6eaaa3a35e0c99180f4ba6616 [file] [log] [blame]
Thomas Gleixner58751752019-05-31 01:09:46 -07001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002
3/*
4
5 Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
6
7 Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
10 The author respectfully requests that any modifications to this software be
11 sent directly to him for evaluation and testing.
12
13 Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
14 advice has been invaluable, to David Gentzel, for writing the original Linux
15 BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
16
17 Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
18 Manager available as freely redistributable source code.
19
20*/
21
Khalid Azizeeceec92013-09-13 13:44:06 -060022#define blogic_drvr_version "2.1.17"
23#define blogic_drvr_date "12 September 2013"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/interrupt.h>
28#include <linux/types.h>
29#include <linux/blkdev.h>
30#include <linux/delay.h>
31#include <linux/ioport.h>
32#include <linux/mm.h>
33#include <linux/stat.h>
34#include <linux/pci.h>
35#include <linux/spinlock.h>
Marcelo Feitoza Parisi60c904a2006-03-28 01:56:47 -080036#include <linux/jiffies.h>
Matthias Gehre910638a2006-03-28 01:56:48 -080037#include <linux/dma-mapping.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
Christoph Hellwig1442f762020-03-24 08:25:26 +010039#include <linux/msdos_partition.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <scsi/scsicam.h>
41
42#include <asm/dma.h>
43#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45#include <scsi/scsi.h>
46#include <scsi/scsi_cmnd.h>
47#include <scsi/scsi_device.h>
48#include <scsi/scsi_host.h>
49#include <scsi/scsi_tcq.h>
50#include "BusLogic.h"
51#include "FlashPoint.c"
52
53#ifndef FAILURE
54#define FAILURE (-1)
55#endif
56
Khalid Aziz839cb992013-05-16 19:44:13 -060057static struct scsi_host_template blogic_template;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59/*
Khalid Aziz839cb992013-05-16 19:44:13 -060060 blogic_drvr_options_count is a count of the number of BusLogic Driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 Options specifications provided via the Linux Kernel Command Line or via
62 the Loadable Kernel Module Installation Facility.
63*/
64
Khalid Aziz839cb992013-05-16 19:44:13 -060065static int blogic_drvr_options_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67
68/*
Khalid Aziz839cb992013-05-16 19:44:13 -060069 blogic_drvr_options is an array of Driver Options structures representing
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 BusLogic Driver Options specifications provided via the Linux Kernel Command
71 Line or via the Loadable Kernel Module Installation Facility.
72*/
73
Khalid Aziz839cb992013-05-16 19:44:13 -060074static struct blogic_drvr_options blogic_drvr_options[BLOGIC_MAX_ADAPTERS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76
77/*
78 BusLogic can be assigned a string by insmod.
79*/
80
81MODULE_LICENSE("GPL");
82#ifdef MODULE
83static char *BusLogic;
84module_param(BusLogic, charp, 0);
85#endif
86
87
88/*
Khalid Aziz839cb992013-05-16 19:44:13 -060089 blogic_probe_options is a set of Probe Options to be applied across
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 all BusLogic Host Adapters.
91*/
92
Khalid Aziz839cb992013-05-16 19:44:13 -060093static struct blogic_probe_options blogic_probe_options;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95
96/*
Khalid Aziz839cb992013-05-16 19:44:13 -060097 blogic_global_options is a set of Global Options to be applied across
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 all BusLogic Host Adapters.
99*/
100
Khalid Aziz839cb992013-05-16 19:44:13 -0600101static struct blogic_global_options blogic_global_options;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
Khalid Aziz839cb992013-05-16 19:44:13 -0600103static LIST_HEAD(blogic_host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600106 blogic_probeinfo_count is the number of entries in blogic_probeinfo_list.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107*/
108
Khalid Aziz839cb992013-05-16 19:44:13 -0600109static int blogic_probeinfo_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111
112/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600113 blogic_probeinfo_list is the list of I/O Addresses and Bus Probe Information
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 to be checked for potential BusLogic Host Adapters. It is initialized by
115 interrogating the PCI Configuration Space on PCI machines as well as from the
116 list of standard BusLogic I/O Addresses.
117*/
118
Khalid Aziz839cb992013-05-16 19:44:13 -0600119static struct blogic_probeinfo *blogic_probeinfo_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121
122/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600123 blogic_cmd_failure_reason holds a string identifying the reason why a
124 call to blogic_cmd failed. It is only non-NULL when blogic_cmd
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 returns a failure code.
126*/
127
Khalid Aziz839cb992013-05-16 19:44:13 -0600128static char *blogic_cmd_failure_reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
130/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600131 blogic_announce_drvr announces the Driver Version and Date, Author's
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 Name, Copyright Notice, and Electronic Mail Address.
133*/
134
Khalid Aziz839cb992013-05-16 19:44:13 -0600135static void blogic_announce_drvr(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Khalid Aziz839cb992013-05-16 19:44:13 -0600137 blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
Colin Ian King43622692020-01-08 19:38:00 +0000138 blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139}
140
141
142/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600143 blogic_drvr_info returns the Host Adapter Name to identify this SCSI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 Driver and Host Adapter.
145*/
146
Khalid Aziz839cb992013-05-16 19:44:13 -0600147static const char *blogic_drvr_info(struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Khalid Aziz839cb992013-05-16 19:44:13 -0600149 struct blogic_adapter *adapter =
150 (struct blogic_adapter *) host->hostdata;
151 return adapter->full_model;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
153
154/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600155 blogic_init_ccbs initializes a group of Command Control Blocks (CCBs)
156 for Host Adapter from the blk_size bytes located at blk_pointer. The newly
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 created CCBs are added to Host Adapter's free list.
158*/
159
Khalid Aziz839cb992013-05-16 19:44:13 -0600160static void blogic_init_ccbs(struct blogic_adapter *adapter, void *blk_pointer,
161 int blk_size, dma_addr_t blkp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Khalid Aziz839cb992013-05-16 19:44:13 -0600163 struct blogic_ccb *ccb = (struct blogic_ccb *) blk_pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 unsigned int offset = 0;
Khalid Aziz839cb992013-05-16 19:44:13 -0600165 memset(blk_pointer, 0, blk_size);
166 ccb->allocgrp_head = blkp;
167 ccb->allocgrp_size = blk_size;
168 while ((blk_size -= sizeof(struct blogic_ccb)) >= 0) {
169 ccb->status = BLOGIC_CCB_FREE;
170 ccb->adapter = adapter;
171 ccb->dma_handle = (u32) blkp + offset;
172 if (blogic_flashpoint_type(adapter)) {
173 ccb->callback = blogic_qcompleted_ccb;
174 ccb->base_addr = adapter->fpinfo.base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600176 ccb->next = adapter->free_ccbs;
177 ccb->next_all = adapter->all_ccbs;
178 adapter->free_ccbs = ccb;
179 adapter->all_ccbs = ccb;
180 adapter->alloc_ccbs++;
181 ccb++;
182 offset += sizeof(struct blogic_ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 }
184}
185
186
187/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600188 blogic_create_initccbs allocates the initial CCBs for Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189*/
190
Khalid Aziz839cb992013-05-16 19:44:13 -0600191static bool __init blogic_create_initccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192{
Khalid Aziz839cb992013-05-16 19:44:13 -0600193 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
194 void *blk_pointer;
195 dma_addr_t blkp;
196
197 while (adapter->alloc_ccbs < adapter->initccbs) {
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200198 blk_pointer = dma_alloc_coherent(&adapter->pci_device->dev,
199 blk_size, &blkp, GFP_KERNEL);
Khalid Aziz839cb992013-05-16 19:44:13 -0600200 if (blk_pointer == NULL) {
201 blogic_err("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
202 adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 return false;
204 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600205 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 }
207 return true;
208}
209
210
211/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600212 blogic_destroy_ccbs deallocates the CCBs for Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213*/
214
Khalid Aziz839cb992013-05-16 19:44:13 -0600215static void blogic_destroy_ccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
Khalid Aziz839cb992013-05-16 19:44:13 -0600217 struct blogic_ccb *next_ccb = adapter->all_ccbs, *ccb, *lastccb = NULL;
218 adapter->all_ccbs = NULL;
219 adapter->free_ccbs = NULL;
220 while ((ccb = next_ccb) != NULL) {
221 next_ccb = ccb->next_all;
222 if (ccb->allocgrp_head) {
223 if (lastccb)
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200224 dma_free_coherent(&adapter->pci_device->dev,
Khalid Aziz839cb992013-05-16 19:44:13 -0600225 lastccb->allocgrp_size, lastccb,
226 lastccb->allocgrp_head);
227 lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 }
229 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600230 if (lastccb)
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200231 dma_free_coherent(&adapter->pci_device->dev,
232 lastccb->allocgrp_size, lastccb,
233 lastccb->allocgrp_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234}
235
236
237/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600238 blogic_create_addlccbs allocates Additional CCBs for Host Adapter. If
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 allocation fails and there are no remaining CCBs available, the Driver Queue
240 Depth is decreased to a known safe value to avoid potential deadlocks when
241 multiple host adapters share the same IRQ Channel.
242*/
243
Khalid Aziz839cb992013-05-16 19:44:13 -0600244static void blogic_create_addlccbs(struct blogic_adapter *adapter,
245 int addl_ccbs, bool print_success)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246{
Khalid Aziz839cb992013-05-16 19:44:13 -0600247 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
248 int prev_alloc = adapter->alloc_ccbs;
249 void *blk_pointer;
250 dma_addr_t blkp;
251 if (addl_ccbs <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return;
Khalid Aziz839cb992013-05-16 19:44:13 -0600253 while (adapter->alloc_ccbs - prev_alloc < addl_ccbs) {
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200254 blk_pointer = dma_alloc_coherent(&adapter->pci_device->dev,
255 blk_size, &blkp, GFP_KERNEL);
Khalid Aziz839cb992013-05-16 19:44:13 -0600256 if (blk_pointer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600258 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600260 if (adapter->alloc_ccbs > prev_alloc) {
261 if (print_success)
262 blogic_notice("Allocated %d additional CCBs (total now %d)\n", adapter, adapter->alloc_ccbs - prev_alloc, adapter->alloc_ccbs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 return;
264 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600265 blogic_notice("Failed to allocate additional CCBs\n", adapter);
266 if (adapter->drvr_qdepth > adapter->alloc_ccbs - adapter->tgt_count) {
267 adapter->drvr_qdepth = adapter->alloc_ccbs - adapter->tgt_count;
268 adapter->scsi_host->can_queue = adapter->drvr_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 }
270}
271
272/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600273 blogic_alloc_ccb allocates a CCB from Host Adapter's free list,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 allocating more memory from the Kernel if necessary. The Host Adapter's
275 Lock should already have been acquired by the caller.
276*/
277
Khalid Aziz839cb992013-05-16 19:44:13 -0600278static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279{
Khalid Aziz839cb992013-05-16 19:44:13 -0600280 static unsigned long serial;
281 struct blogic_ccb *ccb;
282 ccb = adapter->free_ccbs;
283 if (ccb != NULL) {
284 ccb->serial = ++serial;
285 adapter->free_ccbs = ccb->next;
286 ccb->next = NULL;
287 if (adapter->free_ccbs == NULL)
288 blogic_create_addlccbs(adapter, adapter->inc_ccbs,
289 true);
290 return ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600292 blogic_create_addlccbs(adapter, adapter->inc_ccbs, true);
293 ccb = adapter->free_ccbs;
294 if (ccb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return NULL;
Khalid Aziz839cb992013-05-16 19:44:13 -0600296 ccb->serial = ++serial;
297 adapter->free_ccbs = ccb->next;
298 ccb->next = NULL;
299 return ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302
303/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600304 blogic_dealloc_ccb deallocates a CCB, returning it to the Host Adapter's
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 free list. The Host Adapter's Lock should already have been acquired by the
306 caller.
307*/
308
Khalid Azizeeceec92013-09-13 13:44:06 -0600309static void blogic_dealloc_ccb(struct blogic_ccb *ccb, int dma_unmap)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310{
Khalid Aziz839cb992013-05-16 19:44:13 -0600311 struct blogic_adapter *adapter = ccb->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Khalid Azizeeceec92013-09-13 13:44:06 -0600313 if (ccb->command != NULL)
314 scsi_dma_unmap(ccb->command);
315 if (dma_unmap)
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200316 dma_unmap_single(&adapter->pci_device->dev, ccb->sensedata,
317 ccb->sense_datalen, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Khalid Aziz839cb992013-05-16 19:44:13 -0600319 ccb->command = NULL;
320 ccb->status = BLOGIC_CCB_FREE;
321 ccb->next = adapter->free_ccbs;
322 adapter->free_ccbs = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323}
324
325
326/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600327 blogic_cmd sends the command opcode to adapter, optionally
328 providing paramlen bytes of param and receiving at most
329 replylen bytes of reply; any excess reply data is received but
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 discarded.
331
332 On success, this function returns the number of reply bytes read from
333 the Host Adapter (including any discarded data); on failure, it returns
334 -1 if the command was invalid, or -2 if a timeout occurred.
335
Khalid Aziz839cb992013-05-16 19:44:13 -0600336 blogic_cmd is called exclusively during host adapter detection and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 initialization, so performance and latency are not critical, and exclusive
338 access to the Host Adapter hardware is assumed. Once the host adapter and
339 driver are initialized, the only Host Adapter command that is issued is the
340 single byte Execute Mailbox Command operation code, which does not require
341 waiting for the Host Adapter Ready bit to be set in the Status Register.
342*/
343
Khalid Aziz839cb992013-05-16 19:44:13 -0600344static int blogic_cmd(struct blogic_adapter *adapter, enum blogic_opcode opcode,
345 void *param, int paramlen, void *reply, int replylen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Khalid Aziz839cb992013-05-16 19:44:13 -0600347 unsigned char *param_p = (unsigned char *) param;
348 unsigned char *reply_p = (unsigned char *) reply;
349 union blogic_stat_reg statusreg;
350 union blogic_int_reg intreg;
351 unsigned long processor_flag = 0;
352 int reply_b = 0, result;
353 long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 /*
355 Clear out the Reply Data if provided.
356 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600357 if (replylen > 0)
358 memset(reply, 0, replylen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600360 If the IRQ Channel has not yet been acquired, then interrupts
361 must be disabled while issuing host adapter commands since a
362 Command Complete interrupt could occur if the IRQ Channel was
363 previously enabled by another BusLogic Host Adapter or another
364 driver sharing the same IRQ Channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600366 if (!adapter->irq_acquired)
367 local_irq_save(processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600369 Wait for the Host Adapter Ready bit to be set and the
370 Command/Parameter Register Busy bit to be reset in the Status
371 Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600373 timeout = 10000;
374 while (--timeout >= 0) {
375 statusreg.all = blogic_rdstatus(adapter);
376 if (statusreg.sr.adapter_ready && !statusreg.sr.cmd_param_busy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 break;
378 udelay(100);
379 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600380 if (timeout < 0) {
381 blogic_cmd_failure_reason =
382 "Timeout waiting for Host Adapter Ready";
383 result = -2;
384 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
386 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600387 Write the opcode to the Command/Parameter Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600389 adapter->adapter_cmd_complete = false;
390 blogic_setcmdparam(adapter, opcode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 /*
392 Write any additional Parameter Bytes.
393 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600394 timeout = 10000;
395 while (paramlen > 0 && --timeout >= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600397 Wait 100 microseconds to give the Host Adapter enough
398 time to determine whether the last value written to the
399 Command/Parameter Register was valid or not. If the
400 Command Complete bit is set in the Interrupt Register,
401 then the Command Invalid bit in the Status Register will
402 be reset if the Operation Code or Parameter was valid
403 and the command has completed, or set if the Operation
404 Code or Parameter was invalid. If the Data In Register
405 Ready bit is set in the Status Register, then the
406 Operation Code was valid, and data is waiting to be read
407 back from the Host Adapter. Otherwise, wait for the
408 Command/Parameter Register Busy bit in the Status
409 Register to be reset.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 */
411 udelay(100);
Khalid Aziz839cb992013-05-16 19:44:13 -0600412 intreg.all = blogic_rdint(adapter);
413 statusreg.all = blogic_rdstatus(adapter);
414 if (intreg.ir.cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600416 if (adapter->adapter_cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600418 if (statusreg.sr.datain_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600420 if (statusreg.sr.cmd_param_busy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -0600422 blogic_setcmdparam(adapter, *param_p++);
423 paramlen--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600425 if (timeout < 0) {
426 blogic_cmd_failure_reason =
427 "Timeout waiting for Parameter Acceptance";
428 result = -2;
429 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
431 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600432 The Modify I/O Address command does not cause a Command Complete
433 Interrupt.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600435 if (opcode == BLOGIC_MOD_IOADDR) {
436 statusreg.all = blogic_rdstatus(adapter);
437 if (statusreg.sr.cmd_invalid) {
438 blogic_cmd_failure_reason =
439 "Modify I/O Address Invalid";
440 result = -1;
441 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600443 if (blogic_global_options.trace_config)
Colin Ian King43622692020-01-08 19:38:00 +0000444 blogic_notice("blogic_cmd(%02X) Status = %02X: (Modify I/O Address)\n", adapter, opcode, statusreg.all);
Khalid Aziz839cb992013-05-16 19:44:13 -0600445 result = 0;
446 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 }
448 /*
449 Select an appropriate timeout value for awaiting command completion.
450 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600451 switch (opcode) {
452 case BLOGIC_INQ_DEV0TO7:
453 case BLOGIC_INQ_DEV8TO15:
454 case BLOGIC_INQ_DEV:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 /* Approximately 60 seconds. */
Khalid Aziz839cb992013-05-16 19:44:13 -0600456 timeout = 60 * 10000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 break;
458 default:
459 /* Approximately 1 second. */
Khalid Aziz839cb992013-05-16 19:44:13 -0600460 timeout = 10000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 break;
462 }
463 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600464 Receive any Reply Bytes, waiting for either the Command
465 Complete bit to be set in the Interrupt Register, or for the
466 Interrupt Handler to set the Host Adapter Command Completed
467 bit in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600469 while (--timeout >= 0) {
470 intreg.all = blogic_rdint(adapter);
471 statusreg.all = blogic_rdstatus(adapter);
472 if (intreg.ir.cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600474 if (adapter->adapter_cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600476 if (statusreg.sr.datain_ready) {
477 if (++reply_b <= replylen)
478 *reply_p++ = blogic_rddatain(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 else
Khalid Aziz839cb992013-05-16 19:44:13 -0600480 blogic_rddatain(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600482 if (opcode == BLOGIC_FETCH_LOCALRAM &&
483 statusreg.sr.adapter_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 break;
485 udelay(100);
486 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600487 if (timeout < 0) {
488 blogic_cmd_failure_reason =
489 "Timeout waiting for Command Complete";
490 result = -2;
491 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
493 /*
494 Clear any pending Command Complete Interrupt.
495 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600496 blogic_intreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 /*
498 Provide tracing information if requested.
499 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600500 if (blogic_global_options.trace_config) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -0600502 blogic_notice("blogic_cmd(%02X) Status = %02X: %2d ==> %2d:",
503 adapter, opcode, statusreg.all, replylen,
504 reply_b);
505 if (replylen > reply_b)
506 replylen = reply_b;
507 for (i = 0; i < replylen; i++)
508 blogic_notice(" %02X", adapter,
509 ((unsigned char *) reply)[i]);
510 blogic_notice("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 }
512 /*
513 Process Command Invalid conditions.
514 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600515 if (statusreg.sr.cmd_invalid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600517 Some early BusLogic Host Adapters may not recover
518 properly from a Command Invalid condition, so if this
519 appears to be the case, a Soft Reset is issued to the
520 Host Adapter. Potentially invalid commands are never
521 attempted after Mailbox Initialization is performed,
522 so there should be no Host Adapter state lost by a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 Soft Reset in response to a Command Invalid condition.
524 */
525 udelay(1000);
Khalid Aziz839cb992013-05-16 19:44:13 -0600526 statusreg.all = blogic_rdstatus(adapter);
527 if (statusreg.sr.cmd_invalid || statusreg.sr.rsvd ||
528 statusreg.sr.datain_ready ||
529 statusreg.sr.cmd_param_busy ||
530 !statusreg.sr.adapter_ready ||
531 !statusreg.sr.init_reqd ||
532 statusreg.sr.diag_active ||
533 statusreg.sr.diag_failed) {
534 blogic_softreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 udelay(1000);
536 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600537 blogic_cmd_failure_reason = "Command Invalid";
538 result = -1;
539 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 }
541 /*
542 Handle Excess Parameters Supplied conditions.
543 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600544 if (paramlen > 0) {
545 blogic_cmd_failure_reason = "Excess Parameters Supplied";
546 result = -1;
547 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 }
549 /*
550 Indicate the command completed successfully.
551 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600552 blogic_cmd_failure_reason = NULL;
553 result = reply_b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 /*
555 Restore the interrupt status if necessary and return.
556 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600557done:
558 if (!adapter->irq_acquired)
559 local_irq_restore(processor_flag);
560 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561}
562
563
564/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600565 blogic_add_probeaddr_isa appends a single ISA I/O Address to the list
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 of I/O Address and Bus Probe Information to be checked for potential BusLogic
567 Host Adapters.
568*/
569
Khalid Aziz839cb992013-05-16 19:44:13 -0600570static void __init blogic_add_probeaddr_isa(unsigned long io_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
Khalid Aziz839cb992013-05-16 19:44:13 -0600572 struct blogic_probeinfo *probeinfo;
573 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 return;
Khalid Aziz839cb992013-05-16 19:44:13 -0600575 probeinfo = &blogic_probeinfo_list[blogic_probeinfo_count++];
576 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
577 probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
578 probeinfo->io_addr = io_addr;
579 probeinfo->pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580}
581
582
583/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600584 blogic_init_probeinfo_isa initializes the list of I/O Address and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
586 only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
587*/
588
Khalid Aziz839cb992013-05-16 19:44:13 -0600589static void __init blogic_init_probeinfo_isa(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
591 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600592 If BusLogic Driver Options specifications requested that ISA
593 Bus Probes be inhibited, do not proceed further.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600595 if (blogic_probe_options.noprobe_isa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return;
597 /*
598 Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
599 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600600 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe330)
601 blogic_add_probeaddr_isa(0x330);
602 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe334)
603 blogic_add_probeaddr_isa(0x334);
604 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe230)
605 blogic_add_probeaddr_isa(0x230);
606 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe234)
607 blogic_add_probeaddr_isa(0x234);
608 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe130)
609 blogic_add_probeaddr_isa(0x130);
610 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe134)
611 blogic_add_probeaddr_isa(0x134);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612}
613
614
615#ifdef CONFIG_PCI
616
617
618/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600619 blogic_sort_probeinfo sorts a section of blogic_probeinfo_list in order
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 of increasing PCI Bus and Device Number.
621*/
622
Khalid Aziz839cb992013-05-16 19:44:13 -0600623static void __init blogic_sort_probeinfo(struct blogic_probeinfo
624 *probeinfo_list, int probeinfo_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
Khalid Aziz839cb992013-05-16 19:44:13 -0600626 int last_exchange = probeinfo_cnt - 1, bound, j;
627
628 while (last_exchange > 0) {
629 bound = last_exchange;
630 last_exchange = 0;
631 for (j = 0; j < bound; j++) {
632 struct blogic_probeinfo *probeinfo1 =
633 &probeinfo_list[j];
634 struct blogic_probeinfo *probeinfo2 =
635 &probeinfo_list[j + 1];
636 if (probeinfo1->bus > probeinfo2->bus ||
637 (probeinfo1->bus == probeinfo2->bus &&
638 (probeinfo1->dev > probeinfo2->dev))) {
639 struct blogic_probeinfo tmp_probeinfo;
640
641 memcpy(&tmp_probeinfo, probeinfo1,
642 sizeof(struct blogic_probeinfo));
643 memcpy(probeinfo1, probeinfo2,
644 sizeof(struct blogic_probeinfo));
645 memcpy(probeinfo2, &tmp_probeinfo,
646 sizeof(struct blogic_probeinfo));
647 last_exchange = j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 }
649 }
650 }
651}
652
653
654/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600655 blogic_init_mm_probeinfo initializes the list of I/O Address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 and Bus Probe Information to be checked for potential BusLogic MultiMaster
657 SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
658 machines as well as from the list of standard BusLogic MultiMaster ISA
659 I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
660*/
661
Khalid Aziz839cb992013-05-16 19:44:13 -0600662static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
Khalid Aziz839cb992013-05-16 19:44:13 -0600664 struct blogic_probeinfo *pr_probeinfo =
665 &blogic_probeinfo_list[blogic_probeinfo_count];
666 int nonpr_mmindex = blogic_probeinfo_count + 1;
667 int nonpr_mmcount = 0, mmcount = 0;
668 bool force_scan_order = false;
669 bool force_scan_order_checked = false;
670 bool addr_seen[6];
671 struct pci_dev *pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -0600673 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 return 0;
Khalid Aziz839cb992013-05-16 19:44:13 -0600675 blogic_probeinfo_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 for (i = 0; i < 6; i++)
Khalid Aziz839cb992013-05-16 19:44:13 -0600677 addr_seen[i] = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600679 Iterate over the MultiMaster PCI Host Adapters. For each
680 enumerated host adapter, determine whether its ISA Compatible
681 I/O Port is enabled and if so, whether it is assigned the
682 Primary I/O Address. A host adapter that is assigned the
683 Primary I/O Address will always be the preferred boot device.
684 The MultiMaster BIOS will first recognize a host adapter at
685 the Primary I/O Address, then any other PCI host adapters,
686 and finally any host adapters located at the remaining
687 standard ISA I/O Addresses. When a PCI host adapter is found
688 with its ISA Compatible I/O Port enabled, a command is issued
689 to disable the ISA Compatible I/O Port, and it is noted that the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 particular standard ISA I/O Address need not be probed.
691 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600692 pr_probeinfo->io_addr = 0;
693 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
694 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
695 pci_device)) != NULL) {
Khalid Aziz65419322013-09-25 11:45:11 -0600696 struct blogic_adapter *host_adapter = adapter;
Khalid Aziz839cb992013-05-16 19:44:13 -0600697 struct blogic_adapter_info adapter_info;
698 enum blogic_isa_ioport mod_ioaddr_req;
699 unsigned char bus;
700 unsigned char device;
701 unsigned int irq_ch;
702 unsigned long base_addr0;
703 unsigned long base_addr1;
704 unsigned long io_addr;
705 unsigned long pci_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Khalid Aziz839cb992013-05-16 19:44:13 -0600707 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 continue;
709
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200710 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 continue;
712
Khalid Aziz839cb992013-05-16 19:44:13 -0600713 bus = pci_device->bus->number;
714 device = pci_device->devfn >> 3;
715 irq_ch = pci_device->irq;
716 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
717 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Khalid Aziz839cb992013-05-16 19:44:13 -0600719 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
Colin Ian King43622692020-01-08 19:38:00 +0000720 blogic_err("BusLogic: Base Address0 0x%lX not I/O for MultiMaster Host Adapter\n", NULL, base_addr0);
721 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 continue;
723 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600724 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
Colin Ian King43622692020-01-08 19:38:00 +0000725 blogic_err("BusLogic: Base Address1 0x%lX not Memory for MultiMaster Host Adapter\n", NULL, base_addr1);
726 blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 continue;
728 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600729 if (irq_ch == 0) {
Colin Ian King43622692020-01-08 19:38:00 +0000730 blogic_err("BusLogic: IRQ Channel %d invalid for MultiMaster Host Adapter\n", NULL, irq_ch);
731 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 continue;
733 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600734 if (blogic_global_options.trace_probe) {
Colin Ian King43622692020-01-08 19:38:00 +0000735 blogic_notice("BusLogic: PCI MultiMaster Host Adapter detected at\n", NULL);
736 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 }
738 /*
739 Issue the Inquire PCI Host Adapter Information command to determine
740 the ISA Compatible I/O Port. If the ISA Compatible I/O Port is
741 known and enabled, note that the particular Standard ISA I/O
742 Address should not be probed.
743 */
Khalid Aziz65419322013-09-25 11:45:11 -0600744 host_adapter->io_addr = io_addr;
745 blogic_intreset(host_adapter);
746 if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
Khalid Aziz839cb992013-05-16 19:44:13 -0600747 &adapter_info, sizeof(adapter_info)) ==
748 sizeof(adapter_info)) {
749 if (adapter_info.isa_port < 6)
750 addr_seen[adapter_info.isa_port] = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 } else
Khalid Aziz839cb992013-05-16 19:44:13 -0600752 adapter_info.isa_port = BLOGIC_IO_DISABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600754 Issue the Modify I/O Address command to disable the
755 ISA Compatible I/O Port. On PCI Host Adapters, the
756 Modify I/O Address command allows modification of the
757 ISA compatible I/O Address that the Host Adapter
758 responds to; it does not affect the PCI compliant
759 I/O Address assigned at system initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600761 mod_ioaddr_req = BLOGIC_IO_DISABLE;
Khalid Aziz65419322013-09-25 11:45:11 -0600762 blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
Khalid Aziz839cb992013-05-16 19:44:13 -0600763 sizeof(mod_ioaddr_req), NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600765 For the first MultiMaster Host Adapter enumerated,
766 issue the Fetch Host Adapter Local RAM command to read
767 byte 45 of the AutoSCSI area, for the setting of the
768 "Use Bus And Device # For PCI Scanning Seq." option.
769 Issue the Inquire Board ID command since this option is
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 only valid for the BT-948/958/958D.
771 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600772 if (!force_scan_order_checked) {
773 struct blogic_fetch_localram fetch_localram;
774 struct blogic_autoscsi_byte45 autoscsi_byte45;
775 struct blogic_board_id id;
776
777 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
778 fetch_localram.count = sizeof(autoscsi_byte45);
Khalid Aziz65419322013-09-25 11:45:11 -0600779 blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM,
Khalid Aziz839cb992013-05-16 19:44:13 -0600780 &fetch_localram, sizeof(fetch_localram),
781 &autoscsi_byte45,
782 sizeof(autoscsi_byte45));
Khalid Aziz65419322013-09-25 11:45:11 -0600783 blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0,
784 &id, sizeof(id));
Khalid Aziz839cb992013-05-16 19:44:13 -0600785 if (id.fw_ver_digit1 == '5')
786 force_scan_order =
787 autoscsi_byte45.force_scan_order;
788 force_scan_order_checked = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 }
790 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600791 Determine whether this MultiMaster Host Adapter has its
792 ISA Compatible I/O Port enabled and is assigned the
793 Primary I/O Address. If it does, then it is the Primary
794 MultiMaster Host Adapter and must be recognized first.
795 If it does not, then it is added to the list for probing
796 after any Primary MultiMaster Host Adapter is probed.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600798 if (adapter_info.isa_port == BLOGIC_IO_330) {
799 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
800 pr_probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
801 pr_probeinfo->io_addr = io_addr;
802 pr_probeinfo->pci_addr = pci_addr;
803 pr_probeinfo->bus = bus;
804 pr_probeinfo->dev = device;
805 pr_probeinfo->irq_ch = irq_ch;
806 pr_probeinfo->pci_device = pci_dev_get(pci_device);
807 mmcount++;
808 } else if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
809 struct blogic_probeinfo *probeinfo =
810 &blogic_probeinfo_list[blogic_probeinfo_count++];
811 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
812 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
813 probeinfo->io_addr = io_addr;
814 probeinfo->pci_addr = pci_addr;
815 probeinfo->bus = bus;
816 probeinfo->dev = device;
817 probeinfo->irq_ch = irq_ch;
818 probeinfo->pci_device = pci_dev_get(pci_device);
819 nonpr_mmcount++;
820 mmcount++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 } else
Colin Ian King43622692020-01-08 19:38:00 +0000822 blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
824 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600825 If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq."
826 option is ON for the first enumerated MultiMaster Host Adapter,
827 and if that host adapter is a BT-948/958/958D, then the
828 MultiMaster BIOS will recognize MultiMaster Host Adapters in
829 the order of increasing PCI Bus and Device Number. In that case,
830 sort the probe information into the same order the BIOS uses.
831 If this option is OFF, then the MultiMaster BIOS will recognize
832 MultiMaster Host Adapters in the order they are enumerated by
833 the PCI BIOS, and hence no sorting is necessary.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600835 if (force_scan_order)
836 blogic_sort_probeinfo(&blogic_probeinfo_list[nonpr_mmindex],
837 nonpr_mmcount);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600839 If no PCI MultiMaster Host Adapter is assigned the Primary
840 I/O Address, then the Primary I/O Address must be probed
841 explicitly before any PCI host adapters are probed.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600843 if (!blogic_probe_options.noprobe_isa)
844 if (pr_probeinfo->io_addr == 0 &&
845 (!blogic_probe_options.limited_isa ||
846 blogic_probe_options.probe330)) {
847 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
848 pr_probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
849 pr_probeinfo->io_addr = 0x330;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 }
851 /*
852 Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
853 omitting the Primary I/O Address which has already been handled.
854 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600855 if (!blogic_probe_options.noprobe_isa) {
856 if (!addr_seen[1] &&
857 (!blogic_probe_options.limited_isa ||
858 blogic_probe_options.probe334))
859 blogic_add_probeaddr_isa(0x334);
860 if (!addr_seen[2] &&
861 (!blogic_probe_options.limited_isa ||
862 blogic_probe_options.probe230))
863 blogic_add_probeaddr_isa(0x230);
864 if (!addr_seen[3] &&
865 (!blogic_probe_options.limited_isa ||
866 blogic_probe_options.probe234))
867 blogic_add_probeaddr_isa(0x234);
868 if (!addr_seen[4] &&
869 (!blogic_probe_options.limited_isa ||
870 blogic_probe_options.probe130))
871 blogic_add_probeaddr_isa(0x130);
872 if (!addr_seen[5] &&
873 (!blogic_probe_options.limited_isa ||
874 blogic_probe_options.probe134))
875 blogic_add_probeaddr_isa(0x134);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 }
877 /*
878 Iterate over the older non-compliant MultiMaster PCI Host Adapters,
879 noting the PCI bus location and assigned IRQ Channel.
880 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600881 pci_device = NULL;
882 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
883 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
884 pci_device)) != NULL) {
885 unsigned char bus;
886 unsigned char device;
887 unsigned int irq_ch;
888 unsigned long io_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889
Khalid Aziz839cb992013-05-16 19:44:13 -0600890 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 continue;
892
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200893 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 continue;
895
Khalid Aziz839cb992013-05-16 19:44:13 -0600896 bus = pci_device->bus->number;
897 device = pci_device->devfn >> 3;
898 irq_ch = pci_device->irq;
899 io_addr = pci_resource_start(pci_device, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
Khalid Aziz839cb992013-05-16 19:44:13 -0600901 if (io_addr == 0 || irq_ch == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -0600903 for (i = 0; i < blogic_probeinfo_count; i++) {
904 struct blogic_probeinfo *probeinfo =
905 &blogic_probeinfo_list[i];
906 if (probeinfo->io_addr == io_addr &&
907 probeinfo->adapter_type == BLOGIC_MULTIMASTER) {
908 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
909 probeinfo->pci_addr = 0;
910 probeinfo->bus = bus;
911 probeinfo->dev = device;
912 probeinfo->irq_ch = irq_ch;
913 probeinfo->pci_device = pci_dev_get(pci_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 break;
915 }
916 }
917 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600918 return mmcount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919}
920
921
922/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600923 blogic_init_fp_probeinfo initializes the list of I/O Address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 and Bus Probe Information to be checked for potential BusLogic FlashPoint
925 Host Adapters by interrogating the PCI Configuration Space. It returns the
926 number of FlashPoint Host Adapters found.
927*/
928
Khalid Aziz839cb992013-05-16 19:44:13 -0600929static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
Khalid Aziz839cb992013-05-16 19:44:13 -0600931 int fpindex = blogic_probeinfo_count, fpcount = 0;
932 struct pci_dev *pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 /*
934 Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
935 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600936 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
937 PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
938 pci_device)) != NULL) {
939 unsigned char bus;
940 unsigned char device;
941 unsigned int irq_ch;
942 unsigned long base_addr0;
943 unsigned long base_addr1;
944 unsigned long io_addr;
945 unsigned long pci_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
Khalid Aziz839cb992013-05-16 19:44:13 -0600947 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 continue;
949
Christoph Hellwig17a361b2018-10-10 18:03:24 +0200950 if (dma_set_mask(&pci_device->dev, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 continue;
952
Khalid Aziz839cb992013-05-16 19:44:13 -0600953 bus = pci_device->bus->number;
954 device = pci_device->devfn >> 3;
955 irq_ch = pci_device->irq;
956 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
957 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
Matthew Wilcox78b4b052008-03-13 06:55:08 -0600958#ifdef CONFIG_SCSI_FLASHPOINT
Khalid Aziz839cb992013-05-16 19:44:13 -0600959 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
Colin Ian King43622692020-01-08 19:38:00 +0000960 blogic_err("BusLogic: Base Address0 0x%lX not I/O for FlashPoint Host Adapter\n", NULL, base_addr0);
961 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 continue;
963 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600964 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
Colin Ian King43622692020-01-08 19:38:00 +0000965 blogic_err("BusLogic: Base Address1 0x%lX not Memory for FlashPoint Host Adapter\n", NULL, base_addr1);
966 blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 continue;
968 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600969 if (irq_ch == 0) {
Colin Ian King43622692020-01-08 19:38:00 +0000970 blogic_err("BusLogic: IRQ Channel %d invalid for FlashPoint Host Adapter\n", NULL, irq_ch);
971 blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 continue;
973 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600974 if (blogic_global_options.trace_probe) {
Colin Ian King43622692020-01-08 19:38:00 +0000975 blogic_notice("BusLogic: FlashPoint Host Adapter detected at\n", NULL);
976 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600978 if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
979 struct blogic_probeinfo *probeinfo =
980 &blogic_probeinfo_list[blogic_probeinfo_count++];
981 probeinfo->adapter_type = BLOGIC_FLASHPOINT;
982 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
983 probeinfo->io_addr = io_addr;
984 probeinfo->pci_addr = pci_addr;
985 probeinfo->bus = bus;
986 probeinfo->dev = device;
987 probeinfo->irq_ch = irq_ch;
988 probeinfo->pci_device = pci_dev_get(pci_device);
989 fpcount++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 } else
Colin Ian King43622692020-01-08 19:38:00 +0000991 blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992#else
Colin Ian King43622692020-01-08 19:38:00 +0000993 blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", NULL, bus, device);
994 blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, irq %d, but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
995 blogic_err("BusLogic: support was omitted in this kernel configuration.\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996#endif
997 }
998 /*
999 The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
1000 increasing PCI Bus and Device Number, so sort the probe information into
1001 the same order the BIOS uses.
1002 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001003 blogic_sort_probeinfo(&blogic_probeinfo_list[fpindex], fpcount);
1004 return fpcount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005}
1006
1007
1008/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001009 blogic_init_probeinfo_list initializes the list of I/O Address and Bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 Probe Information to be checked for potential BusLogic SCSI Host Adapters by
1011 interrogating the PCI Configuration Space on PCI machines as well as from the
1012 list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
1013 FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
1014 probe for FlashPoint Host Adapters first unless the BIOS primary disk is
1015 controlled by the first PCI MultiMaster Host Adapter, in which case
1016 MultiMaster Host Adapters will be probed first. The BusLogic Driver Options
1017 specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
1018 a particular probe order.
1019*/
1020
Khalid Aziz839cb992013-05-16 19:44:13 -06001021static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022{
1023 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001024 If a PCI BIOS is present, interrogate it for MultiMaster and
1025 FlashPoint Host Adapters; otherwise, default to the standard
1026 ISA MultiMaster probe.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001028 if (!blogic_probe_options.noprobe_pci) {
1029 if (blogic_probe_options.multimaster_first) {
1030 blogic_init_mm_probeinfo(adapter);
1031 blogic_init_fp_probeinfo(adapter);
1032 } else if (blogic_probe_options.flashpoint_first) {
1033 blogic_init_fp_probeinfo(adapter);
1034 blogic_init_mm_probeinfo(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001036 int fpcount = blogic_init_fp_probeinfo(adapter);
1037 int mmcount = blogic_init_mm_probeinfo(adapter);
1038 if (fpcount > 0 && mmcount > 0) {
1039 struct blogic_probeinfo *probeinfo =
1040 &blogic_probeinfo_list[fpcount];
1041 struct blogic_adapter *myadapter = adapter;
1042 struct blogic_fetch_localram fetch_localram;
1043 struct blogic_bios_drvmap d0_mapbyte;
1044
1045 while (probeinfo->adapter_bus_type !=
1046 BLOGIC_PCI_BUS)
1047 probeinfo++;
1048 myadapter->io_addr = probeinfo->io_addr;
1049 fetch_localram.offset =
1050 BLOGIC_BIOS_BASE + BLOGIC_BIOS_DRVMAP;
1051 fetch_localram.count = sizeof(d0_mapbyte);
1052 blogic_cmd(myadapter, BLOGIC_FETCH_LOCALRAM,
1053 &fetch_localram,
1054 sizeof(fetch_localram),
1055 &d0_mapbyte,
1056 sizeof(d0_mapbyte));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001058 If the Map Byte for BIOS Drive 0 indicates
1059 that BIOS Drive 0 is controlled by this
1060 PCI MultiMaster Host Adapter, then reverse
1061 the probe order so that MultiMaster Host
1062 Adapters are probed before FlashPoint Host
1063 Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001065 if (d0_mapbyte.diskgeom != BLOGIC_BIOS_NODISK) {
1066 struct blogic_probeinfo saved_probeinfo[BLOGIC_MAX_ADAPTERS];
1067 int mmcount = blogic_probeinfo_count - fpcount;
1068
1069 memcpy(saved_probeinfo,
1070 blogic_probeinfo_list,
1071 blogic_probeinfo_count * sizeof(struct blogic_probeinfo));
1072 memcpy(&blogic_probeinfo_list[0],
1073 &saved_probeinfo[fpcount],
1074 mmcount * sizeof(struct blogic_probeinfo));
1075 memcpy(&blogic_probeinfo_list[mmcount],
1076 &saved_probeinfo[0],
1077 fpcount * sizeof(struct blogic_probeinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 }
1079 }
1080 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001081 } else {
1082 blogic_init_probeinfo_isa(adapter);
1083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084}
1085
1086
Matthew Wilcox78b4b052008-03-13 06:55:08 -06001087#else
Khalid Aziz839cb992013-05-16 19:44:13 -06001088#define blogic_init_probeinfo_list(adapter) \
1089 blogic_init_probeinfo_isa(adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090#endif /* CONFIG_PCI */
1091
1092
1093/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001094 blogic_failure prints a standardized error message, and then returns false.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095*/
1096
Khalid Aziz839cb992013-05-16 19:44:13 -06001097static bool blogic_failure(struct blogic_adapter *adapter, char *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
Khalid Aziz839cb992013-05-16 19:44:13 -06001099 blogic_announce_drvr(adapter);
1100 if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
1101 blogic_err("While configuring BusLogic PCI Host Adapter at\n",
1102 adapter);
Colin Ian King43622692020-01-08 19:38:00 +00001103 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 } else
Colin Ian King43622692020-01-08 19:38:00 +00001105 blogic_err("While configuring BusLogic Host Adapter at I/O Address 0x%lX:\n", adapter, adapter->io_addr);
Khalid Aziz839cb992013-05-16 19:44:13 -06001106 blogic_err("%s FAILED - DETACHING\n", adapter, msg);
1107 if (blogic_cmd_failure_reason != NULL)
1108 blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
1109 blogic_cmd_failure_reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 return false;
1111}
1112
1113
1114/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001115 blogic_probe probes for a BusLogic Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116*/
1117
Khalid Aziz839cb992013-05-16 19:44:13 -06001118static bool __init blogic_probe(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
Khalid Aziz839cb992013-05-16 19:44:13 -06001120 union blogic_stat_reg statusreg;
1121 union blogic_int_reg intreg;
1122 union blogic_geo_reg georeg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 /*
1124 FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
1125 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001126 if (blogic_flashpoint_type(adapter)) {
1127 struct fpoint_info *fpinfo = &adapter->fpinfo;
1128 fpinfo->base_addr = (u32) adapter->io_addr;
1129 fpinfo->irq_ch = adapter->irq_ch;
1130 fpinfo->present = false;
1131 if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
1132 fpinfo->present)) {
Colin Ian King43622692020-01-08 19:38:00 +00001133 blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
1134 blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
Khalid Aziz839cb992013-05-16 19:44:13 -06001135 blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 return false;
1137 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001138 if (blogic_global_options.trace_probe)
Colin Ian King43622692020-01-08 19:38:00 +00001139 blogic_notice("BusLogic_Probe(0x%lX): FlashPoint Found\n", adapter, adapter->io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 /*
1141 Indicate the Host Adapter Probe completed successfully.
1142 */
1143 return true;
1144 }
1145 /*
1146 Read the Status, Interrupt, and Geometry Registers to test if there are I/O
1147 ports that respond, and to check the values to determine if they are from a
1148 BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which
1149 case there is definitely no BusLogic Host Adapter at this base I/O Address.
1150 The test here is a subset of that used by the BusLogic Host Adapter BIOS.
1151 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001152 statusreg.all = blogic_rdstatus(adapter);
1153 intreg.all = blogic_rdint(adapter);
1154 georeg.all = blogic_rdgeom(adapter);
1155 if (blogic_global_options.trace_probe)
Colin Ian King43622692020-01-08 19:38:00 +00001156 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);
Khalid Aziz839cb992013-05-16 19:44:13 -06001157 if (statusreg.all == 0 || statusreg.sr.diag_active ||
1158 statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
1159 statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return false;
1161 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001162 Check the undocumented Geometry Register to test if there is
1163 an I/O port that responded. Adaptec Host Adapters do not
1164 implement the Geometry Register, so this test helps serve to
1165 avoid incorrectly recognizing an Adaptec 1542A or 1542B as a
1166 BusLogic. Unfortunately, the Adaptec 1542C series does respond
1167 to the Geometry Register I/O port, but it will be rejected
1168 later when the Inquire Extended Setup Information command is
1169 issued in blogic_checkadapter. The AMI FastDisk Host Adapter
1170 is a BusLogic clone that implements the same interface as
1171 earlier BusLogic Host Adapters, including the undocumented
1172 commands, and is therefore supported by this driver. However,
1173 the AMI FastDisk always returns 0x00 upon reading the Geometry
1174 Register, so the extended translation option should always be
1175 left disabled on the AMI FastDisk.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001177 if (georeg.all == 0xFF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 return false;
1179 /*
1180 Indicate the Host Adapter Probe completed successfully.
1181 */
1182 return true;
1183}
1184
1185
1186/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001187 blogic_hwreset issues a Hardware Reset to the Host Adapter
1188 and waits for Host Adapter Diagnostics to complete. If hard_reset is true, a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
1190 Soft Reset is performed which only resets the Host Adapter without forcing a
1191 SCSI Bus Reset.
1192*/
1193
Khalid Aziz839cb992013-05-16 19:44:13 -06001194static bool blogic_hwreset(struct blogic_adapter *adapter, bool hard_reset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
Khalid Aziz839cb992013-05-16 19:44:13 -06001196 union blogic_stat_reg statusreg;
1197 int timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001199 FlashPoint Host Adapters are Hard Reset by the FlashPoint
1200 SCCB Manager.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001202 if (blogic_flashpoint_type(adapter)) {
1203 struct fpoint_info *fpinfo = &adapter->fpinfo;
1204 fpinfo->softreset = !hard_reset;
1205 fpinfo->report_underrun = true;
1206 adapter->cardhandle =
1207 FlashPoint_HardwareResetHostAdapter(fpinfo);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001208 if (adapter->cardhandle == (void *)FPOINT_BADCARD_HANDLE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 return false;
1210 /*
1211 Indicate the Host Adapter Hard Reset completed successfully.
1212 */
1213 return true;
1214 }
1215 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001216 Issue a Hard Reset or Soft Reset Command to the Host Adapter.
1217 The Host Adapter should respond by setting Diagnostic Active in
1218 the Status Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001220 if (hard_reset)
1221 blogic_hardreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001223 blogic_softreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 /*
1225 Wait until Diagnostic Active is set in the Status Register.
1226 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001227 timeout = 5 * 10000;
1228 while (--timeout >= 0) {
1229 statusreg.all = blogic_rdstatus(adapter);
1230 if (statusreg.sr.diag_active)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 break;
1232 udelay(100);
1233 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001234 if (blogic_global_options.trace_hw_reset)
Colin Ian King43622692020-01-08 19:38:00 +00001235 blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Active, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
Khalid Aziz839cb992013-05-16 19:44:13 -06001236 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 return false;
1238 /*
1239 Wait 100 microseconds to allow completion of any initial diagnostic
1240 activity which might leave the contents of the Status Register
1241 unpredictable.
1242 */
1243 udelay(100);
1244 /*
1245 Wait until Diagnostic Active is reset in the Status Register.
1246 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001247 timeout = 10 * 10000;
1248 while (--timeout >= 0) {
1249 statusreg.all = blogic_rdstatus(adapter);
1250 if (!statusreg.sr.diag_active)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 break;
1252 udelay(100);
1253 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001254 if (blogic_global_options.trace_hw_reset)
Colin Ian King43622692020-01-08 19:38:00 +00001255 blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Completed, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
Khalid Aziz839cb992013-05-16 19:44:13 -06001256 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 return false;
1258 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001259 Wait until at least one of the Diagnostic Failure, Host Adapter
1260 Ready, or Data In Register Ready bits is set in the Status Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001262 timeout = 10000;
1263 while (--timeout >= 0) {
1264 statusreg.all = blogic_rdstatus(adapter);
1265 if (statusreg.sr.diag_failed || statusreg.sr.adapter_ready ||
1266 statusreg.sr.datain_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 break;
1268 udelay(100);
1269 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001270 if (blogic_global_options.trace_hw_reset)
Colin Ian King43622692020-01-08 19:38:00 +00001271 blogic_notice("BusLogic_HardwareReset(0x%lX): Host Adapter Ready, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
Khalid Aziz839cb992013-05-16 19:44:13 -06001272 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 return false;
1274 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001275 If Diagnostic Failure is set or Host Adapter Ready is reset,
1276 then an error occurred during the Host Adapter diagnostics.
1277 If Data In Register Ready is set, then there is an Error Code
1278 available.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001280 if (statusreg.sr.diag_failed || !statusreg.sr.adapter_ready) {
1281 blogic_cmd_failure_reason = NULL;
1282 blogic_failure(adapter, "HARD RESET DIAGNOSTICS");
1283 blogic_err("HOST ADAPTER STATUS REGISTER = %02X\n", adapter,
1284 statusreg.all);
1285 if (statusreg.sr.datain_ready)
1286 blogic_err("HOST ADAPTER ERROR CODE = %d\n", adapter,
1287 blogic_rddatain(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 return false;
1289 }
1290 /*
1291 Indicate the Host Adapter Hard Reset completed successfully.
1292 */
1293 return true;
1294}
1295
1296
1297/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001298 blogic_checkadapter checks to be sure this really is a BusLogic
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 Host Adapter.
1300*/
1301
Khalid Aziz839cb992013-05-16 19:44:13 -06001302static bool __init blogic_checkadapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303{
Khalid Aziz839cb992013-05-16 19:44:13 -06001304 struct blogic_ext_setup ext_setupinfo;
1305 unsigned char req_replylen;
1306 bool result = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 /*
1308 FlashPoint Host Adapters do not require this protection.
1309 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001310 if (blogic_flashpoint_type(adapter))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 return true;
1312 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001313 Issue the Inquire Extended Setup Information command. Only genuine
1314 BusLogic Host Adapters and true clones support this command.
1315 Adaptec 1542C series Host Adapters that respond to the Geometry
1316 Register I/O port will fail this command.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001318 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 result = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 /*
1324 Provide tracing information if requested and return.
1325 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001326 if (blogic_global_options.trace_probe)
Colin Ian King43622692020-01-08 19:38:00 +00001327 blogic_notice("BusLogic_Check(0x%lX): MultiMaster %s\n", adapter,
Khalid Aziz839cb992013-05-16 19:44:13 -06001328 adapter->io_addr,
1329 (result ? "Found" : "Not Found"));
1330 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
1333
1334/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001335 blogic_rdconfig reads the Configuration Information
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 from Host Adapter and initializes the Host Adapter structure.
1337*/
1338
Khalid Aziz839cb992013-05-16 19:44:13 -06001339static bool __init blogic_rdconfig(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Khalid Aziz839cb992013-05-16 19:44:13 -06001341 struct blogic_board_id id;
1342 struct blogic_config config;
1343 struct blogic_setup_info setupinfo;
1344 struct blogic_ext_setup ext_setupinfo;
1345 unsigned char model[5];
1346 unsigned char fw_ver_digit3;
1347 unsigned char fw_ver_letter;
1348 struct blogic_adapter_info adapter_info;
1349 struct blogic_fetch_localram fetch_localram;
1350 struct blogic_autoscsi autoscsi;
1351 union blogic_geo_reg georeg;
1352 unsigned char req_replylen;
1353 unsigned char *tgt, ch;
1354 int tgt_id, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001356 Configuration Information for FlashPoint Host Adapters is
1357 provided in the fpoint_info structure by the FlashPoint
1358 SCCB Manager's Probe Function. Initialize fields in the
1359 Host Adapter structure from the fpoint_info structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001361 if (blogic_flashpoint_type(adapter)) {
1362 struct fpoint_info *fpinfo = &adapter->fpinfo;
1363 tgt = adapter->model;
1364 *tgt++ = 'B';
1365 *tgt++ = 'T';
1366 *tgt++ = '-';
1367 for (i = 0; i < sizeof(fpinfo->model); i++)
1368 *tgt++ = fpinfo->model[i];
1369 *tgt++ = '\0';
1370 strcpy(adapter->fw_ver, FLASHPOINT_FW_VER);
1371 adapter->scsi_id = fpinfo->scsi_id;
1372 adapter->ext_trans_enable = fpinfo->ext_trans_enable;
1373 adapter->parity = fpinfo->parity;
1374 adapter->reset_enabled = !fpinfo->softreset;
1375 adapter->level_int = true;
1376 adapter->wide = fpinfo->wide;
1377 adapter->differential = false;
1378 adapter->scam = true;
1379 adapter->ultra = true;
1380 adapter->ext_lun = true;
1381 adapter->terminfo_valid = true;
1382 adapter->low_term = fpinfo->low_term;
1383 adapter->high_term = fpinfo->high_term;
1384 adapter->scam_enabled = fpinfo->scam_enabled;
1385 adapter->scam_lev2 = fpinfo->scam_lev2;
1386 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1387 adapter->maxdev = (adapter->wide ? 16 : 8);
1388 adapter->maxlun = 32;
1389 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1390 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1391 adapter->drvr_qdepth = 255;
1392 adapter->adapter_qdepth = adapter->drvr_qdepth;
1393 adapter->sync_ok = fpinfo->sync_ok;
1394 adapter->fast_ok = fpinfo->fast_ok;
1395 adapter->ultra_ok = fpinfo->ultra_ok;
1396 adapter->wide_ok = fpinfo->wide_ok;
1397 adapter->discon_ok = fpinfo->discon_ok;
1398 adapter->tagq_ok = 0xFFFF;
1399 goto common;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 }
1401 /*
1402 Issue the Inquire Board ID command.
1403 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001404 if (blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
1405 sizeof(id)) != sizeof(id))
1406 return blogic_failure(adapter, "INQUIRE BOARD ID");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 /*
1408 Issue the Inquire Configuration command.
1409 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001410 if (blogic_cmd(adapter, BLOGIC_INQ_CONFIG, NULL, 0, &config,
1411 sizeof(config))
1412 != sizeof(config))
1413 return blogic_failure(adapter, "INQUIRE CONFIGURATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 /*
1415 Issue the Inquire Setup Information command.
1416 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001417 req_replylen = sizeof(setupinfo);
1418 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
1419 sizeof(req_replylen), &setupinfo,
1420 sizeof(setupinfo)) != sizeof(setupinfo))
1421 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 /*
1423 Issue the Inquire Extended Setup Information command.
1424 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001425 req_replylen = sizeof(ext_setupinfo);
1426 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1427 sizeof(req_replylen), &ext_setupinfo,
1428 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1429 return blogic_failure(adapter,
1430 "INQUIRE EXTENDED SETUP INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 /*
1432 Issue the Inquire Firmware Version 3rd Digit command.
1433 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001434 fw_ver_digit3 = '\0';
1435 if (id.fw_ver_digit1 > '0')
1436 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_D3, NULL, 0,
1437 &fw_ver_digit3,
1438 sizeof(fw_ver_digit3)) != sizeof(fw_ver_digit3))
1439 return blogic_failure(adapter,
1440 "INQUIRE FIRMWARE 3RD DIGIT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 /*
1442 Issue the Inquire Host Adapter Model Number command.
1443 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001444 if (ext_setupinfo.bus_type == 'A' && id.fw_ver_digit1 == '2')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 /* BusLogic BT-542B ISA 2.xx */
Khalid Aziz839cb992013-05-16 19:44:13 -06001446 strcpy(model, "542B");
1447 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '2' &&
1448 (id.fw_ver_digit2 <= '1' || (id.fw_ver_digit2 == '2' &&
1449 fw_ver_digit3 == '0')))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 /* BusLogic BT-742A EISA 2.1x or 2.20 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001451 strcpy(model, "742A");
1452 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 /* AMI FastDisk EISA Series 441 0.x */
Khalid Aziz839cb992013-05-16 19:44:13 -06001454 strcpy(model, "747A");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001456 req_replylen = sizeof(model);
1457 if (blogic_cmd(adapter, BLOGIC_INQ_MODELNO, &req_replylen,
1458 sizeof(req_replylen), &model,
1459 sizeof(model)) != sizeof(model))
1460 return blogic_failure(adapter,
1461 "INQUIRE HOST ADAPTER MODEL NUMBER");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 }
1463 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001464 BusLogic MultiMaster Host Adapters can be identified by their
1465 model number and the major version number of their firmware
1466 as follows:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
1468 5.xx BusLogic "W" Series Host Adapters:
1469 BT-948/958/958D
1470 4.xx BusLogic "C" Series Host Adapters:
1471 BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1472 3.xx BusLogic "S" Series Host Adapters:
1473 BT-747S/747D/757S/757D/445S/545S/542D
1474 BT-542B/742A (revision H)
1475 2.xx BusLogic "A" Series Host Adapters:
1476 BT-542B/742A (revision G and below)
1477 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1478 */
1479 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001480 Save the Model Name and Host Adapter Name in the Host Adapter
1481 structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001483 tgt = adapter->model;
1484 *tgt++ = 'B';
1485 *tgt++ = 'T';
1486 *tgt++ = '-';
1487 for (i = 0; i < sizeof(model); i++) {
1488 ch = model[i];
1489 if (ch == ' ' || ch == '\0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06001491 *tgt++ = ch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001493 *tgt++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 /*
1495 Save the Firmware Version in the Host Adapter structure.
1496 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001497 tgt = adapter->fw_ver;
1498 *tgt++ = id.fw_ver_digit1;
1499 *tgt++ = '.';
1500 *tgt++ = id.fw_ver_digit2;
1501 if (fw_ver_digit3 != ' ' && fw_ver_digit3 != '\0')
1502 *tgt++ = fw_ver_digit3;
1503 *tgt = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 /*
1505 Issue the Inquire Firmware Version Letter command.
1506 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001507 if (strcmp(adapter->fw_ver, "3.3") >= 0) {
1508 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_LETTER, NULL, 0,
1509 &fw_ver_letter,
1510 sizeof(fw_ver_letter)) != sizeof(fw_ver_letter))
1511 return blogic_failure(adapter,
1512 "INQUIRE FIRMWARE VERSION LETTER");
1513 if (fw_ver_letter != ' ' && fw_ver_letter != '\0')
1514 *tgt++ = fw_ver_letter;
1515 *tgt = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 }
1517 /*
1518 Save the Host Adapter SCSI ID in the Host Adapter structure.
1519 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001520 adapter->scsi_id = config.id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001522 Determine the Bus Type and save it in the Host Adapter structure,
1523 determine and save the IRQ Channel if necessary, and determine
1524 and save the DMA Channel for ISA Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001526 adapter->adapter_bus_type =
1527 blogic_adater_bus_types[adapter->model[3] - '4'];
1528 if (adapter->irq_ch == 0) {
1529 if (config.irq_ch9)
1530 adapter->irq_ch = 9;
1531 else if (config.irq_ch10)
1532 adapter->irq_ch = 10;
1533 else if (config.irq_ch11)
1534 adapter->irq_ch = 11;
1535 else if (config.irq_ch12)
1536 adapter->irq_ch = 12;
1537 else if (config.irq_ch14)
1538 adapter->irq_ch = 14;
1539 else if (config.irq_ch15)
1540 adapter->irq_ch = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001542 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS) {
1543 if (config.dma_ch5)
1544 adapter->dma_ch = 5;
1545 else if (config.dma_ch6)
1546 adapter->dma_ch = 6;
1547 else if (config.dma_ch7)
1548 adapter->dma_ch = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 }
1550 /*
1551 Determine whether Extended Translation is enabled and save it in
1552 the Host Adapter structure.
1553 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001554 georeg.all = blogic_rdgeom(adapter);
1555 adapter->ext_trans_enable = georeg.gr.ext_trans_enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 /*
1557 Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1558 SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1559 Ultra SCSI flag in the Host Adapter structure.
1560 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001561 adapter->adapter_sglimit = ext_setupinfo.sg_limit;
1562 adapter->drvr_sglimit = adapter->adapter_sglimit;
1563 if (adapter->adapter_sglimit > BLOGIC_SG_LIMIT)
1564 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1565 if (ext_setupinfo.misc.level_int)
1566 adapter->level_int = true;
1567 adapter->wide = ext_setupinfo.wide;
1568 adapter->differential = ext_setupinfo.differential;
1569 adapter->scam = ext_setupinfo.scam;
1570 adapter->ultra = ext_setupinfo.ultra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 /*
1572 Determine whether Extended LUN Format CCBs are supported and save the
1573 information in the Host Adapter structure.
1574 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001575 if (adapter->fw_ver[0] == '5' || (adapter->fw_ver[0] == '4' &&
1576 adapter->wide))
1577 adapter->ext_lun = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 /*
1579 Issue the Inquire PCI Host Adapter Information command to read the
1580 Termination Information from "W" series MultiMaster Host Adapters.
1581 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001582 if (adapter->fw_ver[0] == '5') {
1583 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
1584 &adapter_info,
1585 sizeof(adapter_info)) != sizeof(adapter_info))
1586 return blogic_failure(adapter,
1587 "INQUIRE PCI HOST ADAPTER INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001589 Save the Termination Information in the Host Adapter
1590 structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001592 if (adapter_info.genericinfo_valid) {
1593 adapter->terminfo_valid = true;
1594 adapter->low_term = adapter_info.low_term;
1595 adapter->high_term = adapter_info.high_term;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 }
1597 }
1598 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001599 Issue the Fetch Host Adapter Local RAM command to read the
1600 AutoSCSI data from "W" and "C" series MultiMaster Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001602 if (adapter->fw_ver[0] >= '4') {
1603 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE;
1604 fetch_localram.count = sizeof(autoscsi);
1605 if (blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, &fetch_localram,
1606 sizeof(fetch_localram), &autoscsi,
1607 sizeof(autoscsi)) != sizeof(autoscsi))
1608 return blogic_failure(adapter,
1609 "FETCH HOST ADAPTER LOCAL RAM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001611 Save the Parity Checking Enabled, Bus Reset Enabled,
1612 and Termination Information in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001614 adapter->parity = autoscsi.parity;
1615 adapter->reset_enabled = autoscsi.reset_enabled;
1616 if (adapter->fw_ver[0] == '4') {
1617 adapter->terminfo_valid = true;
1618 adapter->low_term = autoscsi.low_term;
1619 adapter->high_term = autoscsi.high_term;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
1621 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001622 Save the Wide Permitted, Fast Permitted, Synchronous
1623 Permitted, Disconnect Permitted, Ultra Permitted, and
1624 SCAM Information in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001626 adapter->wide_ok = autoscsi.wide_ok;
1627 adapter->fast_ok = autoscsi.fast_ok;
1628 adapter->sync_ok = autoscsi.sync_ok;
1629 adapter->discon_ok = autoscsi.discon_ok;
1630 if (adapter->ultra)
1631 adapter->ultra_ok = autoscsi.ultra_ok;
1632 if (adapter->scam) {
1633 adapter->scam_enabled = autoscsi.scam_enabled;
1634 adapter->scam_lev2 = autoscsi.scam_lev2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 }
1636 }
1637 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001638 Initialize fields in the Host Adapter structure for "S" and "A"
1639 series MultiMaster Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001641 if (adapter->fw_ver[0] < '4') {
1642 if (setupinfo.sync) {
1643 adapter->sync_ok = 0xFF;
1644 if (adapter->adapter_bus_type == BLOGIC_EISA_BUS) {
1645 if (ext_setupinfo.misc.fast_on_eisa)
1646 adapter->fast_ok = 0xFF;
1647 if (strcmp(adapter->model, "BT-757") == 0)
1648 adapter->wide_ok = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 }
1650 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001651 adapter->discon_ok = 0xFF;
1652 adapter->parity = setupinfo.parity;
1653 adapter->reset_enabled = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 }
1655 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001656 Determine the maximum number of Target IDs and Logical Units
1657 supported by this driver for Wide and Narrow Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001659 adapter->maxdev = (adapter->wide ? 16 : 8);
1660 adapter->maxlun = (adapter->ext_lun ? 32 : 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 /*
1662 Select appropriate values for the Mailbox Count, Driver Queue Depth,
Khalid Aziz839cb992013-05-16 19:44:13 -06001663 Initial CCBs, and Incremental CCBs variables based on whether
1664 or not Strict Round Robin Mode is supported. If Strict Round
1665 Robin Mode is supported, then there is no performance degradation
1666 in using the maximum possible number of Outgoing and Incoming
1667 Mailboxes and allowing the Tagged and Untagged Queue Depths to
1668 determine the actual utilization. If Strict Round Robin Mode is
1669 not supported, then the Host Adapter must scan all the Outgoing
1670 Mailboxes whenever an Outgoing Mailbox entry is made, which can
1671 cause a substantial performance penalty. The host adapters
1672 actually have room to store the following number of CCBs
1673 internally; that is, they can internally queue and manage this
1674 many active commands on the SCSI bus simultaneously. Performance
1675 measurements demonstrate that the Driver Queue Depth should be
1676 set to the Mailbox Count, rather than the Host Adapter Queue
1677 Depth (internal CCB capacity), as it is more efficient to have the
1678 queued commands waiting in Outgoing Mailboxes if necessary than
1679 to block the process in the higher levels of the SCSI Subsystem.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 192 BT-948/958/958D
1682 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1683 50 BT-545C/540CF
1684 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1685 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001686 if (adapter->fw_ver[0] == '5')
1687 adapter->adapter_qdepth = 192;
1688 else if (adapter->fw_ver[0] == '4')
1689 adapter->adapter_qdepth = (adapter->adapter_bus_type !=
1690 BLOGIC_ISA_BUS ? 100 : 50);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001692 adapter->adapter_qdepth = 30;
1693 if (strcmp(adapter->fw_ver, "3.31") >= 0) {
1694 adapter->strict_rr = true;
1695 adapter->mbox_count = BLOGIC_MAX_MAILBOX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001697 adapter->strict_rr = false;
1698 adapter->mbox_count = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001700 adapter->drvr_qdepth = adapter->mbox_count;
1701 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1702 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001704 Tagged Queuing support is available and operates properly on
1705 all "W" series MultiMaster Host Adapters, on "C" series
1706 MultiMaster Host Adapters with firmware version 4.22 and above,
1707 and on "S" series MultiMaster Host Adapters with firmware version
1708 3.35 and above.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001710 adapter->tagq_ok = 0;
1711 switch (adapter->fw_ver[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 case '5':
Khalid Aziz839cb992013-05-16 19:44:13 -06001713 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 break;
1715 case '4':
Khalid Aziz839cb992013-05-16 19:44:13 -06001716 if (strcmp(adapter->fw_ver, "4.22") >= 0)
1717 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 break;
1719 case '3':
Khalid Aziz839cb992013-05-16 19:44:13 -06001720 if (strcmp(adapter->fw_ver, "3.35") >= 0)
1721 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 break;
1723 }
1724 /*
1725 Determine the Host Adapter BIOS Address if the BIOS is enabled and
1726 save it in the Host Adapter structure. The BIOS is disabled if the
Khalid Aziz839cb992013-05-16 19:44:13 -06001727 bios_addr is 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001729 adapter->bios_addr = ext_setupinfo.bios_addr << 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001731 ISA Host Adapters require Bounce Buffers if there is more than
1732 16MB memory.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001734 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS &&
1735 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1736 adapter->need_bouncebuf = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001738 BusLogic BT-445S Host Adapters prior to board revision E have a
1739 hardware bug whereby when the BIOS is enabled, transfers to/from
1740 the same address range the BIOS occupies modulo 16MB are handled
1741 incorrectly. Only properly functioning BT-445S Host Adapters
1742 have firmware version 3.37, so require that ISA Bounce Buffers
1743 be used for the buggy BT-445S models if there is more than 16MB
1744 memory.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001746 if (adapter->bios_addr > 0 && strcmp(adapter->model, "BT-445S") == 0 &&
1747 strcmp(adapter->fw_ver, "3.37") < 0 &&
1748 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1749 adapter->need_bouncebuf = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001751 Initialize parameters common to MultiMaster and FlashPoint
1752 Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001754common:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 /*
1756 Initialize the Host Adapter Full Model Name from the Model Name.
1757 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001758 strcpy(adapter->full_model, "BusLogic ");
1759 strcat(adapter->full_model, adapter->model);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 /*
1761 Select an appropriate value for the Tagged Queue Depth either from a
1762 BusLogic Driver Options specification, or based on whether this Host
Khalid Aziz839cb992013-05-16 19:44:13 -06001763 Adapter requires that ISA Bounce Buffers be used. The Tagged Queue
1764 Depth is left at 0 for automatic determination in
1765 BusLogic_SelectQueueDepths. Initialize the Untagged Queue Depth.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001767 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
1768 unsigned char qdepth = 0;
1769 if (adapter->drvr_opts != NULL &&
1770 adapter->drvr_opts->qdepth[tgt_id] > 0)
1771 qdepth = adapter->drvr_opts->qdepth[tgt_id];
1772 else if (adapter->need_bouncebuf)
1773 qdepth = BLOGIC_TAG_DEPTH_BB;
1774 adapter->qdepth[tgt_id] = qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001776 if (adapter->need_bouncebuf)
1777 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH_BB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001779 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH;
1780 if (adapter->drvr_opts != NULL)
1781 adapter->common_qdepth = adapter->drvr_opts->common_qdepth;
1782 if (adapter->common_qdepth > 0 &&
1783 adapter->common_qdepth < adapter->untag_qdepth)
1784 adapter->untag_qdepth = adapter->common_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 /*
1786 Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1787 Therefore, mask the Tagged Queuing Permitted Default bits with the
1788 Disconnect/Reconnect Permitted bits.
1789 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001790 adapter->tagq_ok &= adapter->discon_ok;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001792 Combine the default Tagged Queuing Permitted bits with any
1793 BusLogic Driver Options Tagged Queuing specification.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001795 if (adapter->drvr_opts != NULL)
1796 adapter->tagq_ok = (adapter->drvr_opts->tagq_ok &
1797 adapter->drvr_opts->tagq_ok_mask) |
1798 (adapter->tagq_ok & ~adapter->drvr_opts->tagq_ok_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
1800 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001801 Select an appropriate value for Bus Settle Time either from a
1802 BusLogic Driver Options specification, or from
1803 BLOGIC_BUS_SETTLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001805 if (adapter->drvr_opts != NULL &&
1806 adapter->drvr_opts->bus_settle_time > 0)
1807 adapter->bus_settle_time = adapter->drvr_opts->bus_settle_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001809 adapter->bus_settle_time = BLOGIC_BUS_SETTLE_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001811 Indicate reading the Host Adapter Configuration completed
1812 successfully.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 */
1814 return true;
1815}
1816
1817
1818/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001819 blogic_reportconfig reports the configuration of Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820*/
1821
Khalid Aziz839cb992013-05-16 19:44:13 -06001822static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
Khalid Aziz839cb992013-05-16 19:44:13 -06001824 unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
1825 unsigned short sync_ok, fast_ok;
1826 unsigned short ultra_ok, wide_ok;
1827 unsigned short discon_ok, tagq_ok;
1828 bool common_syncneg, common_tagq_depth;
1829 char syncstr[BLOGIC_MAXDEV + 1];
1830 char widestr[BLOGIC_MAXDEV + 1];
1831 char discon_str[BLOGIC_MAXDEV + 1];
1832 char tagq_str[BLOGIC_MAXDEV + 1];
1833 char *syncmsg = syncstr;
1834 char *widemsg = widestr;
1835 char *discon_msg = discon_str;
1836 char *tagq_msg = tagq_str;
1837 int tgt_id;
1838
1839 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" : ""));
Colin Ian King43622692020-01-08 19:38:00 +00001840 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"));
Khalid Aziz839cb992013-05-16 19:44:13 -06001841 if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
1842 blogic_info(" DMA Channel: ", adapter);
1843 if (adapter->dma_ch > 0)
1844 blogic_info("%d, ", adapter, adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001846 blogic_info("None, ", adapter);
1847 if (adapter->bios_addr > 0)
Colin Ian King59137b72021-07-30 10:50:31 +01001848 blogic_info("BIOS Address: 0x%X, ", adapter,
Khalid Aziz839cb992013-05-16 19:44:13 -06001849 adapter->bios_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001851 blogic_info("BIOS Address: None, ", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001853 blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
1854 adapter->bus, adapter->dev);
1855 if (adapter->pci_addr > 0)
Colin Ian King43622692020-01-08 19:38:00 +00001856 blogic_info("0x%lX, ", adapter, adapter->pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001858 blogic_info("Unassigned, ", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001860 blogic_info("Host Adapter SCSI ID: %d\n", adapter, adapter->scsi_id);
1861 blogic_info(" Parity Checking: %s, Extended Translation: %s\n",
1862 adapter, (adapter->parity ? "Enabled" : "Disabled"),
1863 (adapter->ext_trans_enable ? "Enabled" : "Disabled"));
1864 alltgt_mask &= ~(1 << adapter->scsi_id);
1865 sync_ok = adapter->sync_ok & alltgt_mask;
1866 fast_ok = adapter->fast_ok & alltgt_mask;
1867 ultra_ok = adapter->ultra_ok & alltgt_mask;
1868 if ((blogic_multimaster_type(adapter) &&
1869 (adapter->fw_ver[0] >= '4' ||
1870 adapter->adapter_bus_type == BLOGIC_EISA_BUS)) ||
1871 blogic_flashpoint_type(adapter)) {
1872 common_syncneg = false;
1873 if (sync_ok == 0) {
1874 syncmsg = "Disabled";
1875 common_syncneg = true;
1876 } else if (sync_ok == alltgt_mask) {
1877 if (fast_ok == 0) {
1878 syncmsg = "Slow";
1879 common_syncneg = true;
1880 } else if (fast_ok == alltgt_mask) {
1881 if (ultra_ok == 0) {
1882 syncmsg = "Fast";
1883 common_syncneg = true;
1884 } else if (ultra_ok == alltgt_mask) {
1885 syncmsg = "Ultra";
1886 common_syncneg = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 }
1888 }
1889 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001890 if (!common_syncneg) {
1891 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1892 syncstr[tgt_id] = ((!(sync_ok & (1 << tgt_id))) ? 'N' : (!(fast_ok & (1 << tgt_id)) ? 'S' : (!(ultra_ok & (1 << tgt_id)) ? 'F' : 'U')));
1893 syncstr[adapter->scsi_id] = '#';
1894 syncstr[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 }
1896 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001897 syncmsg = (sync_ok == 0 ? "Disabled" : "Enabled");
1898 wide_ok = adapter->wide_ok & alltgt_mask;
1899 if (wide_ok == 0)
1900 widemsg = "Disabled";
1901 else if (wide_ok == alltgt_mask)
1902 widemsg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001904 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1905 widestr[tgt_id] = ((wide_ok & (1 << tgt_id)) ? 'Y' : 'N');
1906 widestr[adapter->scsi_id] = '#';
1907 widestr[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001909 discon_ok = adapter->discon_ok & alltgt_mask;
1910 if (discon_ok == 0)
1911 discon_msg = "Disabled";
1912 else if (discon_ok == alltgt_mask)
1913 discon_msg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001915 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1916 discon_str[tgt_id] = ((discon_ok & (1 << tgt_id)) ? 'Y' : 'N');
1917 discon_str[adapter->scsi_id] = '#';
1918 discon_str[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001920 tagq_ok = adapter->tagq_ok & alltgt_mask;
1921 if (tagq_ok == 0)
1922 tagq_msg = "Disabled";
1923 else if (tagq_ok == alltgt_mask)
1924 tagq_msg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001926 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1927 tagq_str[tgt_id] = ((tagq_ok & (1 << tgt_id)) ? 'Y' : 'N');
1928 tagq_str[adapter->scsi_id] = '#';
1929 tagq_str[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001931 blogic_info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
1932 adapter, syncmsg, widemsg);
1933 blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
1934 discon_msg, tagq_msg);
1935 if (blogic_multimaster_type(adapter)) {
Colin Ian King43622692020-01-08 19:38:00 +00001936 blogic_info(" Scatter/Gather Limit: %d of %d segments, Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
1937 blogic_info(" Driver Queue Depth: %d, Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 } else
Colin Ian King43622692020-01-08 19:38:00 +00001939 blogic_info(" Driver Queue Depth: %d, Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
Khalid Aziz839cb992013-05-16 19:44:13 -06001940 blogic_info(" Tagged Queue Depth: ", adapter);
1941 common_tagq_depth = true;
1942 for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
1943 if (adapter->qdepth[tgt_id] != adapter->qdepth[0]) {
1944 common_tagq_depth = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 break;
1946 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001947 if (common_tagq_depth) {
1948 if (adapter->qdepth[0] > 0)
1949 blogic_info("%d", adapter, adapter->qdepth[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001951 blogic_info("Automatic", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001953 blogic_info("Individual", adapter);
1954 blogic_info(", Untagged Queue Depth: %d\n", adapter,
1955 adapter->untag_qdepth);
1956 if (adapter->terminfo_valid) {
1957 if (adapter->wide)
1958 blogic_info(" SCSI Bus Termination: %s", adapter,
1959 (adapter->low_term ? (adapter->high_term ? "Both Enabled" : "Low Enabled") : (adapter->high_term ? "High Enabled" : "Both Disabled")));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001961 blogic_info(" SCSI Bus Termination: %s", adapter,
1962 (adapter->low_term ? "Enabled" : "Disabled"));
1963 if (adapter->scam)
1964 blogic_info(", SCAM: %s", adapter,
1965 (adapter->scam_enabled ? (adapter->scam_lev2 ? "Enabled, Level 2" : "Enabled, Level 1") : "Disabled"));
1966 blogic_info("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 }
1968 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001969 Indicate reporting the Host Adapter configuration completed
1970 successfully.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 */
1972 return true;
1973}
1974
1975
1976/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001977 blogic_getres acquires the system resources necessary to use
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 Host Adapter.
1979*/
1980
Khalid Aziz839cb992013-05-16 19:44:13 -06001981static bool __init blogic_getres(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982{
Khalid Aziz839cb992013-05-16 19:44:13 -06001983 if (adapter->irq_ch == 0) {
1984 blogic_err("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
1985 adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 return false;
1987 }
1988 /*
1989 Acquire shared access to the IRQ Channel.
1990 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001991 if (request_irq(adapter->irq_ch, blogic_inthandler, IRQF_SHARED,
1992 adapter->full_model, adapter) < 0) {
1993 blogic_err("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
1994 adapter, adapter->irq_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 return false;
1996 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001997 adapter->irq_acquired = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 /*
1999 Acquire exclusive access to the DMA Channel.
2000 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002001 if (adapter->dma_ch > 0) {
2002 if (request_dma(adapter->dma_ch, adapter->full_model) < 0) {
2003 blogic_err("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", adapter, adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 return false;
2005 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002006 set_dma_mode(adapter->dma_ch, DMA_MODE_CASCADE);
2007 enable_dma(adapter->dma_ch);
2008 adapter->dma_chan_acquired = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 }
2010 /*
2011 Indicate the System Resource Acquisition completed successfully,
2012 */
2013 return true;
2014}
2015
2016
2017/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002018 blogic_relres releases any system resources previously acquired
2019 by blogic_getres.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020*/
2021
Khalid Aziz839cb992013-05-16 19:44:13 -06002022static void blogic_relres(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
2024 /*
2025 Release shared access to the IRQ Channel.
2026 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002027 if (adapter->irq_acquired)
2028 free_irq(adapter->irq_ch, adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 /*
2030 Release exclusive access to the DMA Channel.
2031 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002032 if (adapter->dma_chan_acquired)
2033 free_dma(adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 /*
2035 Release any allocated memory structs not released elsewhere
2036 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002037 if (adapter->mbox_space)
Christoph Hellwig17a361b2018-10-10 18:03:24 +02002038 dma_free_coherent(&adapter->pci_device->dev, adapter->mbox_sz,
Khalid Aziz839cb992013-05-16 19:44:13 -06002039 adapter->mbox_space, adapter->mbox_space_handle);
2040 pci_dev_put(adapter->pci_device);
2041 adapter->mbox_space = NULL;
2042 adapter->mbox_space_handle = 0;
2043 adapter->mbox_sz = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
2046
2047/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002048 blogic_initadapter initializes Host Adapter. This is the only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 function called during SCSI Host Adapter detection which modifies the state
2050 of the Host Adapter from its initial power on or hard reset state.
2051*/
2052
Khalid Aziz839cb992013-05-16 19:44:13 -06002053static bool blogic_initadapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054{
Khalid Aziz839cb992013-05-16 19:44:13 -06002055 struct blogic_extmbox_req extmbox_req;
2056 enum blogic_rr_req rr_req;
2057 enum blogic_setccb_fmt setccb_fmt;
2058 int tgt_id;
2059
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002061 Initialize the pointers to the first and last CCBs that are
2062 queued for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002064 adapter->firstccb = NULL;
2065 adapter->lastccb = NULL;
2066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 /*
2068 Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
2069 Command Successful Flag, Active Commands, and Commands Since Reset
2070 for each Target Device.
2071 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002072 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
2073 adapter->bdr_pend[tgt_id] = NULL;
2074 adapter->tgt_flags[tgt_id].tagq_active = false;
2075 adapter->tgt_flags[tgt_id].cmd_good = false;
2076 adapter->active_cmds[tgt_id] = 0;
2077 adapter->cmds_since_rst[tgt_id] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002079
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 /*
2081 FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
2082 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002083 if (blogic_flashpoint_type(adapter))
2084 goto done;
2085
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 /*
2087 Initialize the Outgoing and Incoming Mailbox pointers.
2088 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002089 adapter->mbox_sz = adapter->mbox_count * (sizeof(struct blogic_outbox) + sizeof(struct blogic_inbox));
Christoph Hellwig17a361b2018-10-10 18:03:24 +02002090 adapter->mbox_space = dma_alloc_coherent(&adapter->pci_device->dev,
2091 adapter->mbox_sz, &adapter->mbox_space_handle,
2092 GFP_KERNEL);
Khalid Aziz839cb992013-05-16 19:44:13 -06002093 if (adapter->mbox_space == NULL)
2094 return blogic_failure(adapter, "MAILBOX ALLOCATION");
2095 adapter->first_outbox = (struct blogic_outbox *) adapter->mbox_space;
2096 adapter->last_outbox = adapter->first_outbox + adapter->mbox_count - 1;
2097 adapter->next_outbox = adapter->first_outbox;
2098 adapter->first_inbox = (struct blogic_inbox *) (adapter->last_outbox + 1);
2099 adapter->last_inbox = adapter->first_inbox + adapter->mbox_count - 1;
2100 adapter->next_inbox = adapter->first_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
2102 /*
2103 Initialize the Outgoing and Incoming Mailbox structures.
2104 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002105 memset(adapter->first_outbox, 0,
2106 adapter->mbox_count * sizeof(struct blogic_outbox));
2107 memset(adapter->first_inbox, 0,
2108 adapter->mbox_count * sizeof(struct blogic_inbox));
2109
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002111 Initialize the Host Adapter's Pointer to the Outgoing/Incoming
2112 Mailboxes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002114 extmbox_req.mbox_count = adapter->mbox_count;
2115 extmbox_req.base_mbox_addr = (u32) adapter->mbox_space_handle;
2116 if (blogic_cmd(adapter, BLOGIC_INIT_EXT_MBOX, &extmbox_req,
2117 sizeof(extmbox_req), NULL, 0) < 0)
2118 return blogic_failure(adapter, "MAILBOX INITIALIZATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002120 Enable Strict Round Robin Mode if supported by the Host Adapter. In
2121 Strict Round Robin Mode, the Host Adapter only looks at the next
2122 Outgoing Mailbox for each new command, rather than scanning
2123 through all the Outgoing Mailboxes to find any that have new
2124 commands in them. Strict Round Robin Mode is significantly more
2125 efficient.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002127 if (adapter->strict_rr) {
2128 rr_req = BLOGIC_STRICT_RR_MODE;
2129 if (blogic_cmd(adapter, BLOGIC_STRICT_RR, &rr_req,
2130 sizeof(rr_req), NULL, 0) < 0)
2131 return blogic_failure(adapter,
2132 "ENABLE STRICT ROUND ROBIN MODE");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002134
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002136 For Host Adapters that support Extended LUN Format CCBs, issue the
2137 Set CCB Format command to allow 32 Logical Units per Target Device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002139 if (adapter->ext_lun) {
2140 setccb_fmt = BLOGIC_EXT_LUN_CCB;
2141 if (blogic_cmd(adapter, BLOGIC_SETCCB_FMT, &setccb_fmt,
2142 sizeof(setccb_fmt), NULL, 0) < 0)
2143 return blogic_failure(adapter, "SET CCB FORMAT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002145
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 /*
2147 Announce Successful Initialization.
2148 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002149done:
2150 if (!adapter->adapter_initd) {
2151 blogic_info("*** %s Initialized Successfully ***\n", adapter,
2152 adapter->full_model);
2153 blogic_info("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06002155 blogic_warn("*** %s Initialized Successfully ***\n", adapter,
2156 adapter->full_model);
2157 adapter->adapter_initd = true;
2158
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 /*
2160 Indicate the Host Adapter Initialization completed successfully.
2161 */
2162 return true;
2163}
2164
2165
2166/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002167 blogic_inquiry inquires about the Target Devices accessible
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 through Host Adapter.
2169*/
2170
Khalid Aziz839cb992013-05-16 19:44:13 -06002171static bool __init blogic_inquiry(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172{
Khalid Aziz839cb992013-05-16 19:44:13 -06002173 u16 installed_devs;
2174 u8 installed_devs0to7[8];
2175 struct blogic_setup_info setupinfo;
2176 u8 sync_period[BLOGIC_MAXDEV];
2177 unsigned char req_replylen;
2178 int tgt_id;
2179
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002181 Wait a few seconds between the Host Adapter Hard Reset which
2182 initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
2183 SCSI devices get confused if they receive SCSI Commands too soon
2184 after a SCSI Bus Reset.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002186 blogic_delay(adapter->bus_settle_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 /*
2188 FlashPoint Host Adapters do not provide for Target Device Inquiry.
2189 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002190 if (blogic_flashpoint_type(adapter))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 return true;
2192 /*
2193 Inhibit the Target Device Inquiry if requested.
2194 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002195 if (adapter->drvr_opts != NULL && adapter->drvr_opts->stop_tgt_inquiry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 return true;
2197 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002198 Issue the Inquire Target Devices command for host adapters with
2199 firmware version 4.25 or later, or the Inquire Installed Devices
2200 ID 0 to 7 command for older host adapters. This is necessary to
2201 force Synchronous Transfer Negotiation so that the Inquire Setup
2202 Information and Inquire Synchronous Period commands will return
2203 valid data. The Inquire Target Devices command is preferable to
2204 Inquire Installed Devices ID 0 to 7 since it only probes Logical
2205 Unit 0 of each Target Device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002207 if (strcmp(adapter->fw_ver, "4.25") >= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
2209 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002210 Issue a Inquire Target Devices command. Inquire Target
2211 Devices only tests Logical Unit 0 of each Target Device
2212 unlike the Inquire Installed Devices commands which test
2213 Logical Units 0 - 7. Two bytes are returned, where byte
2214 0 bit 0 set indicates that Target Device 0 exists, and so on.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 */
2216
Khalid Aziz839cb992013-05-16 19:44:13 -06002217 if (blogic_cmd(adapter, BLOGIC_INQ_DEV, NULL, 0,
2218 &installed_devs, sizeof(installed_devs))
2219 != sizeof(installed_devs))
2220 return blogic_failure(adapter, "INQUIRE TARGET DEVICES");
2221 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2222 adapter->tgt_flags[tgt_id].tgt_exists =
2223 (installed_devs & (1 << tgt_id) ? true : false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 } else {
2225
2226 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002227 Issue an Inquire Installed Devices command. For each
2228 Target Device, a byte is returned where bit 0 set
2229 indicates that Logical Unit 0 * exists, bit 1 set
2230 indicates that Logical Unit 1 exists, and so on.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 */
2232
Khalid Aziz839cb992013-05-16 19:44:13 -06002233 if (blogic_cmd(adapter, BLOGIC_INQ_DEV0TO7, NULL, 0,
2234 &installed_devs0to7, sizeof(installed_devs0to7))
2235 != sizeof(installed_devs0to7))
2236 return blogic_failure(adapter,
2237 "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2238 for (tgt_id = 0; tgt_id < 8; tgt_id++)
2239 adapter->tgt_flags[tgt_id].tgt_exists =
Jason Yan3fa65812020-04-21 11:41:20 +08002240 installed_devs0to7[tgt_id] != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 }
2242 /*
2243 Issue the Inquire Setup Information command.
2244 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002245 req_replylen = sizeof(setupinfo);
2246 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
2247 sizeof(req_replylen), &setupinfo, sizeof(setupinfo))
2248 != sizeof(setupinfo))
2249 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
2250 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2251 adapter->sync_offset[tgt_id] = (tgt_id < 8 ? setupinfo.sync0to7[tgt_id].offset : setupinfo.sync8to15[tgt_id - 8].offset);
2252 if (strcmp(adapter->fw_ver, "5.06L") >= 0)
2253 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2254 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));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 /*
2256 Issue the Inquire Synchronous Period command.
2257 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002258 if (adapter->fw_ver[0] >= '3') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
Khalid Aziz839cb992013-05-16 19:44:13 -06002260 /* Issue a Inquire Synchronous Period command. For each
2261 Target Device, a byte is returned which represents the
2262 Synchronous Transfer Period in units of 10 nanoseconds.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 */
2264
Khalid Aziz839cb992013-05-16 19:44:13 -06002265 req_replylen = sizeof(sync_period);
2266 if (blogic_cmd(adapter, BLOGIC_INQ_SYNC_PERIOD, &req_replylen,
2267 sizeof(req_replylen), &sync_period,
2268 sizeof(sync_period)) != sizeof(sync_period))
2269 return blogic_failure(adapter,
2270 "INQUIRE SYNCHRONOUS PERIOD");
2271 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2272 adapter->sync_period[tgt_id] = sync_period[tgt_id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06002274 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2275 if (setupinfo.sync0to7[tgt_id].offset > 0)
2276 adapter->sync_period[tgt_id] = 20 + 5 * setupinfo.sync0to7[tgt_id].tx_period;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 /*
2278 Indicate the Target Device Inquiry completed successfully.
2279 */
2280 return true;
2281}
2282
2283/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002284 blogic_inithoststruct initializes the fields in the SCSI Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
2286 SCSI Host structure are intentionally left uninitialized, as this driver
2287 handles acquisition and release of these resources explicitly, as well as
2288 ensuring exclusive access to the Host Adapter hardware and data structures
2289 through explicit acquisition and release of the Host Adapter's Lock.
2290*/
2291
Khalid Aziz839cb992013-05-16 19:44:13 -06002292static void __init blogic_inithoststruct(struct blogic_adapter *adapter,
2293 struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294{
Khalid Aziz839cb992013-05-16 19:44:13 -06002295 host->max_id = adapter->maxdev;
2296 host->max_lun = adapter->maxlun;
2297 host->max_channel = 0;
2298 host->unique_id = adapter->io_addr;
2299 host->this_id = adapter->scsi_id;
2300 host->can_queue = adapter->drvr_qdepth;
2301 host->sg_tablesize = adapter->drvr_sglimit;
2302 host->unchecked_isa_dma = adapter->need_bouncebuf;
2303 host->cmd_per_lun = adapter->untag_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304}
2305
2306/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002307 blogic_slaveconfig will actually set the queue depth on individual
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 scsi devices as they are permanently added to the device chain. We
2309 shamelessly rip off the SelectQueueDepths code to make this work mostly
2310 like it used to. Since we don't get called once at the end of the scan
2311 but instead get called for each device, we have to do things a bit
2312 differently.
2313*/
Khalid Aziz839cb992013-05-16 19:44:13 -06002314static int blogic_slaveconfig(struct scsi_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315{
Khalid Aziz839cb992013-05-16 19:44:13 -06002316 struct blogic_adapter *adapter =
2317 (struct blogic_adapter *) dev->host->hostdata;
2318 int tgt_id = dev->id;
2319 int qdepth = adapter->qdepth[tgt_id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Khalid Aziz839cb992013-05-16 19:44:13 -06002321 if (adapter->tgt_flags[tgt_id].tagq_ok &&
2322 (adapter->tagq_ok & (1 << tgt_id))) {
2323 if (qdepth == 0)
2324 qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
2325 adapter->qdepth[tgt_id] = qdepth;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01002326 scsi_change_queue_depth(dev, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002328 adapter->tagq_ok &= ~(1 << tgt_id);
2329 qdepth = adapter->untag_qdepth;
2330 adapter->qdepth[tgt_id] = qdepth;
Christoph Hellwigdb5ed4d2014-11-13 15:08:42 +01002331 scsi_change_queue_depth(dev, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002333 qdepth = 0;
2334 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2335 if (adapter->tgt_flags[tgt_id].tgt_exists)
2336 qdepth += adapter->qdepth[tgt_id];
2337 if (qdepth > adapter->alloc_ccbs)
2338 blogic_create_addlccbs(adapter, qdepth - adapter->alloc_ccbs,
2339 false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 return 0;
2341}
2342
2343/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002344 blogic_init probes for BusLogic Host Adapters at the standard
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 I/O Addresses where they may be located, initializing, registering, and
2346 reporting the configuration of each BusLogic Host Adapter it finds. It
2347 returns the number of BusLogic Host Adapters successfully initialized and
2348 registered.
2349*/
2350
Khalid Aziz839cb992013-05-16 19:44:13 -06002351static int __init blogic_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352{
Khalid Aziz839cb992013-05-16 19:44:13 -06002353 int adapter_count = 0, drvr_optindex = 0, probeindex;
2354 struct blogic_adapter *adapter;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002355 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
2357#ifdef MODULE
2358 if (BusLogic)
Khalid Aziz839cb992013-05-16 19:44:13 -06002359 blogic_setup(BusLogic);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360#endif
2361
Khalid Aziz839cb992013-05-16 19:44:13 -06002362 if (blogic_probe_options.noprobe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 return -ENODEV;
Khalid Aziz839cb992013-05-16 19:44:13 -06002364 blogic_probeinfo_list =
Kees Cook6396bb22018-06-12 14:03:40 -07002365 kcalloc(BLOGIC_MAX_ADAPTERS, sizeof(struct blogic_probeinfo),
Khalid Aziz839cb992013-05-16 19:44:13 -06002366 GFP_KERNEL);
2367 if (blogic_probeinfo_list == NULL) {
2368 blogic_err("BusLogic: Unable to allocate Probe Info List\n",
2369 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 return -ENOMEM;
2371 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002372
Khalid Aziz391e2f22013-05-16 19:44:14 -06002373 adapter = kzalloc(sizeof(struct blogic_adapter), GFP_KERNEL);
Khalid Aziz839cb992013-05-16 19:44:13 -06002374 if (adapter == NULL) {
2375 kfree(blogic_probeinfo_list);
2376 blogic_err("BusLogic: Unable to allocate Prototype Host Adapter\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 return -ENOMEM;
2378 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002379
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380#ifdef MODULE
2381 if (BusLogic != NULL)
Khalid Aziz839cb992013-05-16 19:44:13 -06002382 blogic_setup(BusLogic);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383#endif
Khalid Aziz839cb992013-05-16 19:44:13 -06002384 blogic_init_probeinfo_list(adapter);
2385 for (probeindex = 0; probeindex < blogic_probeinfo_count; probeindex++) {
2386 struct blogic_probeinfo *probeinfo =
2387 &blogic_probeinfo_list[probeindex];
2388 struct blogic_adapter *myadapter = adapter;
2389 struct Scsi_Host *host;
2390
2391 if (probeinfo->io_addr == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06002393 memset(myadapter, 0, sizeof(struct blogic_adapter));
2394 myadapter->adapter_type = probeinfo->adapter_type;
2395 myadapter->adapter_bus_type = probeinfo->adapter_bus_type;
2396 myadapter->io_addr = probeinfo->io_addr;
2397 myadapter->pci_addr = probeinfo->pci_addr;
2398 myadapter->bus = probeinfo->bus;
2399 myadapter->dev = probeinfo->dev;
2400 myadapter->pci_device = probeinfo->pci_device;
2401 myadapter->irq_ch = probeinfo->irq_ch;
2402 myadapter->addr_count =
2403 blogic_adapter_addr_count[myadapter->adapter_type];
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002404
2405 /*
2406 Make sure region is free prior to probing.
2407 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002408 if (!request_region(myadapter->io_addr, myadapter->addr_count,
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002409 "BusLogic"))
2410 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002412 Probe the Host Adapter. If unsuccessful, abort further
2413 initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002415 if (!blogic_probe(myadapter)) {
2416 release_region(myadapter->io_addr,
2417 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 /*
2421 Hard Reset the Host Adapter. If unsuccessful, abort further
2422 initialization.
2423 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002424 if (!blogic_hwreset(myadapter, true)) {
2425 release_region(myadapter->io_addr,
2426 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002430 Check the Host Adapter. If unsuccessful, abort further
2431 initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002433 if (!blogic_checkadapter(myadapter)) {
2434 release_region(myadapter->io_addr,
2435 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 /*
2439 Initialize the Driver Options field if provided.
2440 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002441 if (drvr_optindex < blogic_drvr_options_count)
2442 myadapter->drvr_opts =
2443 &blogic_drvr_options[drvr_optindex++];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002445 Announce the Driver Version and Date, Author's Name,
2446 Copyright Notice, and Electronic Mail Address.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002448 blogic_announce_drvr(myadapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 Register the SCSI Host structure.
2451 */
2452
Khalid Aziz839cb992013-05-16 19:44:13 -06002453 host = scsi_host_alloc(&blogic_template,
2454 sizeof(struct blogic_adapter));
2455 if (host == NULL) {
2456 release_region(myadapter->io_addr,
2457 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 continue;
2459 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002460 myadapter = (struct blogic_adapter *) host->hostdata;
2461 memcpy(myadapter, adapter, sizeof(struct blogic_adapter));
2462 myadapter->scsi_host = host;
2463 myadapter->host_no = host->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002465 Add Host Adapter to the end of the list of registered
2466 BusLogic Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002468 list_add_tail(&myadapter->host_list, &blogic_host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
2470 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002471 Read the Host Adapter Configuration, Configure the Host
2472 Adapter, Acquire the System Resources necessary to use
2473 the Host Adapter, then Create the Initial CCBs, Initialize
2474 the Host Adapter, and finally perform Target Device
2475 Inquiry. From this point onward, any failure will be
2476 assumed to be due to a problem with the Host Adapter,
2477 rather than due to having mistakenly identified this port
2478 as belonging to a BusLogic Host Adapter. The I/O Address
2479 range will not be released, thereby preventing it from
2480 being incorrectly identified as any other type of Host
2481 Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002483 if (blogic_rdconfig(myadapter) &&
2484 blogic_reportconfig(myadapter) &&
2485 blogic_getres(myadapter) &&
2486 blogic_create_initccbs(myadapter) &&
2487 blogic_initadapter(myadapter) &&
2488 blogic_inquiry(myadapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002490 Initialization has been completed successfully.
2491 Release and re-register usage of the I/O Address
2492 range so that the Model Name of the Host Adapter
2493 will appear, and initialize the SCSI Host structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002495 release_region(myadapter->io_addr,
2496 myadapter->addr_count);
2497 if (!request_region(myadapter->io_addr,
2498 myadapter->addr_count,
2499 myadapter->full_model)) {
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002500 printk(KERN_WARNING
2501 "BusLogic: Release and re-register of "
2502 "port 0x%04lx failed \n",
Khalid Aziz839cb992013-05-16 19:44:13 -06002503 (unsigned long)myadapter->io_addr);
2504 blogic_destroy_ccbs(myadapter);
2505 blogic_relres(myadapter);
2506 list_del(&myadapter->host_list);
2507 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002508 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002510 blogic_inithoststruct(myadapter,
2511 host);
2512 if (scsi_add_host(host, myadapter->pci_device
2513 ? &myadapter->pci_device->dev
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002514 : NULL)) {
2515 printk(KERN_WARNING
2516 "BusLogic: scsi_add_host()"
2517 "failed!\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06002518 blogic_destroy_ccbs(myadapter);
2519 blogic_relres(myadapter);
2520 list_del(&myadapter->host_list);
2521 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002522 ret = -ENODEV;
2523 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002524 scsi_scan_host(host);
2525 adapter_count++;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 }
2528 } else {
2529 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002530 An error occurred during Host Adapter Configuration
2531 Querying, Host Adapter Configuration, Resource
2532 Acquisition, CCB Creation, Host Adapter
2533 Initialization, or Target Device Inquiry, so
2534 remove Host Adapter from the list of registered
2535 BusLogic Host Adapters, destroy the CCBs, Release
2536 the System Resources, and Unregister the SCSI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 Host.
2538 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002539 blogic_destroy_ccbs(myadapter);
2540 blogic_relres(myadapter);
2541 list_del(&myadapter->host_list);
2542 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002543 ret = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 }
2545 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002546 kfree(adapter);
2547 kfree(blogic_probeinfo_list);
2548 blogic_probeinfo_list = NULL;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002549 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550}
2551
2552
2553/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002554 blogic_deladapter releases all resources previously acquired to
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 support a specific Host Adapter, including the I/O Address range, and
2556 unregisters the BusLogic Host Adapter.
2557*/
2558
Khalid Aziz839cb992013-05-16 19:44:13 -06002559static int __exit blogic_deladapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Khalid Aziz839cb992013-05-16 19:44:13 -06002561 struct Scsi_Host *host = adapter->scsi_host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Khalid Aziz839cb992013-05-16 19:44:13 -06002563 scsi_remove_host(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
2565 /*
2566 FlashPoint Host Adapters must first be released by the FlashPoint
2567 SCCB Manager.
2568 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002569 if (blogic_flashpoint_type(adapter))
2570 FlashPoint_ReleaseHostAdapter(adapter->cardhandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 /*
2572 Destroy the CCBs and release any system resources acquired to
2573 support Host Adapter.
2574 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002575 blogic_destroy_ccbs(adapter);
2576 blogic_relres(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 /*
2578 Release usage of the I/O Address range.
2579 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002580 release_region(adapter->io_addr, adapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002582 Remove Host Adapter from the list of registered BusLogic
2583 Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002585 list_del(&adapter->host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
Khalid Aziz839cb992013-05-16 19:44:13 -06002587 scsi_host_put(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 return 0;
2589}
2590
2591
2592/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002593 blogic_qcompleted_ccb queues CCB for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594*/
2595
Khalid Aziz839cb992013-05-16 19:44:13 -06002596static void blogic_qcompleted_ccb(struct blogic_ccb *ccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597{
Khalid Aziz839cb992013-05-16 19:44:13 -06002598 struct blogic_adapter *adapter = ccb->adapter;
2599
2600 ccb->status = BLOGIC_CCB_COMPLETE;
2601 ccb->next = NULL;
2602 if (adapter->firstccb == NULL) {
2603 adapter->firstccb = ccb;
2604 adapter->lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002606 adapter->lastccb->next = ccb;
2607 adapter->lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002609 adapter->active_cmds[ccb->tgt_id]--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610}
2611
2612
2613/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002614 blogic_resultcode computes a SCSI Subsystem Result Code from
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 the Host Adapter Status and Target Device Status.
2616*/
2617
Khalid Aziz839cb992013-05-16 19:44:13 -06002618static int blogic_resultcode(struct blogic_adapter *adapter,
2619 enum blogic_adapter_status adapter_status,
2620 enum blogic_tgt_status tgt_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621{
Khalid Aziz839cb992013-05-16 19:44:13 -06002622 int hoststatus;
2623
2624 switch (adapter_status) {
2625 case BLOGIC_CMD_CMPLT_NORMAL:
2626 case BLOGIC_LINK_CMD_CMPLT:
2627 case BLOGIC_LINK_CMD_CMPLT_FLAG:
2628 hoststatus = DID_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002630 case BLOGIC_SELECT_TIMEOUT:
2631 hoststatus = DID_TIME_OUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002633 case BLOGIC_INVALID_OUTBOX_CODE:
2634 case BLOGIC_INVALID_CMD_CODE:
2635 case BLOGIC_BAD_CMD_PARAM:
2636 blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
2637 adapter, adapter_status);
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05002638 fallthrough;
Khalid Aziz839cb992013-05-16 19:44:13 -06002639 case BLOGIC_DATA_UNDERRUN:
2640 case BLOGIC_DATA_OVERRUN:
2641 case BLOGIC_NOEXPECT_BUSFREE:
2642 case BLOGIC_LINKCCB_BADLUN:
2643 case BLOGIC_AUTOREQSENSE_FAIL:
2644 case BLOGIC_TAGQUEUE_REJECT:
2645 case BLOGIC_BAD_MSG_RCVD:
2646 case BLOGIC_HW_FAIL:
2647 case BLOGIC_BAD_RECONNECT:
2648 case BLOGIC_ABRT_QUEUE:
2649 case BLOGIC_ADAPTER_SW_ERROR:
2650 case BLOGIC_HW_TIMEOUT:
2651 case BLOGIC_PARITY_ERR:
2652 hoststatus = DID_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002654 case BLOGIC_INVALID_BUSPHASE:
2655 case BLOGIC_NORESPONSE_TO_ATN:
2656 case BLOGIC_HW_RESET:
2657 case BLOGIC_RST_FROM_OTHERDEV:
2658 case BLOGIC_HW_BDR:
2659 hoststatus = DID_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 break;
2661 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06002662 blogic_warn("Unknown Host Adapter Status 0x%02X\n", adapter,
2663 adapter_status);
2664 hoststatus = DID_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 break;
2666 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002667 return (hoststatus << 16) | tgt_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668}
2669
2670
2671/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002672 blogic_scan_inbox scans the Incoming Mailboxes saving any
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 Incoming Mailbox entries for completion processing.
2674*/
2675
Khalid Aziz839cb992013-05-16 19:44:13 -06002676static void blogic_scan_inbox(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677{
2678 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002679 Scan through the Incoming Mailboxes in Strict Round Robin
2680 fashion, saving any completed CCBs for further processing. It
2681 is essential that for each CCB and SCSI Command issued, command
2682 completion processing is performed exactly once. Therefore,
2683 only Incoming Mailboxes with completion code Command Completed
2684 Without Error, Command Completed With Error, or Command Aborted
2685 At Host Request are saved for completion processing. When an
2686 Incoming Mailbox has a completion code of Aborted Command Not
2687 Found, the CCB had already completed or been aborted before the
2688 current Abort request was processed, and so completion processing
2689 has already occurred and no further action should be taken.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002691 struct blogic_inbox *next_inbox = adapter->next_inbox;
2692 enum blogic_cmplt_code comp_code;
2693
2694 while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002696 We are only allowed to do this because we limit our
2697 architectures we run on to machines where bus_to_virt(
2698 actually works. There *needs* to be a dma_addr_to_virt()
2699 in the new PCI DMA mapping interface to replace
2700 bus_to_virt() or else this code is going to become very
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 innefficient.
2702 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002703 struct blogic_ccb *ccb =
2704 (struct blogic_ccb *) bus_to_virt(next_inbox->ccb);
2705 if (comp_code != BLOGIC_CMD_NOTFOUND) {
2706 if (ccb->status == BLOGIC_CCB_ACTIVE ||
2707 ccb->status == BLOGIC_CCB_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002709 Save the Completion Code for this CCB and
2710 queue the CCB for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002712 ccb->comp_code = comp_code;
2713 blogic_qcompleted_ccb(ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 } else {
2715 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002716 If a CCB ever appears in an Incoming Mailbox
2717 and is not marked as status Active or Reset,
2718 then there is most likely a bug in
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 the Host Adapter firmware.
2720 */
Colin Ian King43622692020-01-08 19:38:00 +00002721 blogic_warn("Illegal CCB #%ld status %d in Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 }
2723 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002724 next_inbox->comp_code = BLOGIC_INBOX_FREE;
2725 if (++next_inbox > adapter->last_inbox)
2726 next_inbox = adapter->first_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002728 adapter->next_inbox = next_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729}
2730
2731
2732/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002733 blogic_process_ccbs iterates over the completed CCBs for Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
2735 calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
2736 should already have been acquired by the caller.
2737*/
2738
Khalid Aziz839cb992013-05-16 19:44:13 -06002739static void blogic_process_ccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740{
Khalid Aziz839cb992013-05-16 19:44:13 -06002741 if (adapter->processing_ccbs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 return;
Khalid Aziz839cb992013-05-16 19:44:13 -06002743 adapter->processing_ccbs = true;
2744 while (adapter->firstccb != NULL) {
2745 struct blogic_ccb *ccb = adapter->firstccb;
2746 struct scsi_cmnd *command = ccb->command;
2747 adapter->firstccb = ccb->next;
2748 if (adapter->firstccb == NULL)
2749 adapter->lastccb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 /*
2751 Process the Completed CCB.
2752 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002753 if (ccb->opcode == BLOGIC_BDR) {
2754 int tgt_id = ccb->tgt_id;
2755
Colin Ian King43622692020-01-08 19:38:00 +00002756 blogic_warn("Bus Device Reset CCB #%ld to Target %d Completed\n", adapter, ccb->serial, tgt_id);
Khalid Aziz839cb992013-05-16 19:44:13 -06002757 blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
2758 adapter->tgt_flags[tgt_id].tagq_active = false;
2759 adapter->cmds_since_rst[tgt_id] = 0;
2760 adapter->last_resetdone[tgt_id] = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 /*
2762 Place CCB back on the Host Adapter's free list.
2763 */
Khalid Azizeeceec92013-09-13 13:44:06 -06002764 blogic_dealloc_ccb(ccb, 1);
2765#if 0 /* this needs to be redone different for new EH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002767 Bus Device Reset CCBs have the command field
2768 non-NULL only when a Bus Device Reset was requested
2769 for a command that did not have a currently active
2770 CCB in the Host Adapter (i.e., a Synchronous Bus
2771 Device Reset), and hence would not have its
2772 Completion Routine called otherwise.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002774 while (command != NULL) {
2775 struct scsi_cmnd *nxt_cmd =
2776 command->reset_chain;
2777 command->reset_chain = NULL;
2778 command->result = DID_RESET << 16;
2779 command->scsi_done(command);
2780 command = nxt_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 }
2782#endif
2783 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002784 Iterate over the CCBs for this Host Adapter
2785 performing completion processing for any CCBs
2786 marked as Reset for this Target.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002788 for (ccb = adapter->all_ccbs; ccb != NULL;
2789 ccb = ccb->next_all)
2790 if (ccb->status == BLOGIC_CCB_RESET &&
2791 ccb->tgt_id == tgt_id) {
2792 command = ccb->command;
Khalid Azizeeceec92013-09-13 13:44:06 -06002793 blogic_dealloc_ccb(ccb, 1);
Khalid Aziz839cb992013-05-16 19:44:13 -06002794 adapter->active_cmds[tgt_id]--;
2795 command->result = DID_RESET << 16;
2796 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002798 adapter->bdr_pend[tgt_id] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 } else {
2800 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002801 Translate the Completion Code, Host Adapter Status,
2802 and Target Device Status into a SCSI Subsystem
2803 Result Code.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002805 switch (ccb->comp_code) {
2806 case BLOGIC_INBOX_FREE:
2807 case BLOGIC_CMD_NOTFOUND:
2808 case BLOGIC_INVALID_CCB:
2809 blogic_warn("CCB #%ld to Target %d Impossible State\n", adapter, ccb->serial, ccb->tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002811 case BLOGIC_CMD_COMPLETE_GOOD:
2812 adapter->tgt_stats[ccb->tgt_id]
2813 .cmds_complete++;
2814 adapter->tgt_flags[ccb->tgt_id]
2815 .cmd_good = true;
2816 command->result = DID_OK << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002818 case BLOGIC_CMD_ABORT_BY_HOST:
2819 blogic_warn("CCB #%ld to Target %d Aborted\n",
2820 adapter, ccb->serial, ccb->tgt_id);
2821 blogic_inc_count(&adapter->tgt_stats[ccb->tgt_id].aborts_done);
2822 command->result = DID_ABORT << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002824 case BLOGIC_CMD_COMPLETE_ERROR:
2825 command->result = blogic_resultcode(adapter,
2826 ccb->adapter_status, ccb->tgt_status);
2827 if (ccb->adapter_status != BLOGIC_SELECT_TIMEOUT) {
2828 adapter->tgt_stats[ccb->tgt_id]
2829 .cmds_complete++;
2830 if (blogic_global_options.trace_err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -06002832 blogic_notice("CCB #%ld Target %d: Result %X Host "
Colin Ian King43622692020-01-08 19:38:00 +00002833 "Adapter Status %02X Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
Khalid Aziz839cb992013-05-16 19:44:13 -06002834 blogic_notice("CDB ", adapter);
2835 for (i = 0; i < ccb->cdblen; i++)
2836 blogic_notice(" %02X", adapter, ccb->cdb[i]);
2837 blogic_notice("\n", adapter);
2838 blogic_notice("Sense ", adapter);
2839 for (i = 0; i < ccb->sense_datalen; i++)
2840 blogic_notice(" %02X", adapter, command->sense_buffer[i]);
2841 blogic_notice("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 }
2843 }
2844 break;
2845 }
2846 /*
2847 When an INQUIRY command completes normally, save the
2848 CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
2849 Wide Data Transfers Supported) bits.
2850 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002851 if (ccb->cdb[0] == INQUIRY && ccb->cdb[1] == 0 &&
2852 ccb->adapter_status == BLOGIC_CMD_CMPLT_NORMAL) {
2853 struct blogic_tgt_flags *tgt_flags =
2854 &adapter->tgt_flags[ccb->tgt_id];
2855 struct scsi_inquiry *inquiry =
2856 (struct scsi_inquiry *) scsi_sglist(command);
2857 tgt_flags->tgt_exists = true;
2858 tgt_flags->tagq_ok = inquiry->CmdQue;
2859 tgt_flags->wide_ok = inquiry->WBus16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 }
2861 /*
2862 Place CCB back on the Host Adapter's free list.
2863 */
Khalid Azizeeceec92013-09-13 13:44:06 -06002864 blogic_dealloc_ccb(ccb, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 /*
2866 Call the SCSI Command Completion Routine.
2867 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002868 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 }
2870 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002871 adapter->processing_ccbs = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
2874
2875/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002876 blogic_inthandler handles hardware interrupts from BusLogic Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 Adapters.
2878*/
2879
Khalid Aziz839cb992013-05-16 19:44:13 -06002880static irqreturn_t blogic_inthandler(int irq_ch, void *devid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881{
Khalid Aziz839cb992013-05-16 19:44:13 -06002882 struct blogic_adapter *adapter = (struct blogic_adapter *) devid;
2883 unsigned long processor_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 /*
2885 Acquire exclusive access to Host Adapter.
2886 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002887 spin_lock_irqsave(adapter->scsi_host->host_lock, processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 /*
2889 Handle Interrupts appropriately for each Host Adapter type.
2890 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002891 if (blogic_multimaster_type(adapter)) {
2892 union blogic_int_reg intreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 /*
2894 Read the Host Adapter Interrupt Register.
2895 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002896 intreg.all = blogic_rdint(adapter);
2897 if (intreg.ir.int_valid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 /*
2899 Acknowledge the interrupt and reset the Host Adapter
2900 Interrupt Register.
2901 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002902 blogic_intreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002904 Process valid External SCSI Bus Reset and Incoming
2905 Mailbox Loaded Interrupts. Command Complete
2906 Interrupts are noted, and Outgoing Mailbox Available
2907 Interrupts are ignored, as they are never enabled.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002909 if (intreg.ir.ext_busreset)
2910 adapter->adapter_extreset = true;
2911 else if (intreg.ir.mailin_loaded)
2912 blogic_scan_inbox(adapter);
2913 else if (intreg.ir.cmd_complete)
2914 adapter->adapter_cmd_complete = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 }
2916 } else {
2917 /*
2918 Check if there is a pending interrupt for this Host Adapter.
2919 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002920 if (FlashPoint_InterruptPending(adapter->cardhandle))
2921 switch (FlashPoint_HandleInterrupt(adapter->cardhandle)) {
2922 case FPOINT_NORMAL_INT:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002924 case FPOINT_EXT_RESET:
2925 adapter->adapter_extreset = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002927 case FPOINT_INTERN_ERR:
2928 blogic_warn("Internal FlashPoint Error detected - Resetting Host Adapter\n", adapter);
2929 adapter->adapter_intern_err = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 break;
2931 }
2932 }
2933 /*
2934 Process any completed CCBs.
2935 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002936 if (adapter->firstccb != NULL)
2937 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 /*
2939 Reset the Host Adapter if requested.
2940 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002941 if (adapter->adapter_extreset) {
2942 blogic_warn("Resetting %s due to External SCSI Bus Reset\n", adapter, adapter->full_model);
2943 blogic_inc_count(&adapter->ext_resets);
2944 blogic_resetadapter(adapter, false);
2945 adapter->adapter_extreset = false;
2946 } else if (adapter->adapter_intern_err) {
2947 blogic_warn("Resetting %s due to Host Adapter Internal Error\n", adapter, adapter->full_model);
2948 blogic_inc_count(&adapter->adapter_intern_errors);
2949 blogic_resetadapter(adapter, true);
2950 adapter->adapter_intern_err = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 }
2952 /*
2953 Release exclusive access to Host Adapter.
2954 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002955 spin_unlock_irqrestore(adapter->scsi_host->host_lock, processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 return IRQ_HANDLED;
2957}
2958
2959
2960/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002961 blogic_write_outbox places CCB and Action Code into an Outgoing
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 Mailbox for execution by Host Adapter. The Host Adapter's Lock should
2963 already have been acquired by the caller.
2964*/
2965
Khalid Aziz839cb992013-05-16 19:44:13 -06002966static bool blogic_write_outbox(struct blogic_adapter *adapter,
2967 enum blogic_action action, struct blogic_ccb *ccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968{
Khalid Aziz839cb992013-05-16 19:44:13 -06002969 struct blogic_outbox *next_outbox;
2970
2971 next_outbox = adapter->next_outbox;
2972 if (next_outbox->action == BLOGIC_OUTBOX_FREE) {
2973 ccb->status = BLOGIC_CCB_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002975 The CCB field must be written before the Action Code field
2976 since the Host Adapter is operating asynchronously and the
2977 locking code does not protect against simultaneous access
2978 by the Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002980 next_outbox->ccb = ccb->dma_handle;
2981 next_outbox->action = action;
2982 blogic_execmbox(adapter);
2983 if (++next_outbox > adapter->last_outbox)
2984 next_outbox = adapter->first_outbox;
2985 adapter->next_outbox = next_outbox;
2986 if (action == BLOGIC_MBOX_START) {
2987 adapter->active_cmds[ccb->tgt_id]++;
2988 if (ccb->opcode != BLOGIC_BDR)
2989 adapter->tgt_stats[ccb->tgt_id].cmds_tried++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 }
2991 return true;
2992 }
2993 return false;
2994}
2995
2996/* Error Handling (EH) support */
2997
Khalid Aziz839cb992013-05-16 19:44:13 -06002998static int blogic_hostreset(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999{
Khalid Aziz839cb992013-05-16 19:44:13 -06003000 struct blogic_adapter *adapter =
3001 (struct blogic_adapter *) SCpnt->device->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003 unsigned int id = SCpnt->device->id;
Khalid Aziz839cb992013-05-16 19:44:13 -06003004 struct blogic_tgt_stats *stats = &adapter->tgt_stats[id];
Jeff Garzik df0ae242005-05-28 07:57:14 -04003005 int rc;
3006
3007 spin_lock_irq(SCpnt->device->host->host_lock);
3008
Colin Ian King209610652017-02-21 16:27:11 +00003009 blogic_inc_count(&stats->adapter_reset_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Khalid Aziz839cb992013-05-16 19:44:13 -06003011 rc = blogic_resetadapter(adapter, false);
Jeff Garzik df0ae242005-05-28 07:57:14 -04003012 spin_unlock_irq(SCpnt->device->host->host_lock);
3013 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014}
3015
3016/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003017 blogic_qcmd creates a CCB for Command and places it into an
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 Outgoing Mailbox for execution by the associated Host Adapter.
3019*/
3020
Khalid Aziz839cb992013-05-16 19:44:13 -06003021static int blogic_qcmd_lck(struct scsi_cmnd *command,
3022 void (*comp_cb) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023{
Khalid Aziz839cb992013-05-16 19:44:13 -06003024 struct blogic_adapter *adapter =
3025 (struct blogic_adapter *) command->device->host->hostdata;
3026 struct blogic_tgt_flags *tgt_flags =
3027 &adapter->tgt_flags[command->device->id];
3028 struct blogic_tgt_stats *tgt_stats = adapter->tgt_stats;
3029 unsigned char *cdb = command->cmnd;
3030 int cdblen = command->cmd_len;
3031 int tgt_id = command->device->id;
3032 int lun = command->device->lun;
3033 int buflen = scsi_bufflen(command);
3034 int count;
3035 struct blogic_ccb *ccb;
Khalid Azizeeceec92013-09-13 13:44:06 -06003036 dma_addr_t sense_buf;
Khalid Aziz839cb992013-05-16 19:44:13 -06003037
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003039 SCSI REQUEST_SENSE commands will be executed automatically by the
3040 Host Adapter for any errors, so they should not be executed
3041 explicitly unless the Sense Data is zero indicating that no error
3042 occurred.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003044 if (cdb[0] == REQUEST_SENSE && command->sense_buffer[0] != 0) {
3045 command->result = DID_OK << 16;
3046 comp_cb(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 return 0;
3048 }
3049 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003050 Allocate a CCB from the Host Adapter's free list. In the unlikely
3051 event that there are none available and memory allocation fails,
3052 wait 1 second and try again. If that fails, the Host Adapter is
3053 probably hung so signal an error as a Host Adapter Hard Reset
3054 should be initiated soon.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003056 ccb = blogic_alloc_ccb(adapter);
3057 if (ccb == NULL) {
3058 spin_unlock_irq(adapter->scsi_host->host_lock);
3059 blogic_delay(1);
3060 spin_lock_irq(adapter->scsi_host->host_lock);
3061 ccb = blogic_alloc_ccb(adapter);
3062 if (ccb == NULL) {
3063 command->result = DID_ERROR << 16;
3064 comp_cb(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 return 0;
3066 }
3067 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003068
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 /*
3070 Initialize the fields in the BusLogic Command Control Block (CCB).
3071 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003072 count = scsi_dma_map(command);
3073 BUG_ON(count < 0);
3074 if (count) {
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003075 struct scatterlist *sg;
3076 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077
Khalid Aziz839cb992013-05-16 19:44:13 -06003078 ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
3079 ccb->datalen = count * sizeof(struct blogic_sg_seg);
3080 if (blogic_multimaster_type(adapter))
Matt Wang63841032021-05-11 03:04:37 +00003081 ccb->data = (unsigned int) ccb->dma_handle +
Khalid Aziz839cb992013-05-16 19:44:13 -06003082 ((unsigned long) &ccb->sglist -
Matt Wang63841032021-05-11 03:04:37 +00003083 (unsigned long) ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 else
Matt Wang63841032021-05-11 03:04:37 +00003085 ccb->data = virt_to_32bit_virt(ccb->sglist);
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003086
Khalid Aziz839cb992013-05-16 19:44:13 -06003087 scsi_for_each_sg(command, sg, count, i) {
3088 ccb->sglist[i].segbytes = sg_dma_len(sg);
3089 ccb->sglist[i].segdata = sg_dma_address(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003091 } else if (!count) {
3092 ccb->opcode = BLOGIC_INITIATOR_CCB;
3093 ccb->datalen = buflen;
3094 ccb->data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003096
Khalid Aziz839cb992013-05-16 19:44:13 -06003097 switch (cdb[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 case READ_6:
3099 case READ_10:
Khalid Aziz839cb992013-05-16 19:44:13 -06003100 ccb->datadir = BLOGIC_DATAIN_CHECKED;
3101 tgt_stats[tgt_id].read_cmds++;
3102 blogic_addcount(&tgt_stats[tgt_id].bytesread, buflen);
3103 blogic_incszbucket(tgt_stats[tgt_id].read_sz_buckets, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 break;
3105 case WRITE_6:
3106 case WRITE_10:
Khalid Aziz839cb992013-05-16 19:44:13 -06003107 ccb->datadir = BLOGIC_DATAOUT_CHECKED;
3108 tgt_stats[tgt_id].write_cmds++;
3109 blogic_addcount(&tgt_stats[tgt_id].byteswritten, buflen);
3110 blogic_incszbucket(tgt_stats[tgt_id].write_sz_buckets, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 break;
3112 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06003113 ccb->datadir = BLOGIC_UNCHECKED_TX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 break;
3115 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003116 ccb->cdblen = cdblen;
3117 ccb->adapter_status = 0;
3118 ccb->tgt_status = 0;
3119 ccb->tgt_id = tgt_id;
3120 ccb->lun = lun;
3121 ccb->tag_enable = false;
3122 ccb->legacytag_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003124 BusLogic recommends that after a Reset the first couple of
3125 commands that are sent to a Target Device be sent in a non
3126 Tagged Queue fashion so that the Host Adapter and Target Device
3127 can establish Synchronous and Wide Transfer before Queue Tag
3128 messages can interfere with the Synchronous and Wide Negotiation
3129 messages. By waiting to enable Tagged Queuing until after the
3130 first BLOGIC_MAX_TAG_DEPTH commands have been queued, it is
3131 assured that after a Reset any pending commands are requeued
3132 before Tagged Queuing is enabled and that the Tagged Queuing
3133 message will not occur while the partition table is being printed.
3134 In addition, some devices do not properly handle the transition
3135 from non-tagged to tagged commands, so it is necessary to wait
3136 until there are no pending commands for a target device
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 before queuing tagged commands.
3138 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003139 if (adapter->cmds_since_rst[tgt_id]++ >= BLOGIC_MAX_TAG_DEPTH &&
3140 !tgt_flags->tagq_active &&
3141 adapter->active_cmds[tgt_id] == 0
3142 && tgt_flags->tagq_ok &&
3143 (adapter->tagq_ok & (1 << tgt_id))) {
3144 tgt_flags->tagq_active = true;
3145 blogic_notice("Tagged Queuing now active for Target %d\n",
3146 adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003148 if (tgt_flags->tagq_active) {
3149 enum blogic_queuetag queuetag = BLOGIC_SIMPLETAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003151 When using Tagged Queuing with Simple Queue Tags, it
3152 appears that disk drive controllers do not guarantee that
3153 a queued command will not remain in a disconnected state
3154 indefinitely if commands that read or write nearer the
3155 head position continue to arrive without interruption.
3156 Therefore, for each Target Device this driver keeps track
3157 of the last time either the queue was empty or an Ordered
3158 Queue Tag was issued. If more than 4 seconds (one fifth
3159 of the 20 second disk timeout) have elapsed since this
3160 last sequence point, this command will be issued with an
3161 Ordered Queue Tag rather than a Simple Queue Tag, which
3162 forces the Target Device to complete all previously
3163 queued commands before this command may be executed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003165 if (adapter->active_cmds[tgt_id] == 0)
3166 adapter->last_seqpoint[tgt_id] = jiffies;
3167 else if (time_after(jiffies,
3168 adapter->last_seqpoint[tgt_id] + 4 * HZ)) {
3169 adapter->last_seqpoint[tgt_id] = jiffies;
3170 queuetag = BLOGIC_ORDEREDTAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003172 if (adapter->ext_lun) {
3173 ccb->tag_enable = true;
3174 ccb->queuetag = queuetag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003176 ccb->legacytag_enable = true;
3177 ccb->legacy_tag = queuetag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 }
3179 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003180 memcpy(ccb->cdb, cdb, cdblen);
3181 ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
Khalid Azizeeceec92013-09-13 13:44:06 -06003182 ccb->command = command;
Christoph Hellwig17a361b2018-10-10 18:03:24 +02003183 sense_buf = dma_map_single(&adapter->pci_device->dev,
Khalid Aziz839cb992013-05-16 19:44:13 -06003184 command->sense_buffer, ccb->sense_datalen,
Christoph Hellwig17a361b2018-10-10 18:03:24 +02003185 DMA_FROM_DEVICE);
Khalid Azizeeceec92013-09-13 13:44:06 -06003186 if (dma_mapping_error(&adapter->pci_device->dev, sense_buf)) {
3187 blogic_err("DMA mapping for sense data buffer failed\n",
3188 adapter);
3189 blogic_dealloc_ccb(ccb, 0);
3190 return SCSI_MLQUEUE_HOST_BUSY;
3191 }
3192 ccb->sensedata = sense_buf;
Khalid Aziz839cb992013-05-16 19:44:13 -06003193 command->scsi_done = comp_cb;
3194 if (blogic_multimaster_type(adapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003196 Place the CCB in an Outgoing Mailbox. The higher levels
3197 of the SCSI Subsystem should not attempt to queue more
3198 commands than can be placed in Outgoing Mailboxes, so
3199 there should always be one free. In the unlikely event
3200 that there are none available, wait 1 second and try
3201 again. If that fails, the Host Adapter is probably hung
3202 so signal an error as a Host Adapter Hard Reset should
3203 be initiated soon.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003205 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
3206 spin_unlock_irq(adapter->scsi_host->host_lock);
Colin Ian King43622692020-01-08 19:38:00 +00003207 blogic_warn("Unable to write Outgoing Mailbox - Pausing for 1 second\n", adapter);
Khalid Aziz839cb992013-05-16 19:44:13 -06003208 blogic_delay(1);
3209 spin_lock_irq(adapter->scsi_host->host_lock);
3210 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
3211 ccb)) {
Colin Ian King43622692020-01-08 19:38:00 +00003212 blogic_warn("Still unable to write Outgoing Mailbox - Host Adapter Dead?\n", adapter);
Khalid Azizeeceec92013-09-13 13:44:06 -06003213 blogic_dealloc_ccb(ccb, 1);
Khalid Aziz839cb992013-05-16 19:44:13 -06003214 command->result = DID_ERROR << 16;
3215 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 }
3217 }
3218 } else {
3219 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003220 Call the FlashPoint SCCB Manager to start execution of
3221 the CCB.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003223 ccb->status = BLOGIC_CCB_ACTIVE;
3224 adapter->active_cmds[tgt_id]++;
3225 tgt_stats[tgt_id].cmds_tried++;
3226 FlashPoint_StartCCB(adapter->cardhandle, ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003228 The Command may have already completed and
3229 blogic_qcompleted_ccb been called, or it may still be
3230 pending.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003232 if (ccb->status == BLOGIC_CCB_COMPLETE)
3233 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234 }
3235 return 0;
3236}
3237
Khalid Aziz839cb992013-05-16 19:44:13 -06003238static DEF_SCSI_QCMD(blogic_qcmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07003240#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003242 blogic_abort aborts Command if possible.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243*/
3244
Khalid Aziz839cb992013-05-16 19:44:13 -06003245static int blogic_abort(struct scsi_cmnd *command)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246{
Khalid Aziz839cb992013-05-16 19:44:13 -06003247 struct blogic_adapter *adapter =
3248 (struct blogic_adapter *) command->device->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Khalid Aziz839cb992013-05-16 19:44:13 -06003250 int tgt_id = command->device->id;
3251 struct blogic_ccb *ccb;
3252 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_request);
3253
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003255 Attempt to find an Active CCB for this Command. If no Active
3256 CCB for this Command is found, then no Abort is necessary.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003258 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3259 if (ccb->command == command)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003261 if (ccb == NULL) {
3262 blogic_warn("Unable to Abort Command to Target %d - No CCB Found\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 return SUCCESS;
Khalid Aziz839cb992013-05-16 19:44:13 -06003264 } else if (ccb->status == BLOGIC_CCB_COMPLETE) {
3265 blogic_warn("Unable to Abort Command to Target %d - CCB Completed\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 return SUCCESS;
Khalid Aziz839cb992013-05-16 19:44:13 -06003267 } else if (ccb->status == BLOGIC_CCB_RESET) {
3268 blogic_warn("Unable to Abort Command to Target %d - CCB Reset\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 return SUCCESS;
3270 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003271 if (blogic_multimaster_type(adapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003273 Attempt to Abort this CCB. MultiMaster Firmware versions
3274 prior to 5.xx do not generate Abort Tag messages, but only
3275 generate the non-tagged Abort message. Since non-tagged
3276 commands are not sent by the Host Adapter until the queue
3277 of outstanding tagged commands has completed, and the
3278 Abort message is treated as a non-tagged command, it is
3279 effectively impossible to abort commands when Tagged
3280 Queuing is active. Firmware version 5.xx does generate
3281 Abort Tag messages, so it is possible to abort commands
3282 when Tagged Queuing is active.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003284 if (adapter->tgt_flags[tgt_id].tagq_active &&
3285 adapter->fw_ver[0] < '5') {
3286 blogic_warn("Unable to Abort CCB #%ld to Target %d - Abort Tag Not Supported\n", adapter, ccb->serial, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 return FAILURE;
Khalid Aziz839cb992013-05-16 19:44:13 -06003288 } else if (blogic_write_outbox(adapter, BLOGIC_MBOX_ABORT,
3289 ccb)) {
3290 blogic_warn("Aborting CCB #%ld to Target %d\n",
3291 adapter, ccb->serial, tgt_id);
3292 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293 return SUCCESS;
3294 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003295 blogic_warn("Unable to Abort CCB #%ld to Target %d - No Outgoing Mailboxes\n", adapter, ccb->serial, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 return FAILURE;
3297 }
3298 } else {
3299 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003300 Call the FlashPoint SCCB Manager to abort execution of
3301 the CCB.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003303 blogic_warn("Aborting CCB #%ld to Target %d\n", adapter,
3304 ccb->serial, tgt_id);
3305 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3306 FlashPoint_AbortCCB(adapter->cardhandle, ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 /*
3308 The Abort may have already been completed and
Khalid Aziz839cb992013-05-16 19:44:13 -06003309 blogic_qcompleted_ccb been called, or it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 may still be pending.
3311 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003312 if (ccb->status == BLOGIC_CCB_COMPLETE)
3313 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 return SUCCESS;
3315 }
3316 return SUCCESS;
3317}
3318
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07003319#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003321 blogic_resetadapter resets Host Adapter if possible, marking all
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 currently executing SCSI Commands as having been Reset.
3323*/
3324
Khalid Aziz839cb992013-05-16 19:44:13 -06003325static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326{
Khalid Aziz839cb992013-05-16 19:44:13 -06003327 struct blogic_ccb *ccb;
3328 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
3330 /*
3331 * Attempt to Reset and Reinitialize the Host Adapter.
3332 */
3333
Khalid Aziz839cb992013-05-16 19:44:13 -06003334 if (!(blogic_hwreset(adapter, hard_reset) &&
3335 blogic_initadapter(adapter))) {
3336 blogic_err("Resetting %s Failed\n", adapter,
3337 adapter->full_model);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 return FAILURE;
3339 }
3340
3341 /*
3342 * Deallocate all currently executing CCBs.
3343 */
3344
Khalid Aziz839cb992013-05-16 19:44:13 -06003345 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3346 if (ccb->status == BLOGIC_CCB_ACTIVE)
Khalid Azizeeceec92013-09-13 13:44:06 -06003347 blogic_dealloc_ccb(ccb, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 /*
3349 * Wait a few seconds between the Host Adapter Hard Reset which
3350 * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
3351 * SCSI devices get confused if they receive SCSI Commands too soon
3352 * after a SCSI Bus Reset.
3353 */
3354
Khalid Aziz839cb992013-05-16 19:44:13 -06003355 if (hard_reset) {
3356 spin_unlock_irq(adapter->scsi_host->host_lock);
3357 blogic_delay(adapter->bus_settle_time);
3358 spin_lock_irq(adapter->scsi_host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 }
3360
Khalid Aziz839cb992013-05-16 19:44:13 -06003361 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
3362 adapter->last_resettried[tgt_id] = jiffies;
3363 adapter->last_resetdone[tgt_id] = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 }
3365 return SUCCESS;
3366}
3367
3368/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003369 blogic_diskparam returns the Heads/Sectors/Cylinders BIOS Disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
3371 the appropriate number of cylinders so as not to exceed drive capacity. In
3372 order for disks equal to or larger than 1 GB to be addressable by the BIOS
3373 without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
3374 may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
3375 series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
3376 series MultiMaster Host Adapters. With Extended Translation enabled, drives
3377 between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
3378 heads and 32 sectors, and drives above 2 GB inclusive are given a disk
3379 geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
3380 Extended Translation setting does not match the geometry in the partition
3381 table, then the translation inferred from the partition table will be used by
3382 the BIOS, and a warning may be displayed.
3383*/
3384
Khalid Aziz839cb992013-05-16 19:44:13 -06003385static int blogic_diskparam(struct scsi_device *sdev, struct block_device *dev,
3386 sector_t capacity, int *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387{
Khalid Aziz839cb992013-05-16 19:44:13 -06003388 struct blogic_adapter *adapter =
3389 (struct blogic_adapter *) sdev->host->hostdata;
3390 struct bios_diskparam *diskparam = (struct bios_diskparam *) params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 unsigned char *buf;
Khalid Aziz839cb992013-05-16 19:44:13 -06003392
3393 if (adapter->ext_trans_enable && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */) {
3394 if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */) {
3395 diskparam->heads = 255;
3396 diskparam->sectors = 63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003398 diskparam->heads = 128;
3399 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400 }
3401 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003402 diskparam->heads = 64;
3403 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003405 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3406 buf = scsi_bios_ptable(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 if (buf == NULL)
3408 return 0;
3409 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003410 If the boot sector partition table flag is valid, search for
3411 a partition table entry whose end_head matches one of the
3412 standard BusLogic geometry translations (64/32, 128/32, or 255/63).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 */
Christoph Hellwig1442f762020-03-24 08:25:26 +01003414 if (*(unsigned short *) (buf + 64) == MSDOS_LABEL_MAGIC) {
3415 struct msdos_partition *part1_entry =
3416 (struct msdos_partition *)buf;
3417 struct msdos_partition *part_entry = part1_entry;
Khalid Aziz839cb992013-05-16 19:44:13 -06003418 int saved_cyl = diskparam->cylinders, part_no;
3419 unsigned char part_end_head = 0, part_end_sector = 0;
3420
3421 for (part_no = 0; part_no < 4; part_no++) {
3422 part_end_head = part_entry->end_head;
3423 part_end_sector = part_entry->end_sector & 0x3F;
3424 if (part_end_head == 64 - 1) {
3425 diskparam->heads = 64;
3426 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003428 } else if (part_end_head == 128 - 1) {
3429 diskparam->heads = 128;
3430 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003432 } else if (part_end_head == 255 - 1) {
3433 diskparam->heads = 255;
3434 diskparam->sectors = 63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 break;
3436 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003437 part_entry++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003439 if (part_no == 4) {
3440 part_end_head = part1_entry->end_head;
3441 part_end_sector = part1_entry->end_sector & 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003443 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3444 if (part_no < 4 && part_end_sector == diskparam->sectors) {
3445 if (diskparam->cylinders != saved_cyl)
3446 blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
3447 } else if (part_end_head > 0 || part_end_sector > 0) {
Colin Ian King43622692020-01-08 19:38:00 +00003448 blogic_warn("Warning: Partition Table appears to have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
3449 blogic_warn("not compatible with current BusLogic Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 }
3451 }
3452 kfree(buf);
3453 return 0;
3454}
3455
3456
3457/*
3458 BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
3459*/
3460
Khalid Aziz839cb992013-05-16 19:44:13 -06003461static int blogic_write_info(struct Scsi_Host *shost, char *procbuf,
3462 int bytes_avail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463{
Khalid Aziz839cb992013-05-16 19:44:13 -06003464 struct blogic_adapter *adapter =
3465 (struct blogic_adapter *) shost->hostdata;
3466 struct blogic_tgt_stats *tgt_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
Khalid Aziz839cb992013-05-16 19:44:13 -06003468 tgt_stats = adapter->tgt_stats;
3469 adapter->ext_resets = 0;
3470 adapter->adapter_intern_errors = 0;
3471 memset(tgt_stats, 0, BLOGIC_MAXDEV * sizeof(struct blogic_tgt_stats));
Al Viro25daa962013-03-31 01:52:13 -04003472 return 0;
3473}
3474
Khalid Aziz839cb992013-05-16 19:44:13 -06003475static int blogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
Al Viro25daa962013-03-31 01:52:13 -04003476{
Khalid Aziz839cb992013-05-16 19:44:13 -06003477 struct blogic_adapter *adapter = (struct blogic_adapter *) shost->hostdata;
3478 struct blogic_tgt_stats *tgt_stats;
3479 int tgt;
Al Viro25daa962013-03-31 01:52:13 -04003480
Khalid Aziz839cb992013-05-16 19:44:13 -06003481 tgt_stats = adapter->tgt_stats;
3482 seq_write(m, adapter->msgbuf, adapter->msgbuflen);
Al Viro25daa962013-03-31 01:52:13 -04003483 seq_printf(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484Current Driver Queue Depth: %d\n\
Khalid Aziz839cb992013-05-16 19:44:13 -06003485Currently Allocated CCBs: %d\n", adapter->drvr_qdepth, adapter->alloc_ccbs);
Rasmus Villemoes91c40f22014-12-03 00:10:52 +01003486 seq_puts(m, "\n\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 DATA TRANSFER STATISTICS\n\
3488\n\
3489Target Tagged Queuing Queue Depth Active Attempted Completed\n\
3490====== ============== =========== ====== ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003491 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3492 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3493 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06003495 seq_printf(m, " %2d %s", tgt, (tgt_flags->tagq_ok ? (tgt_flags->tagq_active ? " Active" : (adapter->tagq_ok & (1 << tgt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 ? " Permitted" : " Disabled"))
3497 : "Not Supported"));
Al Viro25daa962013-03-31 01:52:13 -04003498 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003499 " %3d %3u %9u %9u\n", adapter->qdepth[tgt], adapter->active_cmds[tgt], tgt_stats[tgt].cmds_tried, tgt_stats[tgt].cmds_complete);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 }
Rasmus Villemoes91c40f22014-12-03 00:10:52 +01003501 seq_puts(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
3503====== ============= ============== =================== ===================\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003504 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3505 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3506 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06003508 seq_printf(m, " %2d %9u %9u", tgt, tgt_stats[tgt].read_cmds, tgt_stats[tgt].write_cmds);
3509 if (tgt_stats[tgt].bytesread.billions > 0)
3510 seq_printf(m, " %9u%09u", tgt_stats[tgt].bytesread.billions, tgt_stats[tgt].bytesread.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003512 seq_printf(m, " %9u", tgt_stats[tgt].bytesread.units);
3513 if (tgt_stats[tgt].byteswritten.billions > 0)
3514 seq_printf(m, " %9u%09u\n", tgt_stats[tgt].byteswritten.billions, tgt_stats[tgt].byteswritten.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003516 seq_printf(m, " %9u\n", tgt_stats[tgt].byteswritten.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 }
Rasmus Villemoes91c40f22014-12-03 00:10:52 +01003518 seq_puts(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
3520====== ======= ========= ========= ========= ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003521 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3522 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3523 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 continue;
Al Viro25daa962013-03-31 01:52:13 -04003525 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003526 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3527 tgt_stats[tgt].read_sz_buckets[0],
3528 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]);
Al Viro25daa962013-03-31 01:52:13 -04003529 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003530 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3531 tgt_stats[tgt].write_sz_buckets[0],
3532 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]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 }
Rasmus Villemoes91c40f22014-12-03 00:10:52 +01003534 seq_puts(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
3536====== ======= ========= ========= ========= ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003537 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3538 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3539 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 continue;
Al Viro25daa962013-03-31 01:52:13 -04003541 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003542 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3543 tgt_stats[tgt].read_sz_buckets[5],
3544 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]);
Al Viro25daa962013-03-31 01:52:13 -04003545 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003546 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3547 tgt_stats[tgt].write_sz_buckets[5],
3548 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]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 }
Rasmus Villemoes91c40f22014-12-03 00:10:52 +01003550 seq_puts(m, "\n\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 ERROR RECOVERY STATISTICS\n\
3552\n\
3553 Command Aborts Bus Device Resets Host Adapter Resets\n\
3554Target Requested Completed Requested Completed Requested Completed\n\
3555 ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
3556====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003557 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3558 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3559 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 continue;
Colin Ian King209610652017-02-21 16:27:11 +00003561 seq_printf(m, " %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n",
3562 tgt, tgt_stats[tgt].aborts_request,
3563 tgt_stats[tgt].aborts_tried,
3564 tgt_stats[tgt].aborts_done,
3565 tgt_stats[tgt].bdr_request,
3566 tgt_stats[tgt].bdr_tried,
3567 tgt_stats[tgt].bdr_done,
3568 tgt_stats[tgt].adapter_reset_req,
3569 tgt_stats[tgt].adapter_reset_attempt,
3570 tgt_stats[tgt].adapter_reset_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003572 seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
3573 seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
Al Viro25daa962013-03-31 01:52:13 -04003574 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575}
3576
3577
3578/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003579 blogic_msg prints Driver Messages.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580*/
3581
Khalid Aziz839cb992013-05-16 19:44:13 -06003582static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
3583 struct blogic_adapter *adapter, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584{
Khalid Aziz839cb992013-05-16 19:44:13 -06003585 static char buf[BLOGIC_LINEBUF_SIZE];
3586 static bool begin = true;
3587 va_list args;
3588 int len = 0;
3589
3590 va_start(args, adapter);
3591 len = vsprintf(buf, fmt, args);
3592 va_end(args);
3593 if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
3594 static int msglines = 0;
3595 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3596 adapter->msgbuflen += len;
3597 if (++msglines <= 2)
3598 printk("%sscsi: %s", blogic_msglevelmap[msglevel], buf);
3599 } else if (msglevel == BLOGIC_INFO_LEVEL) {
3600 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3601 adapter->msgbuflen += len;
3602 if (begin) {
3603 if (buf[0] != '\n' || len > 1)
3604 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 } else
Maciej W. Rozycki137dafa2021-04-20 20:01:47 +02003606 pr_cont("%s", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003608 if (begin) {
3609 if (adapter != NULL && adapter->adapter_initd)
3610 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003612 printk("%s%s", blogic_msglevelmap[msglevel], buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 } else
Maciej W. Rozycki137dafa2021-04-20 20:01:47 +02003614 pr_cont("%s", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003616 begin = (buf[len - 1] == '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617}
3618
3619
3620/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003621 blogic_parse parses an individual option keyword. It returns true
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 and updates the pointer if the keyword is recognized and false otherwise.
3623*/
3624
Khalid Aziz839cb992013-05-16 19:44:13 -06003625static bool __init blogic_parse(char **str, char *keyword)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626{
Khalid Aziz839cb992013-05-16 19:44:13 -06003627 char *pointer = *str;
3628 while (*keyword != '\0') {
3629 char strch = *pointer++;
3630 char keywordch = *keyword++;
3631 if (strch >= 'A' && strch <= 'Z')
3632 strch += 'a' - 'Z';
3633 if (keywordch >= 'A' && keywordch <= 'Z')
3634 keywordch += 'a' - 'Z';
3635 if (strch != keywordch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 return false;
3637 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003638 *str = pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 return true;
3640}
3641
3642
3643/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003644 blogic_parseopts handles processing of BusLogic Driver Options
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 specifications.
3646
3647 BusLogic Driver Options may be specified either via the Linux Kernel Command
3648 Line or via the Loadable Kernel Module Installation Facility. Driver Options
3649 for multiple host adapters may be specified either by separating the option
3650 strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
3651 command line. Individual option specifications for a single host adapter are
3652 separated by commas. The Probing and Debugging Options apply to all host
3653 adapters whereas the remaining options apply individually only to the
3654 selected host adapter.
3655
3656 The BusLogic Driver Probing Options are described in
Mauro Carvalho Chehab977b8992020-03-02 09:15:44 +01003657 <file:Documentation/scsi/BusLogic.rst>.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658*/
3659
Khalid Aziz839cb992013-05-16 19:44:13 -06003660static int __init blogic_parseopts(char *options)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661{
3662 while (true) {
Khalid Aziz839cb992013-05-16 19:44:13 -06003663 struct blogic_drvr_options *drvr_opts =
3664 &blogic_drvr_options[blogic_drvr_options_count++];
3665 int tgt_id;
3666
3667 memset(drvr_opts, 0, sizeof(struct blogic_drvr_options));
3668 while (*options != '\0' && *options != ';') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 /* Probing Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003670 if (blogic_parse(&options, "IO:")) {
3671 unsigned long io_addr = simple_strtoul(options,
3672 &options, 0);
3673 blogic_probe_options.limited_isa = true;
3674 switch (io_addr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 case 0x330:
Khalid Aziz839cb992013-05-16 19:44:13 -06003676 blogic_probe_options.probe330 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 break;
3678 case 0x334:
Khalid Aziz839cb992013-05-16 19:44:13 -06003679 blogic_probe_options.probe334 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 break;
3681 case 0x230:
Khalid Aziz839cb992013-05-16 19:44:13 -06003682 blogic_probe_options.probe230 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683 break;
3684 case 0x234:
Khalid Aziz839cb992013-05-16 19:44:13 -06003685 blogic_probe_options.probe234 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 break;
3687 case 0x130:
Khalid Aziz839cb992013-05-16 19:44:13 -06003688 blogic_probe_options.probe130 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 break;
3690 case 0x134:
Khalid Aziz839cb992013-05-16 19:44:13 -06003691 blogic_probe_options.probe134 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 break;
3693 default:
Colin Ian King43622692020-01-08 19:38:00 +00003694 blogic_err("BusLogic: Invalid Driver Options (invalid I/O Address 0x%lX)\n", NULL, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 return 0;
3696 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003697 } else if (blogic_parse(&options, "NoProbeISA"))
3698 blogic_probe_options.noprobe_isa = true;
3699 else if (blogic_parse(&options, "NoProbePCI"))
3700 blogic_probe_options.noprobe_pci = true;
3701 else if (blogic_parse(&options, "NoProbe"))
3702 blogic_probe_options.noprobe = true;
3703 else if (blogic_parse(&options, "NoSortPCI"))
3704 blogic_probe_options.nosort_pci = true;
3705 else if (blogic_parse(&options, "MultiMasterFirst"))
3706 blogic_probe_options.multimaster_first = true;
3707 else if (blogic_parse(&options, "FlashPointFirst"))
3708 blogic_probe_options.flashpoint_first = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 /* Tagged Queuing Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003710 else if (blogic_parse(&options, "QueueDepth:[") ||
3711 blogic_parse(&options, "QD:[")) {
3712 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
3713 unsigned short qdepth = simple_strtoul(options, &options, 0);
3714 if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
Colin Ian King43622692020-01-08 19:38:00 +00003715 blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 return 0;
3717 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003718 drvr_opts->qdepth[tgt_id] = qdepth;
3719 if (*options == ',')
3720 options++;
3721 else if (*options == ']')
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 break;
3723 else {
Colin Ian King43622692020-01-08 19:38:00 +00003724 blogic_err("BusLogic: Invalid Driver Options (',' or ']' expected at '%s')\n", NULL, options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 return 0;
3726 }
3727 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003728 if (*options != ']') {
Colin Ian King43622692020-01-08 19:38:00 +00003729 blogic_err("BusLogic: Invalid Driver Options (']' expected at '%s')\n", NULL, options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730 return 0;
3731 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06003732 options++;
3733 } else if (blogic_parse(&options, "QueueDepth:") || blogic_parse(&options, "QD:")) {
3734 unsigned short qdepth = simple_strtoul(options, &options, 0);
3735 if (qdepth == 0 ||
3736 qdepth > BLOGIC_MAX_TAG_DEPTH) {
Colin Ian King43622692020-01-08 19:38:00 +00003737 blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 return 0;
3739 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003740 drvr_opts->common_qdepth = qdepth;
3741 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3742 drvr_opts->qdepth[tgt_id] = qdepth;
3743 } else if (blogic_parse(&options, "TaggedQueuing:") ||
3744 blogic_parse(&options, "TQ:")) {
3745 if (blogic_parse(&options, "Default")) {
3746 drvr_opts->tagq_ok = 0x0000;
3747 drvr_opts->tagq_ok_mask = 0x0000;
3748 } else if (blogic_parse(&options, "Enable")) {
3749 drvr_opts->tagq_ok = 0xFFFF;
3750 drvr_opts->tagq_ok_mask = 0xFFFF;
3751 } else if (blogic_parse(&options, "Disable")) {
3752 drvr_opts->tagq_ok = 0x0000;
3753 drvr_opts->tagq_ok_mask = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003755 unsigned short tgt_bit;
3756 for (tgt_id = 0, tgt_bit = 1;
3757 tgt_id < BLOGIC_MAXDEV;
3758 tgt_id++, tgt_bit <<= 1)
3759 switch (*options++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 case 'Y':
Khalid Aziz839cb992013-05-16 19:44:13 -06003761 drvr_opts->tagq_ok |= tgt_bit;
3762 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 break;
3764 case 'N':
Khalid Aziz839cb992013-05-16 19:44:13 -06003765 drvr_opts->tagq_ok &= ~tgt_bit;
3766 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 break;
3768 case 'X':
3769 break;
3770 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06003771 options--;
3772 tgt_id = BLOGIC_MAXDEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 break;
3774 }
3775 }
3776 }
3777 /* Miscellaneous Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003778 else if (blogic_parse(&options, "BusSettleTime:") ||
3779 blogic_parse(&options, "BST:")) {
3780 unsigned short bus_settle_time =
3781 simple_strtoul(options, &options, 0);
3782 if (bus_settle_time > 5 * 60) {
Colin Ian King43622692020-01-08 19:38:00 +00003783 blogic_err("BusLogic: Invalid Driver Options (invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 return 0;
3785 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003786 drvr_opts->bus_settle_time = bus_settle_time;
3787 } else if (blogic_parse(&options,
3788 "InhibitTargetInquiry"))
3789 drvr_opts->stop_tgt_inquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 /* Debugging Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003791 else if (blogic_parse(&options, "TraceProbe"))
3792 blogic_global_options.trace_probe = true;
3793 else if (blogic_parse(&options, "TraceHardwareReset"))
3794 blogic_global_options.trace_hw_reset = true;
3795 else if (blogic_parse(&options, "TraceConfiguration"))
3796 blogic_global_options.trace_config = true;
3797 else if (blogic_parse(&options, "TraceErrors"))
3798 blogic_global_options.trace_err = true;
3799 else if (blogic_parse(&options, "Debug")) {
3800 blogic_global_options.trace_probe = true;
3801 blogic_global_options.trace_hw_reset = true;
3802 blogic_global_options.trace_config = true;
3803 blogic_global_options.trace_err = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003805 if (*options == ',')
3806 options++;
3807 else if (*options != ';' && *options != '\0') {
Colin Ian King43622692020-01-08 19:38:00 +00003808 blogic_err("BusLogic: Unexpected Driver Option '%s' ignored\n", NULL, options);
Khalid Aziz839cb992013-05-16 19:44:13 -06003809 *options = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 }
3811 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003812 if (!(blogic_drvr_options_count == 0 ||
3813 blogic_probeinfo_count == 0 ||
3814 blogic_drvr_options_count == blogic_probeinfo_count)) {
Colin Ian King43622692020-01-08 19:38:00 +00003815 blogic_err("BusLogic: Invalid Driver Options (all or no I/O Addresses must be specified)\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 return 0;
3817 }
3818 /*
3819 Tagged Queuing is disabled when the Queue Depth is 1 since queuing
3820 multiple commands is not possible.
3821 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003822 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3823 if (drvr_opts->qdepth[tgt_id] == 1) {
3824 unsigned short tgt_bit = 1 << tgt_id;
3825 drvr_opts->tagq_ok &= ~tgt_bit;
3826 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003828 if (*options == ';')
3829 options++;
3830 if (*options == '\0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 return 0;
3832 }
3833 return 1;
3834}
3835
3836/*
3837 Get it all started
3838*/
3839
Khalid Aziz839cb992013-05-16 19:44:13 -06003840static struct scsi_host_template blogic_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 .module = THIS_MODULE,
3842 .proc_name = "BusLogic",
Khalid Aziz839cb992013-05-16 19:44:13 -06003843 .write_info = blogic_write_info,
3844 .show_info = blogic_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 .name = "BusLogic",
Khalid Aziz839cb992013-05-16 19:44:13 -06003846 .info = blogic_drvr_info,
3847 .queuecommand = blogic_qcmd,
3848 .slave_configure = blogic_slaveconfig,
3849 .bios_param = blogic_diskparam,
3850 .eh_host_reset_handler = blogic_hostreset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851#if 0
Khalid Aziz839cb992013-05-16 19:44:13 -06003852 .eh_abort_handler = blogic_abort,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853#endif
3854 .unchecked_isa_dma = 1,
3855 .max_sectors = 128,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856};
3857
3858/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003859 blogic_setup handles processing of Kernel Command Line Arguments.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860*/
3861
Khalid Aziz839cb992013-05-16 19:44:13 -06003862static int __init blogic_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863{
3864 int ints[3];
3865
3866 (void) get_options(str, ARRAY_SIZE(ints), ints);
3867
3868 if (ints[0] != 0) {
Colin Ian King43622692020-01-08 19:38:00 +00003869 blogic_err("BusLogic: Obsolete Command Line Entry Format Ignored\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870 return 0;
3871 }
3872 if (str == NULL || *str == '\0')
3873 return 0;
Khalid Aziz839cb992013-05-16 19:44:13 -06003874 return blogic_parseopts(str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875}
3876
3877/*
3878 * Exit function. Deletes all hosts associated with this driver.
3879 */
3880
Khalid Aziz839cb992013-05-16 19:44:13 -06003881static void __exit blogic_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882{
Khalid Aziz839cb992013-05-16 19:44:13 -06003883 struct blogic_adapter *ha, *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
Khalid Aziz839cb992013-05-16 19:44:13 -06003885 list_for_each_entry_safe(ha, next, &blogic_host_list, host_list)
3886 blogic_deladapter(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887}
3888
Khalid Aziz839cb992013-05-16 19:44:13 -06003889__setup("BusLogic=", blogic_setup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003891#ifdef MODULE
Khalid Aziz839cb992013-05-16 19:44:13 -06003892/*static struct pci_device_id blogic_pci_tbl[] = {
Ben Collins745b5712006-10-18 08:36:57 -04003893 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
3894 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3895 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
3896 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3897 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
3898 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3899 { }
Khalid Aziz839cb992013-05-16 19:44:13 -06003900};*/
Benoit Taine9baa3c32014-08-08 15:56:03 +02003901static const struct pci_device_id blogic_pci_tbl[] = {
Khalid Aziz839cb992013-05-16 19:44:13 -06003902 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
3903 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
3904 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
3905 {0, },
Ben Collins745b5712006-10-18 08:36:57 -04003906};
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003907#endif
Khalid Aziz839cb992013-05-16 19:44:13 -06003908MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
Ben Collins745b5712006-10-18 08:36:57 -04003909
Khalid Aziz839cb992013-05-16 19:44:13 -06003910module_init(blogic_init);
3911module_exit(blogic_exit);