blob: 6ec36d83af6c053b72f5300d27b237cf3eae6b1d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001
2/*
3
4 Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
5
6 Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
7
8 This program is free software; you may redistribute and/or modify it under
9 the terms of the GNU General Public License Version 2 as published by the
10 Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for complete details.
16
17 The author respectfully requests that any modifications to this software be
18 sent directly to him for evaluation and testing.
19
20 Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
21 advice has been invaluable, to David Gentzel, for writing the original Linux
22 BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
23
24 Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
25 Manager available as freely redistributable source code.
26
27*/
28
Khalid Aziz839cb992013-05-16 19:44:13 -060029#define blogic_drvr_version "2.1.16"
30#define blogic_drvr_date "18 July 2002"
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/interrupt.h>
35#include <linux/types.h>
36#include <linux/blkdev.h>
37#include <linux/delay.h>
38#include <linux/ioport.h>
39#include <linux/mm.h>
40#include <linux/stat.h>
41#include <linux/pci.h>
42#include <linux/spinlock.h>
Marcelo Feitoza Parisi60c904a2006-03-28 01:56:47 -080043#include <linux/jiffies.h>
Matthias Gehre910638a2006-03-28 01:56:48 -080044#include <linux/dma-mapping.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090045#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <scsi/scsicam.h>
47
48#include <asm/dma.h>
49#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <scsi/scsi.h>
52#include <scsi/scsi_cmnd.h>
53#include <scsi/scsi_device.h>
54#include <scsi/scsi_host.h>
55#include <scsi/scsi_tcq.h>
56#include "BusLogic.h"
57#include "FlashPoint.c"
58
59#ifndef FAILURE
60#define FAILURE (-1)
61#endif
62
Khalid Aziz839cb992013-05-16 19:44:13 -060063static struct scsi_host_template blogic_template;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65/*
Khalid Aziz839cb992013-05-16 19:44:13 -060066 blogic_drvr_options_count is a count of the number of BusLogic Driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 Options specifications provided via the Linux Kernel Command Line or via
68 the Loadable Kernel Module Installation Facility.
69*/
70
Khalid Aziz839cb992013-05-16 19:44:13 -060071static int blogic_drvr_options_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73
74/*
Khalid Aziz839cb992013-05-16 19:44:13 -060075 blogic_drvr_options is an array of Driver Options structures representing
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 BusLogic Driver Options specifications provided via the Linux Kernel Command
77 Line or via the Loadable Kernel Module Installation Facility.
78*/
79
Khalid Aziz839cb992013-05-16 19:44:13 -060080static struct blogic_drvr_options blogic_drvr_options[BLOGIC_MAX_ADAPTERS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
82
83/*
84 BusLogic can be assigned a string by insmod.
85*/
86
87MODULE_LICENSE("GPL");
88#ifdef MODULE
89static char *BusLogic;
90module_param(BusLogic, charp, 0);
91#endif
92
93
94/*
Khalid Aziz839cb992013-05-16 19:44:13 -060095 blogic_probe_options is a set of Probe Options to be applied across
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 all BusLogic Host Adapters.
97*/
98
Khalid Aziz839cb992013-05-16 19:44:13 -060099static struct blogic_probe_options blogic_probe_options;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101
102/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600103 blogic_global_options is a set of Global Options to be applied across
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 all BusLogic Host Adapters.
105*/
106
Khalid Aziz839cb992013-05-16 19:44:13 -0600107static struct blogic_global_options blogic_global_options;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Khalid Aziz839cb992013-05-16 19:44:13 -0600109static LIST_HEAD(blogic_host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600112 blogic_probeinfo_count is the number of entries in blogic_probeinfo_list.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113*/
114
Khalid Aziz839cb992013-05-16 19:44:13 -0600115static int blogic_probeinfo_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117
118/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600119 blogic_probeinfo_list is the list of I/O Addresses and Bus Probe Information
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 to be checked for potential BusLogic Host Adapters. It is initialized by
121 interrogating the PCI Configuration Space on PCI machines as well as from the
122 list of standard BusLogic I/O Addresses.
123*/
124
Khalid Aziz839cb992013-05-16 19:44:13 -0600125static struct blogic_probeinfo *blogic_probeinfo_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127
128/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600129 blogic_cmd_failure_reason holds a string identifying the reason why a
130 call to blogic_cmd failed. It is only non-NULL when blogic_cmd
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 returns a failure code.
132*/
133
Khalid Aziz839cb992013-05-16 19:44:13 -0600134static char *blogic_cmd_failure_reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
136/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600137 blogic_announce_drvr announces the Driver Version and Date, Author's
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 Name, Copyright Notice, and Electronic Mail Address.
139*/
140
Khalid Aziz839cb992013-05-16 19:44:13 -0600141static void blogic_announce_drvr(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
Khalid Aziz839cb992013-05-16 19:44:13 -0600143 blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
144 blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145}
146
147
148/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600149 blogic_drvr_info returns the Host Adapter Name to identify this SCSI
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 Driver and Host Adapter.
151*/
152
Khalid Aziz839cb992013-05-16 19:44:13 -0600153static const char *blogic_drvr_info(struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
Khalid Aziz839cb992013-05-16 19:44:13 -0600155 struct blogic_adapter *adapter =
156 (struct blogic_adapter *) host->hostdata;
157 return adapter->full_model;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158}
159
160/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600161 blogic_init_ccbs initializes a group of Command Control Blocks (CCBs)
162 for Host Adapter from the blk_size bytes located at blk_pointer. The newly
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 created CCBs are added to Host Adapter's free list.
164*/
165
Khalid Aziz839cb992013-05-16 19:44:13 -0600166static void blogic_init_ccbs(struct blogic_adapter *adapter, void *blk_pointer,
167 int blk_size, dma_addr_t blkp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
Khalid Aziz839cb992013-05-16 19:44:13 -0600169 struct blogic_ccb *ccb = (struct blogic_ccb *) blk_pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 unsigned int offset = 0;
Khalid Aziz839cb992013-05-16 19:44:13 -0600171 memset(blk_pointer, 0, blk_size);
172 ccb->allocgrp_head = blkp;
173 ccb->allocgrp_size = blk_size;
174 while ((blk_size -= sizeof(struct blogic_ccb)) >= 0) {
175 ccb->status = BLOGIC_CCB_FREE;
176 ccb->adapter = adapter;
177 ccb->dma_handle = (u32) blkp + offset;
178 if (blogic_flashpoint_type(adapter)) {
179 ccb->callback = blogic_qcompleted_ccb;
180 ccb->base_addr = adapter->fpinfo.base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600182 ccb->next = adapter->free_ccbs;
183 ccb->next_all = adapter->all_ccbs;
184 adapter->free_ccbs = ccb;
185 adapter->all_ccbs = ccb;
186 adapter->alloc_ccbs++;
187 ccb++;
188 offset += sizeof(struct blogic_ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 }
190}
191
192
193/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600194 blogic_create_initccbs allocates the initial CCBs for Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195*/
196
Khalid Aziz839cb992013-05-16 19:44:13 -0600197static bool __init blogic_create_initccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
Khalid Aziz839cb992013-05-16 19:44:13 -0600199 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
200 void *blk_pointer;
201 dma_addr_t blkp;
202
203 while (adapter->alloc_ccbs < adapter->initccbs) {
204 blk_pointer = pci_alloc_consistent(adapter->pci_device,
205 blk_size, &blkp);
206 if (blk_pointer == NULL) {
207 blogic_err("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
208 adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 return false;
210 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600211 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 }
213 return true;
214}
215
216
217/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600218 blogic_destroy_ccbs deallocates the CCBs for Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219*/
220
Khalid Aziz839cb992013-05-16 19:44:13 -0600221static void blogic_destroy_ccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222{
Khalid Aziz839cb992013-05-16 19:44:13 -0600223 struct blogic_ccb *next_ccb = adapter->all_ccbs, *ccb, *lastccb = NULL;
224 adapter->all_ccbs = NULL;
225 adapter->free_ccbs = NULL;
226 while ((ccb = next_ccb) != NULL) {
227 next_ccb = ccb->next_all;
228 if (ccb->allocgrp_head) {
229 if (lastccb)
230 pci_free_consistent(adapter->pci_device,
231 lastccb->allocgrp_size, lastccb,
232 lastccb->allocgrp_head);
233 lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 }
235 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600236 if (lastccb)
237 pci_free_consistent(adapter->pci_device, lastccb->allocgrp_size,
238 lastccb, lastccb->allocgrp_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
241
242/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600243 blogic_create_addlccbs allocates Additional CCBs for Host Adapter. If
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 allocation fails and there are no remaining CCBs available, the Driver Queue
245 Depth is decreased to a known safe value to avoid potential deadlocks when
246 multiple host adapters share the same IRQ Channel.
247*/
248
Khalid Aziz839cb992013-05-16 19:44:13 -0600249static void blogic_create_addlccbs(struct blogic_adapter *adapter,
250 int addl_ccbs, bool print_success)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251{
Khalid Aziz839cb992013-05-16 19:44:13 -0600252 int blk_size = BLOGIC_CCB_GRP_ALLOCSIZE * sizeof(struct blogic_ccb);
253 int prev_alloc = adapter->alloc_ccbs;
254 void *blk_pointer;
255 dma_addr_t blkp;
256 if (addl_ccbs <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 return;
Khalid Aziz839cb992013-05-16 19:44:13 -0600258 while (adapter->alloc_ccbs - prev_alloc < addl_ccbs) {
259 blk_pointer = pci_alloc_consistent(adapter->pci_device,
260 blk_size, &blkp);
261 if (blk_pointer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600263 blogic_init_ccbs(adapter, blk_pointer, blk_size, blkp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600265 if (adapter->alloc_ccbs > prev_alloc) {
266 if (print_success)
267 blogic_notice("Allocated %d additional CCBs (total now %d)\n", adapter, adapter->alloc_ccbs - prev_alloc, adapter->alloc_ccbs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 return;
269 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600270 blogic_notice("Failed to allocate additional CCBs\n", adapter);
271 if (adapter->drvr_qdepth > adapter->alloc_ccbs - adapter->tgt_count) {
272 adapter->drvr_qdepth = adapter->alloc_ccbs - adapter->tgt_count;
273 adapter->scsi_host->can_queue = adapter->drvr_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275}
276
277/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600278 blogic_alloc_ccb allocates a CCB from Host Adapter's free list,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 allocating more memory from the Kernel if necessary. The Host Adapter's
280 Lock should already have been acquired by the caller.
281*/
282
Khalid Aziz839cb992013-05-16 19:44:13 -0600283static struct blogic_ccb *blogic_alloc_ccb(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{
Khalid Aziz839cb992013-05-16 19:44:13 -0600285 static unsigned long serial;
286 struct blogic_ccb *ccb;
287 ccb = adapter->free_ccbs;
288 if (ccb != NULL) {
289 ccb->serial = ++serial;
290 adapter->free_ccbs = ccb->next;
291 ccb->next = NULL;
292 if (adapter->free_ccbs == NULL)
293 blogic_create_addlccbs(adapter, adapter->inc_ccbs,
294 true);
295 return ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600297 blogic_create_addlccbs(adapter, adapter->inc_ccbs, true);
298 ccb = adapter->free_ccbs;
299 if (ccb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 return NULL;
Khalid Aziz839cb992013-05-16 19:44:13 -0600301 ccb->serial = ++serial;
302 adapter->free_ccbs = ccb->next;
303 ccb->next = NULL;
304 return ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305}
306
307
308/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600309 blogic_dealloc_ccb deallocates a CCB, returning it to the Host Adapter's
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 free list. The Host Adapter's Lock should already have been acquired by the
311 caller.
312*/
313
Khalid Aziz839cb992013-05-16 19:44:13 -0600314static void blogic_dealloc_ccb(struct blogic_ccb *ccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
Khalid Aziz839cb992013-05-16 19:44:13 -0600316 struct blogic_adapter *adapter = ccb->adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Khalid Aziz839cb992013-05-16 19:44:13 -0600318 scsi_dma_unmap(ccb->command);
319 pci_unmap_single(adapter->pci_device, ccb->sensedata,
320 ccb->sense_datalen, PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Khalid Aziz839cb992013-05-16 19:44:13 -0600322 ccb->command = NULL;
323 ccb->status = BLOGIC_CCB_FREE;
324 ccb->next = adapter->free_ccbs;
325 adapter->free_ccbs = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326}
327
328
329/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600330 blogic_cmd sends the command opcode to adapter, optionally
331 providing paramlen bytes of param and receiving at most
332 replylen bytes of reply; any excess reply data is received but
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 discarded.
334
335 On success, this function returns the number of reply bytes read from
336 the Host Adapter (including any discarded data); on failure, it returns
337 -1 if the command was invalid, or -2 if a timeout occurred.
338
Khalid Aziz839cb992013-05-16 19:44:13 -0600339 blogic_cmd is called exclusively during host adapter detection and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 initialization, so performance and latency are not critical, and exclusive
341 access to the Host Adapter hardware is assumed. Once the host adapter and
342 driver are initialized, the only Host Adapter command that is issued is the
343 single byte Execute Mailbox Command operation code, which does not require
344 waiting for the Host Adapter Ready bit to be set in the Status Register.
345*/
346
Khalid Aziz839cb992013-05-16 19:44:13 -0600347static int blogic_cmd(struct blogic_adapter *adapter, enum blogic_opcode opcode,
348 void *param, int paramlen, void *reply, int replylen)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
Khalid Aziz839cb992013-05-16 19:44:13 -0600350 unsigned char *param_p = (unsigned char *) param;
351 unsigned char *reply_p = (unsigned char *) reply;
352 union blogic_stat_reg statusreg;
353 union blogic_int_reg intreg;
354 unsigned long processor_flag = 0;
355 int reply_b = 0, result;
356 long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /*
358 Clear out the Reply Data if provided.
359 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600360 if (replylen > 0)
361 memset(reply, 0, replylen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600363 If the IRQ Channel has not yet been acquired, then interrupts
364 must be disabled while issuing host adapter commands since a
365 Command Complete interrupt could occur if the IRQ Channel was
366 previously enabled by another BusLogic Host Adapter or another
367 driver sharing the same IRQ Channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600369 if (!adapter->irq_acquired)
370 local_irq_save(processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600372 Wait for the Host Adapter Ready bit to be set and the
373 Command/Parameter Register Busy bit to be reset in the Status
374 Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600376 timeout = 10000;
377 while (--timeout >= 0) {
378 statusreg.all = blogic_rdstatus(adapter);
379 if (statusreg.sr.adapter_ready && !statusreg.sr.cmd_param_busy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 break;
381 udelay(100);
382 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600383 if (timeout < 0) {
384 blogic_cmd_failure_reason =
385 "Timeout waiting for Host Adapter Ready";
386 result = -2;
387 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
389 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600390 Write the opcode to the Command/Parameter Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600392 adapter->adapter_cmd_complete = false;
393 blogic_setcmdparam(adapter, opcode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 /*
395 Write any additional Parameter Bytes.
396 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600397 timeout = 10000;
398 while (paramlen > 0 && --timeout >= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600400 Wait 100 microseconds to give the Host Adapter enough
401 time to determine whether the last value written to the
402 Command/Parameter Register was valid or not. If the
403 Command Complete bit is set in the Interrupt Register,
404 then the Command Invalid bit in the Status Register will
405 be reset if the Operation Code or Parameter was valid
406 and the command has completed, or set if the Operation
407 Code or Parameter was invalid. If the Data In Register
408 Ready bit is set in the Status Register, then the
409 Operation Code was valid, and data is waiting to be read
410 back from the Host Adapter. Otherwise, wait for the
411 Command/Parameter Register Busy bit in the Status
412 Register to be reset.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 */
414 udelay(100);
Khalid Aziz839cb992013-05-16 19:44:13 -0600415 intreg.all = blogic_rdint(adapter);
416 statusreg.all = blogic_rdstatus(adapter);
417 if (intreg.ir.cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600419 if (adapter->adapter_cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600421 if (statusreg.sr.datain_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600423 if (statusreg.sr.cmd_param_busy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -0600425 blogic_setcmdparam(adapter, *param_p++);
426 paramlen--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600428 if (timeout < 0) {
429 blogic_cmd_failure_reason =
430 "Timeout waiting for Parameter Acceptance";
431 result = -2;
432 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 }
434 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600435 The Modify I/O Address command does not cause a Command Complete
436 Interrupt.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600438 if (opcode == BLOGIC_MOD_IOADDR) {
439 statusreg.all = blogic_rdstatus(adapter);
440 if (statusreg.sr.cmd_invalid) {
441 blogic_cmd_failure_reason =
442 "Modify I/O Address Invalid";
443 result = -1;
444 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600446 if (blogic_global_options.trace_config)
447 blogic_notice("blogic_cmd(%02X) Status = %02X: " "(Modify I/O Address)\n", adapter, opcode, statusreg.all);
448 result = 0;
449 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
451 /*
452 Select an appropriate timeout value for awaiting command completion.
453 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600454 switch (opcode) {
455 case BLOGIC_INQ_DEV0TO7:
456 case BLOGIC_INQ_DEV8TO15:
457 case BLOGIC_INQ_DEV:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 /* Approximately 60 seconds. */
Khalid Aziz839cb992013-05-16 19:44:13 -0600459 timeout = 60 * 10000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 break;
461 default:
462 /* Approximately 1 second. */
Khalid Aziz839cb992013-05-16 19:44:13 -0600463 timeout = 10000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 break;
465 }
466 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600467 Receive any Reply Bytes, waiting for either the Command
468 Complete bit to be set in the Interrupt Register, or for the
469 Interrupt Handler to set the Host Adapter Command Completed
470 bit in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600472 while (--timeout >= 0) {
473 intreg.all = blogic_rdint(adapter);
474 statusreg.all = blogic_rdstatus(adapter);
475 if (intreg.ir.cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600477 if (adapter->adapter_cmd_complete)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 break;
Khalid Aziz839cb992013-05-16 19:44:13 -0600479 if (statusreg.sr.datain_ready) {
480 if (++reply_b <= replylen)
481 *reply_p++ = blogic_rddatain(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 else
Khalid Aziz839cb992013-05-16 19:44:13 -0600483 blogic_rddatain(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600485 if (opcode == BLOGIC_FETCH_LOCALRAM &&
486 statusreg.sr.adapter_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 break;
488 udelay(100);
489 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600490 if (timeout < 0) {
491 blogic_cmd_failure_reason =
492 "Timeout waiting for Command Complete";
493 result = -2;
494 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 }
496 /*
497 Clear any pending Command Complete Interrupt.
498 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600499 blogic_intreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 /*
501 Provide tracing information if requested.
502 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600503 if (blogic_global_options.trace_config) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -0600505 blogic_notice("blogic_cmd(%02X) Status = %02X: %2d ==> %2d:",
506 adapter, opcode, statusreg.all, replylen,
507 reply_b);
508 if (replylen > reply_b)
509 replylen = reply_b;
510 for (i = 0; i < replylen; i++)
511 blogic_notice(" %02X", adapter,
512 ((unsigned char *) reply)[i]);
513 blogic_notice("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 }
515 /*
516 Process Command Invalid conditions.
517 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600518 if (statusreg.sr.cmd_invalid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600520 Some early BusLogic Host Adapters may not recover
521 properly from a Command Invalid condition, so if this
522 appears to be the case, a Soft Reset is issued to the
523 Host Adapter. Potentially invalid commands are never
524 attempted after Mailbox Initialization is performed,
525 so there should be no Host Adapter state lost by a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 Soft Reset in response to a Command Invalid condition.
527 */
528 udelay(1000);
Khalid Aziz839cb992013-05-16 19:44:13 -0600529 statusreg.all = blogic_rdstatus(adapter);
530 if (statusreg.sr.cmd_invalid || statusreg.sr.rsvd ||
531 statusreg.sr.datain_ready ||
532 statusreg.sr.cmd_param_busy ||
533 !statusreg.sr.adapter_ready ||
534 !statusreg.sr.init_reqd ||
535 statusreg.sr.diag_active ||
536 statusreg.sr.diag_failed) {
537 blogic_softreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 udelay(1000);
539 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600540 blogic_cmd_failure_reason = "Command Invalid";
541 result = -1;
542 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544 /*
545 Handle Excess Parameters Supplied conditions.
546 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600547 if (paramlen > 0) {
548 blogic_cmd_failure_reason = "Excess Parameters Supplied";
549 result = -1;
550 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552 /*
553 Indicate the command completed successfully.
554 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600555 blogic_cmd_failure_reason = NULL;
556 result = reply_b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 /*
558 Restore the interrupt status if necessary and return.
559 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600560done:
561 if (!adapter->irq_acquired)
562 local_irq_restore(processor_flag);
563 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
566
567/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600568 blogic_add_probeaddr_isa appends a single ISA I/O Address to the list
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 of I/O Address and Bus Probe Information to be checked for potential BusLogic
570 Host Adapters.
571*/
572
Khalid Aziz839cb992013-05-16 19:44:13 -0600573static void __init blogic_add_probeaddr_isa(unsigned long io_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
Khalid Aziz839cb992013-05-16 19:44:13 -0600575 struct blogic_probeinfo *probeinfo;
576 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 return;
Khalid Aziz839cb992013-05-16 19:44:13 -0600578 probeinfo = &blogic_probeinfo_list[blogic_probeinfo_count++];
579 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
580 probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
581 probeinfo->io_addr = io_addr;
582 probeinfo->pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583}
584
585
586/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600587 blogic_init_probeinfo_isa initializes the list of I/O Address and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
589 only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
590*/
591
Khalid Aziz839cb992013-05-16 19:44:13 -0600592static void __init blogic_init_probeinfo_isa(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600595 If BusLogic Driver Options specifications requested that ISA
596 Bus Probes be inhibited, do not proceed further.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600598 if (blogic_probe_options.noprobe_isa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 return;
600 /*
601 Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
602 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600603 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe330)
604 blogic_add_probeaddr_isa(0x330);
605 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe334)
606 blogic_add_probeaddr_isa(0x334);
607 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe230)
608 blogic_add_probeaddr_isa(0x230);
609 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe234)
610 blogic_add_probeaddr_isa(0x234);
611 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe130)
612 blogic_add_probeaddr_isa(0x130);
613 if (!blogic_probe_options.limited_isa || blogic_probe_options.probe134)
614 blogic_add_probeaddr_isa(0x134);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615}
616
617
618#ifdef CONFIG_PCI
619
620
621/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600622 blogic_sort_probeinfo sorts a section of blogic_probeinfo_list in order
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 of increasing PCI Bus and Device Number.
624*/
625
Khalid Aziz839cb992013-05-16 19:44:13 -0600626static void __init blogic_sort_probeinfo(struct blogic_probeinfo
627 *probeinfo_list, int probeinfo_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
Khalid Aziz839cb992013-05-16 19:44:13 -0600629 int last_exchange = probeinfo_cnt - 1, bound, j;
630
631 while (last_exchange > 0) {
632 bound = last_exchange;
633 last_exchange = 0;
634 for (j = 0; j < bound; j++) {
635 struct blogic_probeinfo *probeinfo1 =
636 &probeinfo_list[j];
637 struct blogic_probeinfo *probeinfo2 =
638 &probeinfo_list[j + 1];
639 if (probeinfo1->bus > probeinfo2->bus ||
640 (probeinfo1->bus == probeinfo2->bus &&
641 (probeinfo1->dev > probeinfo2->dev))) {
642 struct blogic_probeinfo tmp_probeinfo;
643
644 memcpy(&tmp_probeinfo, probeinfo1,
645 sizeof(struct blogic_probeinfo));
646 memcpy(probeinfo1, probeinfo2,
647 sizeof(struct blogic_probeinfo));
648 memcpy(probeinfo2, &tmp_probeinfo,
649 sizeof(struct blogic_probeinfo));
650 last_exchange = j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652 }
653 }
654}
655
656
657/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600658 blogic_init_mm_probeinfo initializes the list of I/O Address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 and Bus Probe Information to be checked for potential BusLogic MultiMaster
660 SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
661 machines as well as from the list of standard BusLogic MultiMaster ISA
662 I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
663*/
664
Khalid Aziz839cb992013-05-16 19:44:13 -0600665static int __init blogic_init_mm_probeinfo(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
Khalid Aziz839cb992013-05-16 19:44:13 -0600667 struct blogic_probeinfo *pr_probeinfo =
668 &blogic_probeinfo_list[blogic_probeinfo_count];
669 int nonpr_mmindex = blogic_probeinfo_count + 1;
670 int nonpr_mmcount = 0, mmcount = 0;
671 bool force_scan_order = false;
672 bool force_scan_order_checked = false;
673 bool addr_seen[6];
674 struct pci_dev *pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -0600676 if (blogic_probeinfo_count >= BLOGIC_MAX_ADAPTERS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 return 0;
Khalid Aziz839cb992013-05-16 19:44:13 -0600678 blogic_probeinfo_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 for (i = 0; i < 6; i++)
Khalid Aziz839cb992013-05-16 19:44:13 -0600680 addr_seen[i] = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600682 Iterate over the MultiMaster PCI Host Adapters. For each
683 enumerated host adapter, determine whether its ISA Compatible
684 I/O Port is enabled and if so, whether it is assigned the
685 Primary I/O Address. A host adapter that is assigned the
686 Primary I/O Address will always be the preferred boot device.
687 The MultiMaster BIOS will first recognize a host adapter at
688 the Primary I/O Address, then any other PCI host adapters,
689 and finally any host adapters located at the remaining
690 standard ISA I/O Addresses. When a PCI host adapter is found
691 with its ISA Compatible I/O Port enabled, a command is issued
692 to disable the ISA Compatible I/O Port, and it is noted that the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 particular standard ISA I/O Address need not be probed.
694 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600695 pr_probeinfo->io_addr = 0;
696 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
697 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
698 pci_device)) != NULL) {
699 struct blogic_adapter *adapter = adapter;
700 struct blogic_adapter_info adapter_info;
701 enum blogic_isa_ioport mod_ioaddr_req;
702 unsigned char bus;
703 unsigned char device;
704 unsigned int irq_ch;
705 unsigned long base_addr0;
706 unsigned long base_addr1;
707 unsigned long io_addr;
708 unsigned long pci_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Khalid Aziz839cb992013-05-16 19:44:13 -0600710 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 continue;
712
Khalid Aziz839cb992013-05-16 19:44:13 -0600713 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 continue;
715
Khalid Aziz839cb992013-05-16 19:44:13 -0600716 bus = pci_device->bus->number;
717 device = pci_device->devfn >> 3;
718 irq_ch = pci_device->irq;
719 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
720 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Khalid Aziz839cb992013-05-16 19:44:13 -0600722 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
723 blogic_err("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, base_addr0);
724 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 continue;
726 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600727 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
728 blogic_err("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, base_addr1);
729 blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 continue;
731 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600732 if (irq_ch == 0) {
733 blogic_err("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, irq_ch);
734 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 continue;
736 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600737 if (blogic_global_options.trace_probe) {
738 blogic_notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
739 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 }
741 /*
742 Issue the Inquire PCI Host Adapter Information command to determine
743 the ISA Compatible I/O Port. If the ISA Compatible I/O Port is
744 known and enabled, note that the particular Standard ISA I/O
745 Address should not be probed.
746 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600747 adapter->io_addr = io_addr;
748 blogic_intreset(adapter);
749 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
750 &adapter_info, sizeof(adapter_info)) ==
751 sizeof(adapter_info)) {
752 if (adapter_info.isa_port < 6)
753 addr_seen[adapter_info.isa_port] = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 } else
Khalid Aziz839cb992013-05-16 19:44:13 -0600755 adapter_info.isa_port = BLOGIC_IO_DISABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600757 Issue the Modify I/O Address command to disable the
758 ISA Compatible I/O Port. On PCI Host Adapters, the
759 Modify I/O Address command allows modification of the
760 ISA compatible I/O Address that the Host Adapter
761 responds to; it does not affect the PCI compliant
762 I/O Address assigned at system initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600764 mod_ioaddr_req = BLOGIC_IO_DISABLE;
765 blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
766 sizeof(mod_ioaddr_req), NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600768 For the first MultiMaster Host Adapter enumerated,
769 issue the Fetch Host Adapter Local RAM command to read
770 byte 45 of the AutoSCSI area, for the setting of the
771 "Use Bus And Device # For PCI Scanning Seq." option.
772 Issue the Inquire Board ID command since this option is
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 only valid for the BT-948/958/958D.
774 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600775 if (!force_scan_order_checked) {
776 struct blogic_fetch_localram fetch_localram;
777 struct blogic_autoscsi_byte45 autoscsi_byte45;
778 struct blogic_board_id id;
779
780 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
781 fetch_localram.count = sizeof(autoscsi_byte45);
782 blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM,
783 &fetch_localram, sizeof(fetch_localram),
784 &autoscsi_byte45,
785 sizeof(autoscsi_byte45));
786 blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
787 sizeof(id));
788 if (id.fw_ver_digit1 == '5')
789 force_scan_order =
790 autoscsi_byte45.force_scan_order;
791 force_scan_order_checked = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 }
793 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600794 Determine whether this MultiMaster Host Adapter has its
795 ISA Compatible I/O Port enabled and is assigned the
796 Primary I/O Address. If it does, then it is the Primary
797 MultiMaster Host Adapter and must be recognized first.
798 If it does not, then it is added to the list for probing
799 after any Primary MultiMaster Host Adapter is probed.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600801 if (adapter_info.isa_port == BLOGIC_IO_330) {
802 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
803 pr_probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
804 pr_probeinfo->io_addr = io_addr;
805 pr_probeinfo->pci_addr = pci_addr;
806 pr_probeinfo->bus = bus;
807 pr_probeinfo->dev = device;
808 pr_probeinfo->irq_ch = irq_ch;
809 pr_probeinfo->pci_device = pci_dev_get(pci_device);
810 mmcount++;
811 } else if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
812 struct blogic_probeinfo *probeinfo =
813 &blogic_probeinfo_list[blogic_probeinfo_count++];
814 probeinfo->adapter_type = BLOGIC_MULTIMASTER;
815 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
816 probeinfo->io_addr = io_addr;
817 probeinfo->pci_addr = pci_addr;
818 probeinfo->bus = bus;
819 probeinfo->dev = device;
820 probeinfo->irq_ch = irq_ch;
821 probeinfo->pci_device = pci_dev_get(pci_device);
822 nonpr_mmcount++;
823 mmcount++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 } else
Khalid Aziz839cb992013-05-16 19:44:13 -0600825 blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 }
827 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600828 If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq."
829 option is ON for the first enumerated MultiMaster Host Adapter,
830 and if that host adapter is a BT-948/958/958D, then the
831 MultiMaster BIOS will recognize MultiMaster Host Adapters in
832 the order of increasing PCI Bus and Device Number. In that case,
833 sort the probe information into the same order the BIOS uses.
834 If this option is OFF, then the MultiMaster BIOS will recognize
835 MultiMaster Host Adapters in the order they are enumerated by
836 the PCI BIOS, and hence no sorting is necessary.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600838 if (force_scan_order)
839 blogic_sort_probeinfo(&blogic_probeinfo_list[nonpr_mmindex],
840 nonpr_mmcount);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 /*
Khalid Aziz839cb992013-05-16 19:44:13 -0600842 If no PCI MultiMaster Host Adapter is assigned the Primary
843 I/O Address, then the Primary I/O Address must be probed
844 explicitly before any PCI host adapters are probed.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600846 if (!blogic_probe_options.noprobe_isa)
847 if (pr_probeinfo->io_addr == 0 &&
848 (!blogic_probe_options.limited_isa ||
849 blogic_probe_options.probe330)) {
850 pr_probeinfo->adapter_type = BLOGIC_MULTIMASTER;
851 pr_probeinfo->adapter_bus_type = BLOGIC_ISA_BUS;
852 pr_probeinfo->io_addr = 0x330;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
854 /*
855 Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
856 omitting the Primary I/O Address which has already been handled.
857 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600858 if (!blogic_probe_options.noprobe_isa) {
859 if (!addr_seen[1] &&
860 (!blogic_probe_options.limited_isa ||
861 blogic_probe_options.probe334))
862 blogic_add_probeaddr_isa(0x334);
863 if (!addr_seen[2] &&
864 (!blogic_probe_options.limited_isa ||
865 blogic_probe_options.probe230))
866 blogic_add_probeaddr_isa(0x230);
867 if (!addr_seen[3] &&
868 (!blogic_probe_options.limited_isa ||
869 blogic_probe_options.probe234))
870 blogic_add_probeaddr_isa(0x234);
871 if (!addr_seen[4] &&
872 (!blogic_probe_options.limited_isa ||
873 blogic_probe_options.probe130))
874 blogic_add_probeaddr_isa(0x130);
875 if (!addr_seen[5] &&
876 (!blogic_probe_options.limited_isa ||
877 blogic_probe_options.probe134))
878 blogic_add_probeaddr_isa(0x134);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 }
880 /*
881 Iterate over the older non-compliant MultiMaster PCI Host Adapters,
882 noting the PCI bus location and assigned IRQ Channel.
883 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600884 pci_device = NULL;
885 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
886 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
887 pci_device)) != NULL) {
888 unsigned char bus;
889 unsigned char device;
890 unsigned int irq_ch;
891 unsigned long io_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Khalid Aziz839cb992013-05-16 19:44:13 -0600893 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 continue;
895
Khalid Aziz839cb992013-05-16 19:44:13 -0600896 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 continue;
898
Khalid Aziz839cb992013-05-16 19:44:13 -0600899 bus = pci_device->bus->number;
900 device = pci_device->devfn >> 3;
901 irq_ch = pci_device->irq;
902 io_addr = pci_resource_start(pci_device, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
Khalid Aziz839cb992013-05-16 19:44:13 -0600904 if (io_addr == 0 || irq_ch == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -0600906 for (i = 0; i < blogic_probeinfo_count; i++) {
907 struct blogic_probeinfo *probeinfo =
908 &blogic_probeinfo_list[i];
909 if (probeinfo->io_addr == io_addr &&
910 probeinfo->adapter_type == BLOGIC_MULTIMASTER) {
911 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
912 probeinfo->pci_addr = 0;
913 probeinfo->bus = bus;
914 probeinfo->dev = device;
915 probeinfo->irq_ch = irq_ch;
916 probeinfo->pci_device = pci_dev_get(pci_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 break;
918 }
919 }
920 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600921 return mmcount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922}
923
924
925/*
Khalid Aziz839cb992013-05-16 19:44:13 -0600926 blogic_init_fp_probeinfo initializes the list of I/O Address
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 and Bus Probe Information to be checked for potential BusLogic FlashPoint
928 Host Adapters by interrogating the PCI Configuration Space. It returns the
929 number of FlashPoint Host Adapters found.
930*/
931
Khalid Aziz839cb992013-05-16 19:44:13 -0600932static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Khalid Aziz839cb992013-05-16 19:44:13 -0600934 int fpindex = blogic_probeinfo_count, fpcount = 0;
935 struct pci_dev *pci_device = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 /*
937 Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
938 */
Khalid Aziz839cb992013-05-16 19:44:13 -0600939 while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
940 PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
941 pci_device)) != NULL) {
942 unsigned char bus;
943 unsigned char device;
944 unsigned int irq_ch;
945 unsigned long base_addr0;
946 unsigned long base_addr1;
947 unsigned long io_addr;
948 unsigned long pci_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Khalid Aziz839cb992013-05-16 19:44:13 -0600950 if (pci_enable_device(pci_device))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 continue;
952
Khalid Aziz839cb992013-05-16 19:44:13 -0600953 if (pci_set_dma_mask(pci_device, DMA_BIT_MASK(32)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 continue;
955
Khalid Aziz839cb992013-05-16 19:44:13 -0600956 bus = pci_device->bus->number;
957 device = pci_device->devfn >> 3;
958 irq_ch = pci_device->irq;
959 io_addr = base_addr0 = pci_resource_start(pci_device, 0);
960 pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
Matthew Wilcox78b4b052008-03-13 06:55:08 -0600961#ifdef CONFIG_SCSI_FLASHPOINT
Khalid Aziz839cb992013-05-16 19:44:13 -0600962 if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
963 blogic_err("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, base_addr0);
964 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 continue;
966 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600967 if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
968 blogic_err("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, base_addr1);
969 blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 continue;
971 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600972 if (irq_ch == 0) {
973 blogic_err("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, irq_ch);
974 blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 continue;
976 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600977 if (blogic_global_options.trace_probe) {
978 blogic_notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
979 blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 }
Khalid Aziz839cb992013-05-16 19:44:13 -0600981 if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
982 struct blogic_probeinfo *probeinfo =
983 &blogic_probeinfo_list[blogic_probeinfo_count++];
984 probeinfo->adapter_type = BLOGIC_FLASHPOINT;
985 probeinfo->adapter_bus_type = BLOGIC_PCI_BUS;
986 probeinfo->io_addr = io_addr;
987 probeinfo->pci_addr = pci_addr;
988 probeinfo->bus = bus;
989 probeinfo->dev = device;
990 probeinfo->irq_ch = irq_ch;
991 probeinfo->pci_device = pci_dev_get(pci_device);
992 fpcount++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 } else
Khalid Aziz839cb992013-05-16 19:44:13 -0600994 blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995#else
Khalid Aziz839cb992013-05-16 19:44:13 -0600996 blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, bus, device);
997 blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
998 blogic_err("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999#endif
1000 }
1001 /*
1002 The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
1003 increasing PCI Bus and Device Number, so sort the probe information into
1004 the same order the BIOS uses.
1005 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001006 blogic_sort_probeinfo(&blogic_probeinfo_list[fpindex], fpcount);
1007 return fpcount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008}
1009
1010
1011/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001012 blogic_init_probeinfo_list initializes the list of I/O Address and Bus
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 Probe Information to be checked for potential BusLogic SCSI Host Adapters by
1014 interrogating the PCI Configuration Space on PCI machines as well as from the
1015 list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
1016 FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
1017 probe for FlashPoint Host Adapters first unless the BIOS primary disk is
1018 controlled by the first PCI MultiMaster Host Adapter, in which case
1019 MultiMaster Host Adapters will be probed first. The BusLogic Driver Options
1020 specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
1021 a particular probe order.
1022*/
1023
Khalid Aziz839cb992013-05-16 19:44:13 -06001024static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025{
1026 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001027 If a PCI BIOS is present, interrogate it for MultiMaster and
1028 FlashPoint Host Adapters; otherwise, default to the standard
1029 ISA MultiMaster probe.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001031 if (!blogic_probe_options.noprobe_pci) {
1032 if (blogic_probe_options.multimaster_first) {
1033 blogic_init_mm_probeinfo(adapter);
1034 blogic_init_fp_probeinfo(adapter);
1035 } else if (blogic_probe_options.flashpoint_first) {
1036 blogic_init_fp_probeinfo(adapter);
1037 blogic_init_mm_probeinfo(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001039 int fpcount = blogic_init_fp_probeinfo(adapter);
1040 int mmcount = blogic_init_mm_probeinfo(adapter);
1041 if (fpcount > 0 && mmcount > 0) {
1042 struct blogic_probeinfo *probeinfo =
1043 &blogic_probeinfo_list[fpcount];
1044 struct blogic_adapter *myadapter = adapter;
1045 struct blogic_fetch_localram fetch_localram;
1046 struct blogic_bios_drvmap d0_mapbyte;
1047
1048 while (probeinfo->adapter_bus_type !=
1049 BLOGIC_PCI_BUS)
1050 probeinfo++;
1051 myadapter->io_addr = probeinfo->io_addr;
1052 fetch_localram.offset =
1053 BLOGIC_BIOS_BASE + BLOGIC_BIOS_DRVMAP;
1054 fetch_localram.count = sizeof(d0_mapbyte);
1055 blogic_cmd(myadapter, BLOGIC_FETCH_LOCALRAM,
1056 &fetch_localram,
1057 sizeof(fetch_localram),
1058 &d0_mapbyte,
1059 sizeof(d0_mapbyte));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001061 If the Map Byte for BIOS Drive 0 indicates
1062 that BIOS Drive 0 is controlled by this
1063 PCI MultiMaster Host Adapter, then reverse
1064 the probe order so that MultiMaster Host
1065 Adapters are probed before FlashPoint Host
1066 Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001068 if (d0_mapbyte.diskgeom != BLOGIC_BIOS_NODISK) {
1069 struct blogic_probeinfo saved_probeinfo[BLOGIC_MAX_ADAPTERS];
1070 int mmcount = blogic_probeinfo_count - fpcount;
1071
1072 memcpy(saved_probeinfo,
1073 blogic_probeinfo_list,
1074 blogic_probeinfo_count * sizeof(struct blogic_probeinfo));
1075 memcpy(&blogic_probeinfo_list[0],
1076 &saved_probeinfo[fpcount],
1077 mmcount * sizeof(struct blogic_probeinfo));
1078 memcpy(&blogic_probeinfo_list[mmcount],
1079 &saved_probeinfo[0],
1080 fpcount * sizeof(struct blogic_probeinfo));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 }
1082 }
1083 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001084 } else {
1085 blogic_init_probeinfo_isa(adapter);
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087}
1088
1089
Matthew Wilcox78b4b052008-03-13 06:55:08 -06001090#else
Khalid Aziz839cb992013-05-16 19:44:13 -06001091#define blogic_init_probeinfo_list(adapter) \
1092 blogic_init_probeinfo_isa(adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093#endif /* CONFIG_PCI */
1094
1095
1096/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001097 blogic_failure prints a standardized error message, and then returns false.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098*/
1099
Khalid Aziz839cb992013-05-16 19:44:13 -06001100static bool blogic_failure(struct blogic_adapter *adapter, char *msg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
Khalid Aziz839cb992013-05-16 19:44:13 -06001102 blogic_announce_drvr(adapter);
1103 if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
1104 blogic_err("While configuring BusLogic PCI Host Adapter at\n",
1105 adapter);
1106 blogic_err("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001108 blogic_err("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", adapter, adapter->io_addr);
1109 blogic_err("%s FAILED - DETACHING\n", adapter, msg);
1110 if (blogic_cmd_failure_reason != NULL)
1111 blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
1112 blogic_cmd_failure_reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 return false;
1114}
1115
1116
1117/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001118 blogic_probe probes for a BusLogic Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119*/
1120
Khalid Aziz839cb992013-05-16 19:44:13 -06001121static bool __init blogic_probe(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122{
Khalid Aziz839cb992013-05-16 19:44:13 -06001123 union blogic_stat_reg statusreg;
1124 union blogic_int_reg intreg;
1125 union blogic_geo_reg georeg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 /*
1127 FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
1128 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001129 if (blogic_flashpoint_type(adapter)) {
1130 struct fpoint_info *fpinfo = &adapter->fpinfo;
1131 fpinfo->base_addr = (u32) adapter->io_addr;
1132 fpinfo->irq_ch = adapter->irq_ch;
1133 fpinfo->present = false;
1134 if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
1135 fpinfo->present)) {
1136 blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
1137 blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
1138 blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 return false;
1140 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001141 if (blogic_global_options.trace_probe)
1142 blogic_notice("BusLogic_Probe(0x%X): FlashPoint Found\n", adapter, adapter->io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 /*
1144 Indicate the Host Adapter Probe completed successfully.
1145 */
1146 return true;
1147 }
1148 /*
1149 Read the Status, Interrupt, and Geometry Registers to test if there are I/O
1150 ports that respond, and to check the values to determine if they are from a
1151 BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which
1152 case there is definitely no BusLogic Host Adapter at this base I/O Address.
1153 The test here is a subset of that used by the BusLogic Host Adapter BIOS.
1154 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001155 statusreg.all = blogic_rdstatus(adapter);
1156 intreg.all = blogic_rdint(adapter);
1157 georeg.all = blogic_rdgeom(adapter);
1158 if (blogic_global_options.trace_probe)
1159 blogic_notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
1160 if (statusreg.all == 0 || statusreg.sr.diag_active ||
1161 statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
1162 statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return false;
1164 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001165 Check the undocumented Geometry Register to test if there is
1166 an I/O port that responded. Adaptec Host Adapters do not
1167 implement the Geometry Register, so this test helps serve to
1168 avoid incorrectly recognizing an Adaptec 1542A or 1542B as a
1169 BusLogic. Unfortunately, the Adaptec 1542C series does respond
1170 to the Geometry Register I/O port, but it will be rejected
1171 later when the Inquire Extended Setup Information command is
1172 issued in blogic_checkadapter. The AMI FastDisk Host Adapter
1173 is a BusLogic clone that implements the same interface as
1174 earlier BusLogic Host Adapters, including the undocumented
1175 commands, and is therefore supported by this driver. However,
1176 the AMI FastDisk always returns 0x00 upon reading the Geometry
1177 Register, so the extended translation option should always be
1178 left disabled on the AMI FastDisk.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001180 if (georeg.all == 0xFF)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 return false;
1182 /*
1183 Indicate the Host Adapter Probe completed successfully.
1184 */
1185 return true;
1186}
1187
1188
1189/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001190 blogic_hwreset issues a Hardware Reset to the Host Adapter
1191 and waits for Host Adapter Diagnostics to complete. If hard_reset is true, a
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
1193 Soft Reset is performed which only resets the Host Adapter without forcing a
1194 SCSI Bus Reset.
1195*/
1196
Khalid Aziz839cb992013-05-16 19:44:13 -06001197static bool blogic_hwreset(struct blogic_adapter *adapter, bool hard_reset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198{
Khalid Aziz839cb992013-05-16 19:44:13 -06001199 union blogic_stat_reg statusreg;
1200 int timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001202 FlashPoint Host Adapters are Hard Reset by the FlashPoint
1203 SCCB Manager.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001205 if (blogic_flashpoint_type(adapter)) {
1206 struct fpoint_info *fpinfo = &adapter->fpinfo;
1207 fpinfo->softreset = !hard_reset;
1208 fpinfo->report_underrun = true;
1209 adapter->cardhandle =
1210 FlashPoint_HardwareResetHostAdapter(fpinfo);
1211 if (adapter->cardhandle == FPOINT_BADCARD_HANDLE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return false;
1213 /*
1214 Indicate the Host Adapter Hard Reset completed successfully.
1215 */
1216 return true;
1217 }
1218 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001219 Issue a Hard Reset or Soft Reset Command to the Host Adapter.
1220 The Host Adapter should respond by setting Diagnostic Active in
1221 the Status Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001223 if (hard_reset)
1224 blogic_hardreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001226 blogic_softreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 /*
1228 Wait until Diagnostic Active is set in the Status Register.
1229 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001230 timeout = 5 * 10000;
1231 while (--timeout >= 0) {
1232 statusreg.all = blogic_rdstatus(adapter);
1233 if (statusreg.sr.diag_active)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 break;
1235 udelay(100);
1236 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001237 if (blogic_global_options.trace_hw_reset)
1238 blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1239 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 return false;
1241 /*
1242 Wait 100 microseconds to allow completion of any initial diagnostic
1243 activity which might leave the contents of the Status Register
1244 unpredictable.
1245 */
1246 udelay(100);
1247 /*
1248 Wait until Diagnostic Active is reset in the Status Register.
1249 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001250 timeout = 10 * 10000;
1251 while (--timeout >= 0) {
1252 statusreg.all = blogic_rdstatus(adapter);
1253 if (!statusreg.sr.diag_active)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 break;
1255 udelay(100);
1256 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001257 if (blogic_global_options.trace_hw_reset)
1258 blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1259 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 return false;
1261 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001262 Wait until at least one of the Diagnostic Failure, Host Adapter
1263 Ready, or Data In Register Ready bits is set in the Status Register.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001265 timeout = 10000;
1266 while (--timeout >= 0) {
1267 statusreg.all = blogic_rdstatus(adapter);
1268 if (statusreg.sr.diag_failed || statusreg.sr.adapter_ready ||
1269 statusreg.sr.datain_ready)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 break;
1271 udelay(100);
1272 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001273 if (blogic_global_options.trace_hw_reset)
1274 blogic_notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
1275 if (timeout < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return false;
1277 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001278 If Diagnostic Failure is set or Host Adapter Ready is reset,
1279 then an error occurred during the Host Adapter diagnostics.
1280 If Data In Register Ready is set, then there is an Error Code
1281 available.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001283 if (statusreg.sr.diag_failed || !statusreg.sr.adapter_ready) {
1284 blogic_cmd_failure_reason = NULL;
1285 blogic_failure(adapter, "HARD RESET DIAGNOSTICS");
1286 blogic_err("HOST ADAPTER STATUS REGISTER = %02X\n", adapter,
1287 statusreg.all);
1288 if (statusreg.sr.datain_ready)
1289 blogic_err("HOST ADAPTER ERROR CODE = %d\n", adapter,
1290 blogic_rddatain(adapter));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return false;
1292 }
1293 /*
1294 Indicate the Host Adapter Hard Reset completed successfully.
1295 */
1296 return true;
1297}
1298
1299
1300/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001301 blogic_checkadapter checks to be sure this really is a BusLogic
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 Host Adapter.
1303*/
1304
Khalid Aziz839cb992013-05-16 19:44:13 -06001305static bool __init blogic_checkadapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
Khalid Aziz839cb992013-05-16 19:44:13 -06001307 struct blogic_ext_setup ext_setupinfo;
1308 unsigned char req_replylen;
1309 bool result = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 /*
1311 FlashPoint Host Adapters do not require this protection.
1312 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001313 if (blogic_flashpoint_type(adapter))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 return true;
1315 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001316 Issue the Inquire Extended Setup Information command. Only genuine
1317 BusLogic Host Adapters and true clones support this command.
1318 Adaptec 1542C series Host Adapters that respond to the Geometry
1319 Register I/O port will fail this command.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001321 req_replylen = sizeof(ext_setupinfo);
1322 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1323 sizeof(req_replylen), &ext_setupinfo,
1324 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1325 result = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 /*
1327 Provide tracing information if requested and return.
1328 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001329 if (blogic_global_options.trace_probe)
1330 blogic_notice("BusLogic_Check(0x%X): MultiMaster %s\n", adapter,
1331 adapter->io_addr,
1332 (result ? "Found" : "Not Found"));
1333 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334}
1335
1336
1337/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001338 blogic_rdconfig reads the Configuration Information
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 from Host Adapter and initializes the Host Adapter structure.
1340*/
1341
Khalid Aziz839cb992013-05-16 19:44:13 -06001342static bool __init blogic_rdconfig(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343{
Khalid Aziz839cb992013-05-16 19:44:13 -06001344 struct blogic_board_id id;
1345 struct blogic_config config;
1346 struct blogic_setup_info setupinfo;
1347 struct blogic_ext_setup ext_setupinfo;
1348 unsigned char model[5];
1349 unsigned char fw_ver_digit3;
1350 unsigned char fw_ver_letter;
1351 struct blogic_adapter_info adapter_info;
1352 struct blogic_fetch_localram fetch_localram;
1353 struct blogic_autoscsi autoscsi;
1354 union blogic_geo_reg georeg;
1355 unsigned char req_replylen;
1356 unsigned char *tgt, ch;
1357 int tgt_id, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001359 Configuration Information for FlashPoint Host Adapters is
1360 provided in the fpoint_info structure by the FlashPoint
1361 SCCB Manager's Probe Function. Initialize fields in the
1362 Host Adapter structure from the fpoint_info structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001364 if (blogic_flashpoint_type(adapter)) {
1365 struct fpoint_info *fpinfo = &adapter->fpinfo;
1366 tgt = adapter->model;
1367 *tgt++ = 'B';
1368 *tgt++ = 'T';
1369 *tgt++ = '-';
1370 for (i = 0; i < sizeof(fpinfo->model); i++)
1371 *tgt++ = fpinfo->model[i];
1372 *tgt++ = '\0';
1373 strcpy(adapter->fw_ver, FLASHPOINT_FW_VER);
1374 adapter->scsi_id = fpinfo->scsi_id;
1375 adapter->ext_trans_enable = fpinfo->ext_trans_enable;
1376 adapter->parity = fpinfo->parity;
1377 adapter->reset_enabled = !fpinfo->softreset;
1378 adapter->level_int = true;
1379 adapter->wide = fpinfo->wide;
1380 adapter->differential = false;
1381 adapter->scam = true;
1382 adapter->ultra = true;
1383 adapter->ext_lun = true;
1384 adapter->terminfo_valid = true;
1385 adapter->low_term = fpinfo->low_term;
1386 adapter->high_term = fpinfo->high_term;
1387 adapter->scam_enabled = fpinfo->scam_enabled;
1388 adapter->scam_lev2 = fpinfo->scam_lev2;
1389 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1390 adapter->maxdev = (adapter->wide ? 16 : 8);
1391 adapter->maxlun = 32;
1392 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1393 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
1394 adapter->drvr_qdepth = 255;
1395 adapter->adapter_qdepth = adapter->drvr_qdepth;
1396 adapter->sync_ok = fpinfo->sync_ok;
1397 adapter->fast_ok = fpinfo->fast_ok;
1398 adapter->ultra_ok = fpinfo->ultra_ok;
1399 adapter->wide_ok = fpinfo->wide_ok;
1400 adapter->discon_ok = fpinfo->discon_ok;
1401 adapter->tagq_ok = 0xFFFF;
1402 goto common;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 }
1404 /*
1405 Issue the Inquire Board ID command.
1406 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001407 if (blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
1408 sizeof(id)) != sizeof(id))
1409 return blogic_failure(adapter, "INQUIRE BOARD ID");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 /*
1411 Issue the Inquire Configuration command.
1412 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001413 if (blogic_cmd(adapter, BLOGIC_INQ_CONFIG, NULL, 0, &config,
1414 sizeof(config))
1415 != sizeof(config))
1416 return blogic_failure(adapter, "INQUIRE CONFIGURATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 /*
1418 Issue the Inquire Setup Information command.
1419 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001420 req_replylen = sizeof(setupinfo);
1421 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
1422 sizeof(req_replylen), &setupinfo,
1423 sizeof(setupinfo)) != sizeof(setupinfo))
1424 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 /*
1426 Issue the Inquire Extended Setup Information command.
1427 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001428 req_replylen = sizeof(ext_setupinfo);
1429 if (blogic_cmd(adapter, BLOGIC_INQ_EXTSETUP, &req_replylen,
1430 sizeof(req_replylen), &ext_setupinfo,
1431 sizeof(ext_setupinfo)) != sizeof(ext_setupinfo))
1432 return blogic_failure(adapter,
1433 "INQUIRE EXTENDED SETUP INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 /*
1435 Issue the Inquire Firmware Version 3rd Digit command.
1436 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001437 fw_ver_digit3 = '\0';
1438 if (id.fw_ver_digit1 > '0')
1439 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_D3, NULL, 0,
1440 &fw_ver_digit3,
1441 sizeof(fw_ver_digit3)) != sizeof(fw_ver_digit3))
1442 return blogic_failure(adapter,
1443 "INQUIRE FIRMWARE 3RD DIGIT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 /*
1445 Issue the Inquire Host Adapter Model Number command.
1446 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001447 if (ext_setupinfo.bus_type == 'A' && id.fw_ver_digit1 == '2')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 /* BusLogic BT-542B ISA 2.xx */
Khalid Aziz839cb992013-05-16 19:44:13 -06001449 strcpy(model, "542B");
1450 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '2' &&
1451 (id.fw_ver_digit2 <= '1' || (id.fw_ver_digit2 == '2' &&
1452 fw_ver_digit3 == '0')))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 /* BusLogic BT-742A EISA 2.1x or 2.20 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001454 strcpy(model, "742A");
1455 else if (ext_setupinfo.bus_type == 'E' && id.fw_ver_digit1 == '0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 /* AMI FastDisk EISA Series 441 0.x */
Khalid Aziz839cb992013-05-16 19:44:13 -06001457 strcpy(model, "747A");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001459 req_replylen = sizeof(model);
1460 if (blogic_cmd(adapter, BLOGIC_INQ_MODELNO, &req_replylen,
1461 sizeof(req_replylen), &model,
1462 sizeof(model)) != sizeof(model))
1463 return blogic_failure(adapter,
1464 "INQUIRE HOST ADAPTER MODEL NUMBER");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 }
1466 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001467 BusLogic MultiMaster Host Adapters can be identified by their
1468 model number and the major version number of their firmware
1469 as follows:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 5.xx BusLogic "W" Series Host Adapters:
1472 BT-948/958/958D
1473 4.xx BusLogic "C" Series Host Adapters:
1474 BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1475 3.xx BusLogic "S" Series Host Adapters:
1476 BT-747S/747D/757S/757D/445S/545S/542D
1477 BT-542B/742A (revision H)
1478 2.xx BusLogic "A" Series Host Adapters:
1479 BT-542B/742A (revision G and below)
1480 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1481 */
1482 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001483 Save the Model Name and Host Adapter Name in the Host Adapter
1484 structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001486 tgt = adapter->model;
1487 *tgt++ = 'B';
1488 *tgt++ = 'T';
1489 *tgt++ = '-';
1490 for (i = 0; i < sizeof(model); i++) {
1491 ch = model[i];
1492 if (ch == ' ' || ch == '\0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06001494 *tgt++ = ch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001496 *tgt++ = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 /*
1498 Save the Firmware Version in the Host Adapter structure.
1499 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001500 tgt = adapter->fw_ver;
1501 *tgt++ = id.fw_ver_digit1;
1502 *tgt++ = '.';
1503 *tgt++ = id.fw_ver_digit2;
1504 if (fw_ver_digit3 != ' ' && fw_ver_digit3 != '\0')
1505 *tgt++ = fw_ver_digit3;
1506 *tgt = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 /*
1508 Issue the Inquire Firmware Version Letter command.
1509 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001510 if (strcmp(adapter->fw_ver, "3.3") >= 0) {
1511 if (blogic_cmd(adapter, BLOGIC_INQ_FWVER_LETTER, NULL, 0,
1512 &fw_ver_letter,
1513 sizeof(fw_ver_letter)) != sizeof(fw_ver_letter))
1514 return blogic_failure(adapter,
1515 "INQUIRE FIRMWARE VERSION LETTER");
1516 if (fw_ver_letter != ' ' && fw_ver_letter != '\0')
1517 *tgt++ = fw_ver_letter;
1518 *tgt = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 }
1520 /*
1521 Save the Host Adapter SCSI ID in the Host Adapter structure.
1522 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001523 adapter->scsi_id = config.id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001525 Determine the Bus Type and save it in the Host Adapter structure,
1526 determine and save the IRQ Channel if necessary, and determine
1527 and save the DMA Channel for ISA Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001529 adapter->adapter_bus_type =
1530 blogic_adater_bus_types[adapter->model[3] - '4'];
1531 if (adapter->irq_ch == 0) {
1532 if (config.irq_ch9)
1533 adapter->irq_ch = 9;
1534 else if (config.irq_ch10)
1535 adapter->irq_ch = 10;
1536 else if (config.irq_ch11)
1537 adapter->irq_ch = 11;
1538 else if (config.irq_ch12)
1539 adapter->irq_ch = 12;
1540 else if (config.irq_ch14)
1541 adapter->irq_ch = 14;
1542 else if (config.irq_ch15)
1543 adapter->irq_ch = 15;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001545 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS) {
1546 if (config.dma_ch5)
1547 adapter->dma_ch = 5;
1548 else if (config.dma_ch6)
1549 adapter->dma_ch = 6;
1550 else if (config.dma_ch7)
1551 adapter->dma_ch = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 }
1553 /*
1554 Determine whether Extended Translation is enabled and save it in
1555 the Host Adapter structure.
1556 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001557 georeg.all = blogic_rdgeom(adapter);
1558 adapter->ext_trans_enable = georeg.gr.ext_trans_enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 /*
1560 Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1561 SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1562 Ultra SCSI flag in the Host Adapter structure.
1563 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001564 adapter->adapter_sglimit = ext_setupinfo.sg_limit;
1565 adapter->drvr_sglimit = adapter->adapter_sglimit;
1566 if (adapter->adapter_sglimit > BLOGIC_SG_LIMIT)
1567 adapter->drvr_sglimit = BLOGIC_SG_LIMIT;
1568 if (ext_setupinfo.misc.level_int)
1569 adapter->level_int = true;
1570 adapter->wide = ext_setupinfo.wide;
1571 adapter->differential = ext_setupinfo.differential;
1572 adapter->scam = ext_setupinfo.scam;
1573 adapter->ultra = ext_setupinfo.ultra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 /*
1575 Determine whether Extended LUN Format CCBs are supported and save the
1576 information in the Host Adapter structure.
1577 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001578 if (adapter->fw_ver[0] == '5' || (adapter->fw_ver[0] == '4' &&
1579 adapter->wide))
1580 adapter->ext_lun = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 /*
1582 Issue the Inquire PCI Host Adapter Information command to read the
1583 Termination Information from "W" series MultiMaster Host Adapters.
1584 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001585 if (adapter->fw_ver[0] == '5') {
1586 if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
1587 &adapter_info,
1588 sizeof(adapter_info)) != sizeof(adapter_info))
1589 return blogic_failure(adapter,
1590 "INQUIRE PCI HOST ADAPTER INFORMATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001592 Save the Termination Information in the Host Adapter
1593 structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001595 if (adapter_info.genericinfo_valid) {
1596 adapter->terminfo_valid = true;
1597 adapter->low_term = adapter_info.low_term;
1598 adapter->high_term = adapter_info.high_term;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 }
1600 }
1601 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001602 Issue the Fetch Host Adapter Local RAM command to read the
1603 AutoSCSI data from "W" and "C" series MultiMaster Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001605 if (adapter->fw_ver[0] >= '4') {
1606 fetch_localram.offset = BLOGIC_AUTOSCSI_BASE;
1607 fetch_localram.count = sizeof(autoscsi);
1608 if (blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM, &fetch_localram,
1609 sizeof(fetch_localram), &autoscsi,
1610 sizeof(autoscsi)) != sizeof(autoscsi))
1611 return blogic_failure(adapter,
1612 "FETCH HOST ADAPTER LOCAL RAM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001614 Save the Parity Checking Enabled, Bus Reset Enabled,
1615 and Termination Information in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001617 adapter->parity = autoscsi.parity;
1618 adapter->reset_enabled = autoscsi.reset_enabled;
1619 if (adapter->fw_ver[0] == '4') {
1620 adapter->terminfo_valid = true;
1621 adapter->low_term = autoscsi.low_term;
1622 adapter->high_term = autoscsi.high_term;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 }
1624 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001625 Save the Wide Permitted, Fast Permitted, Synchronous
1626 Permitted, Disconnect Permitted, Ultra Permitted, and
1627 SCAM Information in the Host Adapter structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001629 adapter->wide_ok = autoscsi.wide_ok;
1630 adapter->fast_ok = autoscsi.fast_ok;
1631 adapter->sync_ok = autoscsi.sync_ok;
1632 adapter->discon_ok = autoscsi.discon_ok;
1633 if (adapter->ultra)
1634 adapter->ultra_ok = autoscsi.ultra_ok;
1635 if (adapter->scam) {
1636 adapter->scam_enabled = autoscsi.scam_enabled;
1637 adapter->scam_lev2 = autoscsi.scam_lev2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
1639 }
1640 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001641 Initialize fields in the Host Adapter structure for "S" and "A"
1642 series MultiMaster Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001644 if (adapter->fw_ver[0] < '4') {
1645 if (setupinfo.sync) {
1646 adapter->sync_ok = 0xFF;
1647 if (adapter->adapter_bus_type == BLOGIC_EISA_BUS) {
1648 if (ext_setupinfo.misc.fast_on_eisa)
1649 adapter->fast_ok = 0xFF;
1650 if (strcmp(adapter->model, "BT-757") == 0)
1651 adapter->wide_ok = 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 }
1653 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001654 adapter->discon_ok = 0xFF;
1655 adapter->parity = setupinfo.parity;
1656 adapter->reset_enabled = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001659 Determine the maximum number of Target IDs and Logical Units
1660 supported by this driver for Wide and Narrow Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001662 adapter->maxdev = (adapter->wide ? 16 : 8);
1663 adapter->maxlun = (adapter->ext_lun ? 32 : 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 /*
1665 Select appropriate values for the Mailbox Count, Driver Queue Depth,
Khalid Aziz839cb992013-05-16 19:44:13 -06001666 Initial CCBs, and Incremental CCBs variables based on whether
1667 or not Strict Round Robin Mode is supported. If Strict Round
1668 Robin Mode is supported, then there is no performance degradation
1669 in using the maximum possible number of Outgoing and Incoming
1670 Mailboxes and allowing the Tagged and Untagged Queue Depths to
1671 determine the actual utilization. If Strict Round Robin Mode is
1672 not supported, then the Host Adapter must scan all the Outgoing
1673 Mailboxes whenever an Outgoing Mailbox entry is made, which can
1674 cause a substantial performance penalty. The host adapters
1675 actually have room to store the following number of CCBs
1676 internally; that is, they can internally queue and manage this
1677 many active commands on the SCSI bus simultaneously. Performance
1678 measurements demonstrate that the Driver Queue Depth should be
1679 set to the Mailbox Count, rather than the Host Adapter Queue
1680 Depth (internal CCB capacity), as it is more efficient to have the
1681 queued commands waiting in Outgoing Mailboxes if necessary than
1682 to block the process in the higher levels of the SCSI Subsystem.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 192 BT-948/958/958D
1685 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1686 50 BT-545C/540CF
1687 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1688 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001689 if (adapter->fw_ver[0] == '5')
1690 adapter->adapter_qdepth = 192;
1691 else if (adapter->fw_ver[0] == '4')
1692 adapter->adapter_qdepth = (adapter->adapter_bus_type !=
1693 BLOGIC_ISA_BUS ? 100 : 50);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001695 adapter->adapter_qdepth = 30;
1696 if (strcmp(adapter->fw_ver, "3.31") >= 0) {
1697 adapter->strict_rr = true;
1698 adapter->mbox_count = BLOGIC_MAX_MAILBOX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001700 adapter->strict_rr = false;
1701 adapter->mbox_count = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001703 adapter->drvr_qdepth = adapter->mbox_count;
1704 adapter->initccbs = 4 * BLOGIC_CCB_GRP_ALLOCSIZE;
1705 adapter->inc_ccbs = BLOGIC_CCB_GRP_ALLOCSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001707 Tagged Queuing support is available and operates properly on
1708 all "W" series MultiMaster Host Adapters, on "C" series
1709 MultiMaster Host Adapters with firmware version 4.22 and above,
1710 and on "S" series MultiMaster Host Adapters with firmware version
1711 3.35 and above.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001713 adapter->tagq_ok = 0;
1714 switch (adapter->fw_ver[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 case '5':
Khalid Aziz839cb992013-05-16 19:44:13 -06001716 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 break;
1718 case '4':
Khalid Aziz839cb992013-05-16 19:44:13 -06001719 if (strcmp(adapter->fw_ver, "4.22") >= 0)
1720 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 break;
1722 case '3':
Khalid Aziz839cb992013-05-16 19:44:13 -06001723 if (strcmp(adapter->fw_ver, "3.35") >= 0)
1724 adapter->tagq_ok = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 break;
1726 }
1727 /*
1728 Determine the Host Adapter BIOS Address if the BIOS is enabled and
1729 save it in the Host Adapter structure. The BIOS is disabled if the
Khalid Aziz839cb992013-05-16 19:44:13 -06001730 bios_addr is 0.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001732 adapter->bios_addr = ext_setupinfo.bios_addr << 12;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001734 ISA Host Adapters require Bounce Buffers if there is more than
1735 16MB memory.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001737 if (adapter->adapter_bus_type == BLOGIC_ISA_BUS &&
1738 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1739 adapter->need_bouncebuf = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001741 BusLogic BT-445S Host Adapters prior to board revision E have a
1742 hardware bug whereby when the BIOS is enabled, transfers to/from
1743 the same address range the BIOS occupies modulo 16MB are handled
1744 incorrectly. Only properly functioning BT-445S Host Adapters
1745 have firmware version 3.37, so require that ISA Bounce Buffers
1746 be used for the buggy BT-445S models if there is more than 16MB
1747 memory.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001749 if (adapter->bios_addr > 0 && strcmp(adapter->model, "BT-445S") == 0 &&
1750 strcmp(adapter->fw_ver, "3.37") < 0 &&
1751 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1752 adapter->need_bouncebuf = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001754 Initialize parameters common to MultiMaster and FlashPoint
1755 Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001757common:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 /*
1759 Initialize the Host Adapter Full Model Name from the Model Name.
1760 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001761 strcpy(adapter->full_model, "BusLogic ");
1762 strcat(adapter->full_model, adapter->model);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 /*
1764 Select an appropriate value for the Tagged Queue Depth either from a
1765 BusLogic Driver Options specification, or based on whether this Host
Khalid Aziz839cb992013-05-16 19:44:13 -06001766 Adapter requires that ISA Bounce Buffers be used. The Tagged Queue
1767 Depth is left at 0 for automatic determination in
1768 BusLogic_SelectQueueDepths. Initialize the Untagged Queue Depth.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001770 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
1771 unsigned char qdepth = 0;
1772 if (adapter->drvr_opts != NULL &&
1773 adapter->drvr_opts->qdepth[tgt_id] > 0)
1774 qdepth = adapter->drvr_opts->qdepth[tgt_id];
1775 else if (adapter->need_bouncebuf)
1776 qdepth = BLOGIC_TAG_DEPTH_BB;
1777 adapter->qdepth[tgt_id] = qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001779 if (adapter->need_bouncebuf)
1780 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH_BB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001782 adapter->untag_qdepth = BLOGIC_UNTAG_DEPTH;
1783 if (adapter->drvr_opts != NULL)
1784 adapter->common_qdepth = adapter->drvr_opts->common_qdepth;
1785 if (adapter->common_qdepth > 0 &&
1786 adapter->common_qdepth < adapter->untag_qdepth)
1787 adapter->untag_qdepth = adapter->common_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 /*
1789 Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1790 Therefore, mask the Tagged Queuing Permitted Default bits with the
1791 Disconnect/Reconnect Permitted bits.
1792 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001793 adapter->tagq_ok &= adapter->discon_ok;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001795 Combine the default Tagged Queuing Permitted bits with any
1796 BusLogic Driver Options Tagged Queuing specification.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001798 if (adapter->drvr_opts != NULL)
1799 adapter->tagq_ok = (adapter->drvr_opts->tagq_ok &
1800 adapter->drvr_opts->tagq_ok_mask) |
1801 (adapter->tagq_ok & ~adapter->drvr_opts->tagq_ok_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001804 Select an appropriate value for Bus Settle Time either from a
1805 BusLogic Driver Options specification, or from
1806 BLOGIC_BUS_SETTLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001808 if (adapter->drvr_opts != NULL &&
1809 adapter->drvr_opts->bus_settle_time > 0)
1810 adapter->bus_settle_time = adapter->drvr_opts->bus_settle_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001812 adapter->bus_settle_time = BLOGIC_BUS_SETTLE_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001814 Indicate reading the Host Adapter Configuration completed
1815 successfully.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 */
1817 return true;
1818}
1819
1820
1821/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001822 blogic_reportconfig reports the configuration of Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823*/
1824
Khalid Aziz839cb992013-05-16 19:44:13 -06001825static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
Khalid Aziz839cb992013-05-16 19:44:13 -06001827 unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
1828 unsigned short sync_ok, fast_ok;
1829 unsigned short ultra_ok, wide_ok;
1830 unsigned short discon_ok, tagq_ok;
1831 bool common_syncneg, common_tagq_depth;
1832 char syncstr[BLOGIC_MAXDEV + 1];
1833 char widestr[BLOGIC_MAXDEV + 1];
1834 char discon_str[BLOGIC_MAXDEV + 1];
1835 char tagq_str[BLOGIC_MAXDEV + 1];
1836 char *syncmsg = syncstr;
1837 char *widemsg = widestr;
1838 char *discon_msg = discon_str;
1839 char *tagq_msg = tagq_str;
1840 int tgt_id;
1841
1842 blogic_info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", adapter, adapter->model, blogic_adapter_busnames[adapter->adapter_bus_type], (adapter->wide ? " Wide" : ""), (adapter->differential ? " Differential" : ""), (adapter->ultra ? " Ultra" : ""));
1843 blogic_info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
1844 if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
1845 blogic_info(" DMA Channel: ", adapter);
1846 if (adapter->dma_ch > 0)
1847 blogic_info("%d, ", adapter, adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001849 blogic_info("None, ", adapter);
1850 if (adapter->bios_addr > 0)
1851 blogic_info("BIOS Address: 0x%X, ", adapter,
1852 adapter->bios_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001854 blogic_info("BIOS Address: None, ", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001856 blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
1857 adapter->bus, adapter->dev);
1858 if (adapter->pci_addr > 0)
1859 blogic_info("0x%X, ", adapter, adapter->pci_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001861 blogic_info("Unassigned, ", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001863 blogic_info("Host Adapter SCSI ID: %d\n", adapter, adapter->scsi_id);
1864 blogic_info(" Parity Checking: %s, Extended Translation: %s\n",
1865 adapter, (adapter->parity ? "Enabled" : "Disabled"),
1866 (adapter->ext_trans_enable ? "Enabled" : "Disabled"));
1867 alltgt_mask &= ~(1 << adapter->scsi_id);
1868 sync_ok = adapter->sync_ok & alltgt_mask;
1869 fast_ok = adapter->fast_ok & alltgt_mask;
1870 ultra_ok = adapter->ultra_ok & alltgt_mask;
1871 if ((blogic_multimaster_type(adapter) &&
1872 (adapter->fw_ver[0] >= '4' ||
1873 adapter->adapter_bus_type == BLOGIC_EISA_BUS)) ||
1874 blogic_flashpoint_type(adapter)) {
1875 common_syncneg = false;
1876 if (sync_ok == 0) {
1877 syncmsg = "Disabled";
1878 common_syncneg = true;
1879 } else if (sync_ok == alltgt_mask) {
1880 if (fast_ok == 0) {
1881 syncmsg = "Slow";
1882 common_syncneg = true;
1883 } else if (fast_ok == alltgt_mask) {
1884 if (ultra_ok == 0) {
1885 syncmsg = "Fast";
1886 common_syncneg = true;
1887 } else if (ultra_ok == alltgt_mask) {
1888 syncmsg = "Ultra";
1889 common_syncneg = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 }
1891 }
1892 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001893 if (!common_syncneg) {
1894 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1895 syncstr[tgt_id] = ((!(sync_ok & (1 << tgt_id))) ? 'N' : (!(fast_ok & (1 << tgt_id)) ? 'S' : (!(ultra_ok & (1 << tgt_id)) ? 'F' : 'U')));
1896 syncstr[adapter->scsi_id] = '#';
1897 syncstr[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 }
1899 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001900 syncmsg = (sync_ok == 0 ? "Disabled" : "Enabled");
1901 wide_ok = adapter->wide_ok & alltgt_mask;
1902 if (wide_ok == 0)
1903 widemsg = "Disabled";
1904 else if (wide_ok == alltgt_mask)
1905 widemsg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001907 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1908 widestr[tgt_id] = ((wide_ok & (1 << tgt_id)) ? 'Y' : 'N');
1909 widestr[adapter->scsi_id] = '#';
1910 widestr[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001912 discon_ok = adapter->discon_ok & alltgt_mask;
1913 if (discon_ok == 0)
1914 discon_msg = "Disabled";
1915 else if (discon_ok == alltgt_mask)
1916 discon_msg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001918 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1919 discon_str[tgt_id] = ((discon_ok & (1 << tgt_id)) ? 'Y' : 'N');
1920 discon_str[adapter->scsi_id] = '#';
1921 discon_str[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001923 tagq_ok = adapter->tagq_ok & alltgt_mask;
1924 if (tagq_ok == 0)
1925 tagq_msg = "Disabled";
1926 else if (tagq_ok == alltgt_mask)
1927 tagq_msg = "Enabled";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06001929 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
1930 tagq_str[tgt_id] = ((tagq_ok & (1 << tgt_id)) ? 'Y' : 'N');
1931 tagq_str[adapter->scsi_id] = '#';
1932 tagq_str[adapter->maxdev] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001934 blogic_info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
1935 adapter, syncmsg, widemsg);
1936 blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
1937 discon_msg, tagq_msg);
1938 if (blogic_multimaster_type(adapter)) {
1939 blogic_info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
1940 blogic_info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001942 blogic_info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
1943 blogic_info(" Tagged Queue Depth: ", adapter);
1944 common_tagq_depth = true;
1945 for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
1946 if (adapter->qdepth[tgt_id] != adapter->qdepth[0]) {
1947 common_tagq_depth = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 break;
1949 }
Khalid Aziz839cb992013-05-16 19:44:13 -06001950 if (common_tagq_depth) {
1951 if (adapter->qdepth[0] > 0)
1952 blogic_info("%d", adapter, adapter->qdepth[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001954 blogic_info("Automatic", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06001956 blogic_info("Individual", adapter);
1957 blogic_info(", Untagged Queue Depth: %d\n", adapter,
1958 adapter->untag_qdepth);
1959 if (adapter->terminfo_valid) {
1960 if (adapter->wide)
1961 blogic_info(" SCSI Bus Termination: %s", adapter,
1962 (adapter->low_term ? (adapter->high_term ? "Both Enabled" : "Low Enabled") : (adapter->high_term ? "High Enabled" : "Both Disabled")));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 else
Khalid Aziz839cb992013-05-16 19:44:13 -06001964 blogic_info(" SCSI Bus Termination: %s", adapter,
1965 (adapter->low_term ? "Enabled" : "Disabled"));
1966 if (adapter->scam)
1967 blogic_info(", SCAM: %s", adapter,
1968 (adapter->scam_enabled ? (adapter->scam_lev2 ? "Enabled, Level 2" : "Enabled, Level 1") : "Disabled"));
1969 blogic_info("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 }
1971 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06001972 Indicate reporting the Host Adapter configuration completed
1973 successfully.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974 */
1975 return true;
1976}
1977
1978
1979/*
Khalid Aziz839cb992013-05-16 19:44:13 -06001980 blogic_getres acquires the system resources necessary to use
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 Host Adapter.
1982*/
1983
Khalid Aziz839cb992013-05-16 19:44:13 -06001984static bool __init blogic_getres(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985{
Khalid Aziz839cb992013-05-16 19:44:13 -06001986 if (adapter->irq_ch == 0) {
1987 blogic_err("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
1988 adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 return false;
1990 }
1991 /*
1992 Acquire shared access to the IRQ Channel.
1993 */
Khalid Aziz839cb992013-05-16 19:44:13 -06001994 if (request_irq(adapter->irq_ch, blogic_inthandler, IRQF_SHARED,
1995 adapter->full_model, adapter) < 0) {
1996 blogic_err("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
1997 adapter, adapter->irq_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 return false;
1999 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002000 adapter->irq_acquired = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 /*
2002 Acquire exclusive access to the DMA Channel.
2003 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002004 if (adapter->dma_ch > 0) {
2005 if (request_dma(adapter->dma_ch, adapter->full_model) < 0) {
2006 blogic_err("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", adapter, adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007 return false;
2008 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002009 set_dma_mode(adapter->dma_ch, DMA_MODE_CASCADE);
2010 enable_dma(adapter->dma_ch);
2011 adapter->dma_chan_acquired = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 }
2013 /*
2014 Indicate the System Resource Acquisition completed successfully,
2015 */
2016 return true;
2017}
2018
2019
2020/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002021 blogic_relres releases any system resources previously acquired
2022 by blogic_getres.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023*/
2024
Khalid Aziz839cb992013-05-16 19:44:13 -06002025static void blogic_relres(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026{
2027 /*
2028 Release shared access to the IRQ Channel.
2029 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002030 if (adapter->irq_acquired)
2031 free_irq(adapter->irq_ch, adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 /*
2033 Release exclusive access to the DMA Channel.
2034 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002035 if (adapter->dma_chan_acquired)
2036 free_dma(adapter->dma_ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 /*
2038 Release any allocated memory structs not released elsewhere
2039 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002040 if (adapter->mbox_space)
2041 pci_free_consistent(adapter->pci_device, adapter->mbox_sz,
2042 adapter->mbox_space, adapter->mbox_space_handle);
2043 pci_dev_put(adapter->pci_device);
2044 adapter->mbox_space = NULL;
2045 adapter->mbox_space_handle = 0;
2046 adapter->mbox_sz = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047}
2048
2049
2050/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002051 blogic_initadapter initializes Host Adapter. This is the only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 function called during SCSI Host Adapter detection which modifies the state
2053 of the Host Adapter from its initial power on or hard reset state.
2054*/
2055
Khalid Aziz839cb992013-05-16 19:44:13 -06002056static bool blogic_initadapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057{
Khalid Aziz839cb992013-05-16 19:44:13 -06002058 struct blogic_extmbox_req extmbox_req;
2059 enum blogic_rr_req rr_req;
2060 enum blogic_setccb_fmt setccb_fmt;
2061 int tgt_id;
2062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002064 Initialize the pointers to the first and last CCBs that are
2065 queued for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002067 adapter->firstccb = NULL;
2068 adapter->lastccb = NULL;
2069
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 /*
2071 Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
2072 Command Successful Flag, Active Commands, and Commands Since Reset
2073 for each Target Device.
2074 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002075 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
2076 adapter->bdr_pend[tgt_id] = NULL;
2077 adapter->tgt_flags[tgt_id].tagq_active = false;
2078 adapter->tgt_flags[tgt_id].cmd_good = false;
2079 adapter->active_cmds[tgt_id] = 0;
2080 adapter->cmds_since_rst[tgt_id] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002082
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 /*
2084 FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
2085 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002086 if (blogic_flashpoint_type(adapter))
2087 goto done;
2088
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 /*
2090 Initialize the Outgoing and Incoming Mailbox pointers.
2091 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002092 adapter->mbox_sz = adapter->mbox_count * (sizeof(struct blogic_outbox) + sizeof(struct blogic_inbox));
2093 adapter->mbox_space = pci_alloc_consistent(adapter->pci_device,
2094 adapter->mbox_sz, &adapter->mbox_space_handle);
2095 if (adapter->mbox_space == NULL)
2096 return blogic_failure(adapter, "MAILBOX ALLOCATION");
2097 adapter->first_outbox = (struct blogic_outbox *) adapter->mbox_space;
2098 adapter->last_outbox = adapter->first_outbox + adapter->mbox_count - 1;
2099 adapter->next_outbox = adapter->first_outbox;
2100 adapter->first_inbox = (struct blogic_inbox *) (adapter->last_outbox + 1);
2101 adapter->last_inbox = adapter->first_inbox + adapter->mbox_count - 1;
2102 adapter->next_inbox = adapter->first_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
2104 /*
2105 Initialize the Outgoing and Incoming Mailbox structures.
2106 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002107 memset(adapter->first_outbox, 0,
2108 adapter->mbox_count * sizeof(struct blogic_outbox));
2109 memset(adapter->first_inbox, 0,
2110 adapter->mbox_count * sizeof(struct blogic_inbox));
2111
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002113 Initialize the Host Adapter's Pointer to the Outgoing/Incoming
2114 Mailboxes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002116 extmbox_req.mbox_count = adapter->mbox_count;
2117 extmbox_req.base_mbox_addr = (u32) adapter->mbox_space_handle;
2118 if (blogic_cmd(adapter, BLOGIC_INIT_EXT_MBOX, &extmbox_req,
2119 sizeof(extmbox_req), NULL, 0) < 0)
2120 return blogic_failure(adapter, "MAILBOX INITIALIZATION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002122 Enable Strict Round Robin Mode if supported by the Host Adapter. In
2123 Strict Round Robin Mode, the Host Adapter only looks at the next
2124 Outgoing Mailbox for each new command, rather than scanning
2125 through all the Outgoing Mailboxes to find any that have new
2126 commands in them. Strict Round Robin Mode is significantly more
2127 efficient.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002129 if (adapter->strict_rr) {
2130 rr_req = BLOGIC_STRICT_RR_MODE;
2131 if (blogic_cmd(adapter, BLOGIC_STRICT_RR, &rr_req,
2132 sizeof(rr_req), NULL, 0) < 0)
2133 return blogic_failure(adapter,
2134 "ENABLE STRICT ROUND ROBIN MODE");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002136
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002138 For Host Adapters that support Extended LUN Format CCBs, issue the
2139 Set CCB Format command to allow 32 Logical Units per Target Device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002141 if (adapter->ext_lun) {
2142 setccb_fmt = BLOGIC_EXT_LUN_CCB;
2143 if (blogic_cmd(adapter, BLOGIC_SETCCB_FMT, &setccb_fmt,
2144 sizeof(setccb_fmt), NULL, 0) < 0)
2145 return blogic_failure(adapter, "SET CCB FORMAT");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002147
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148 /*
2149 Announce Successful Initialization.
2150 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002151done:
2152 if (!adapter->adapter_initd) {
2153 blogic_info("*** %s Initialized Successfully ***\n", adapter,
2154 adapter->full_model);
2155 blogic_info("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06002157 blogic_warn("*** %s Initialized Successfully ***\n", adapter,
2158 adapter->full_model);
2159 adapter->adapter_initd = true;
2160
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 /*
2162 Indicate the Host Adapter Initialization completed successfully.
2163 */
2164 return true;
2165}
2166
2167
2168/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002169 blogic_inquiry inquires about the Target Devices accessible
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 through Host Adapter.
2171*/
2172
Khalid Aziz839cb992013-05-16 19:44:13 -06002173static bool __init blogic_inquiry(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174{
Khalid Aziz839cb992013-05-16 19:44:13 -06002175 u16 installed_devs;
2176 u8 installed_devs0to7[8];
2177 struct blogic_setup_info setupinfo;
2178 u8 sync_period[BLOGIC_MAXDEV];
2179 unsigned char req_replylen;
2180 int tgt_id;
2181
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002183 Wait a few seconds between the Host Adapter Hard Reset which
2184 initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
2185 SCSI devices get confused if they receive SCSI Commands too soon
2186 after a SCSI Bus Reset.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002188 blogic_delay(adapter->bus_settle_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 /*
2190 FlashPoint Host Adapters do not provide for Target Device Inquiry.
2191 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002192 if (blogic_flashpoint_type(adapter))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 return true;
2194 /*
2195 Inhibit the Target Device Inquiry if requested.
2196 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002197 if (adapter->drvr_opts != NULL && adapter->drvr_opts->stop_tgt_inquiry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 return true;
2199 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002200 Issue the Inquire Target Devices command for host adapters with
2201 firmware version 4.25 or later, or the Inquire Installed Devices
2202 ID 0 to 7 command for older host adapters. This is necessary to
2203 force Synchronous Transfer Negotiation so that the Inquire Setup
2204 Information and Inquire Synchronous Period commands will return
2205 valid data. The Inquire Target Devices command is preferable to
2206 Inquire Installed Devices ID 0 to 7 since it only probes Logical
2207 Unit 0 of each Target Device.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002209 if (strcmp(adapter->fw_ver, "4.25") >= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
2211 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002212 Issue a Inquire Target Devices command. Inquire Target
2213 Devices only tests Logical Unit 0 of each Target Device
2214 unlike the Inquire Installed Devices commands which test
2215 Logical Units 0 - 7. Two bytes are returned, where byte
2216 0 bit 0 set indicates that Target Device 0 exists, and so on.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 */
2218
Khalid Aziz839cb992013-05-16 19:44:13 -06002219 if (blogic_cmd(adapter, BLOGIC_INQ_DEV, NULL, 0,
2220 &installed_devs, sizeof(installed_devs))
2221 != sizeof(installed_devs))
2222 return blogic_failure(adapter, "INQUIRE TARGET DEVICES");
2223 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2224 adapter->tgt_flags[tgt_id].tgt_exists =
2225 (installed_devs & (1 << tgt_id) ? true : false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 } else {
2227
2228 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002229 Issue an Inquire Installed Devices command. For each
2230 Target Device, a byte is returned where bit 0 set
2231 indicates that Logical Unit 0 * exists, bit 1 set
2232 indicates that Logical Unit 1 exists, and so on.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 */
2234
Khalid Aziz839cb992013-05-16 19:44:13 -06002235 if (blogic_cmd(adapter, BLOGIC_INQ_DEV0TO7, NULL, 0,
2236 &installed_devs0to7, sizeof(installed_devs0to7))
2237 != sizeof(installed_devs0to7))
2238 return blogic_failure(adapter,
2239 "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2240 for (tgt_id = 0; tgt_id < 8; tgt_id++)
2241 adapter->tgt_flags[tgt_id].tgt_exists =
2242 (installed_devs0to7[tgt_id] != 0 ? true : false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244 /*
2245 Issue the Inquire Setup Information command.
2246 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002247 req_replylen = sizeof(setupinfo);
2248 if (blogic_cmd(adapter, BLOGIC_INQ_SETUPINFO, &req_replylen,
2249 sizeof(req_replylen), &setupinfo, sizeof(setupinfo))
2250 != sizeof(setupinfo))
2251 return blogic_failure(adapter, "INQUIRE SETUP INFORMATION");
2252 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2253 adapter->sync_offset[tgt_id] = (tgt_id < 8 ? setupinfo.sync0to7[tgt_id].offset : setupinfo.sync8to15[tgt_id - 8].offset);
2254 if (strcmp(adapter->fw_ver, "5.06L") >= 0)
2255 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2256 adapter->tgt_flags[tgt_id].wide_active = (tgt_id < 8 ? (setupinfo.wide_tx_active0to7 & (1 << tgt_id) ? true : false) : (setupinfo.wide_tx_active8to15 & (1 << (tgt_id - 8)) ? true : false));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 /*
2258 Issue the Inquire Synchronous Period command.
2259 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002260 if (adapter->fw_ver[0] >= '3') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
Khalid Aziz839cb992013-05-16 19:44:13 -06002262 /* Issue a Inquire Synchronous Period command. For each
2263 Target Device, a byte is returned which represents the
2264 Synchronous Transfer Period in units of 10 nanoseconds.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 */
2266
Khalid Aziz839cb992013-05-16 19:44:13 -06002267 req_replylen = sizeof(sync_period);
2268 if (blogic_cmd(adapter, BLOGIC_INQ_SYNC_PERIOD, &req_replylen,
2269 sizeof(req_replylen), &sync_period,
2270 sizeof(sync_period)) != sizeof(sync_period))
2271 return blogic_failure(adapter,
2272 "INQUIRE SYNCHRONOUS PERIOD");
2273 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2274 adapter->sync_period[tgt_id] = sync_period[tgt_id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06002276 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2277 if (setupinfo.sync0to7[tgt_id].offset > 0)
2278 adapter->sync_period[tgt_id] = 20 + 5 * setupinfo.sync0to7[tgt_id].tx_period;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 /*
2280 Indicate the Target Device Inquiry completed successfully.
2281 */
2282 return true;
2283}
2284
2285/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002286 blogic_inithoststruct initializes the fields in the SCSI Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
2288 SCSI Host structure are intentionally left uninitialized, as this driver
2289 handles acquisition and release of these resources explicitly, as well as
2290 ensuring exclusive access to the Host Adapter hardware and data structures
2291 through explicit acquisition and release of the Host Adapter's Lock.
2292*/
2293
Khalid Aziz839cb992013-05-16 19:44:13 -06002294static void __init blogic_inithoststruct(struct blogic_adapter *adapter,
2295 struct Scsi_Host *host)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296{
Khalid Aziz839cb992013-05-16 19:44:13 -06002297 host->max_id = adapter->maxdev;
2298 host->max_lun = adapter->maxlun;
2299 host->max_channel = 0;
2300 host->unique_id = adapter->io_addr;
2301 host->this_id = adapter->scsi_id;
2302 host->can_queue = adapter->drvr_qdepth;
2303 host->sg_tablesize = adapter->drvr_sglimit;
2304 host->unchecked_isa_dma = adapter->need_bouncebuf;
2305 host->cmd_per_lun = adapter->untag_qdepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306}
2307
2308/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002309 blogic_slaveconfig will actually set the queue depth on individual
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 scsi devices as they are permanently added to the device chain. We
2311 shamelessly rip off the SelectQueueDepths code to make this work mostly
2312 like it used to. Since we don't get called once at the end of the scan
2313 but instead get called for each device, we have to do things a bit
2314 differently.
2315*/
Khalid Aziz839cb992013-05-16 19:44:13 -06002316static int blogic_slaveconfig(struct scsi_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317{
Khalid Aziz839cb992013-05-16 19:44:13 -06002318 struct blogic_adapter *adapter =
2319 (struct blogic_adapter *) dev->host->hostdata;
2320 int tgt_id = dev->id;
2321 int qdepth = adapter->qdepth[tgt_id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Khalid Aziz839cb992013-05-16 19:44:13 -06002323 if (adapter->tgt_flags[tgt_id].tagq_ok &&
2324 (adapter->tagq_ok & (1 << tgt_id))) {
2325 if (qdepth == 0)
2326 qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
2327 adapter->qdepth[tgt_id] = qdepth;
2328 scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002330 adapter->tagq_ok &= ~(1 << tgt_id);
2331 qdepth = adapter->untag_qdepth;
2332 adapter->qdepth[tgt_id] = qdepth;
2333 scsi_adjust_queue_depth(dev, 0, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002335 qdepth = 0;
2336 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
2337 if (adapter->tgt_flags[tgt_id].tgt_exists)
2338 qdepth += adapter->qdepth[tgt_id];
2339 if (qdepth > adapter->alloc_ccbs)
2340 blogic_create_addlccbs(adapter, qdepth - adapter->alloc_ccbs,
2341 false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 return 0;
2343}
2344
2345/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002346 blogic_init probes for BusLogic Host Adapters at the standard
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 I/O Addresses where they may be located, initializing, registering, and
2348 reporting the configuration of each BusLogic Host Adapter it finds. It
2349 returns the number of BusLogic Host Adapters successfully initialized and
2350 registered.
2351*/
2352
Khalid Aziz839cb992013-05-16 19:44:13 -06002353static int __init blogic_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354{
Khalid Aziz839cb992013-05-16 19:44:13 -06002355 int adapter_count = 0, drvr_optindex = 0, probeindex;
2356 struct blogic_adapter *adapter;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002357 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359#ifdef MODULE
2360 if (BusLogic)
Khalid Aziz839cb992013-05-16 19:44:13 -06002361 blogic_setup(BusLogic);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362#endif
2363
Khalid Aziz839cb992013-05-16 19:44:13 -06002364 if (blogic_probe_options.noprobe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 return -ENODEV;
Khalid Aziz839cb992013-05-16 19:44:13 -06002366 blogic_probeinfo_list =
2367 kzalloc(BLOGIC_MAX_ADAPTERS * sizeof(struct blogic_probeinfo),
2368 GFP_KERNEL);
2369 if (blogic_probeinfo_list == NULL) {
2370 blogic_err("BusLogic: Unable to allocate Probe Info List\n",
2371 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 return -ENOMEM;
2373 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002374
Khalid Aziz839cb992013-05-16 19:44:13 -06002375 adapter =
2376 kzalloc(sizeof(struct blogic_adapter), GFP_KERNEL);
2377 if (adapter == NULL) {
2378 kfree(blogic_probeinfo_list);
2379 blogic_err("BusLogic: Unable to allocate Prototype Host Adapter\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 return -ENOMEM;
2381 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002382
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383#ifdef MODULE
2384 if (BusLogic != NULL)
Khalid Aziz839cb992013-05-16 19:44:13 -06002385 blogic_setup(BusLogic);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386#endif
Khalid Aziz839cb992013-05-16 19:44:13 -06002387 blogic_init_probeinfo_list(adapter);
2388 for (probeindex = 0; probeindex < blogic_probeinfo_count; probeindex++) {
2389 struct blogic_probeinfo *probeinfo =
2390 &blogic_probeinfo_list[probeindex];
2391 struct blogic_adapter *myadapter = adapter;
2392 struct Scsi_Host *host;
2393
2394 if (probeinfo->io_addr == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06002396 memset(myadapter, 0, sizeof(struct blogic_adapter));
2397 myadapter->adapter_type = probeinfo->adapter_type;
2398 myadapter->adapter_bus_type = probeinfo->adapter_bus_type;
2399 myadapter->io_addr = probeinfo->io_addr;
2400 myadapter->pci_addr = probeinfo->pci_addr;
2401 myadapter->bus = probeinfo->bus;
2402 myadapter->dev = probeinfo->dev;
2403 myadapter->pci_device = probeinfo->pci_device;
2404 myadapter->irq_ch = probeinfo->irq_ch;
2405 myadapter->addr_count =
2406 blogic_adapter_addr_count[myadapter->adapter_type];
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002407
2408 /*
2409 Make sure region is free prior to probing.
2410 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002411 if (!request_region(myadapter->io_addr, myadapter->addr_count,
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002412 "BusLogic"))
2413 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002415 Probe the Host Adapter. If unsuccessful, abort further
2416 initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002418 if (!blogic_probe(myadapter)) {
2419 release_region(myadapter->io_addr,
2420 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 /*
2424 Hard Reset the Host Adapter. If unsuccessful, abort further
2425 initialization.
2426 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002427 if (!blogic_hwreset(myadapter, true)) {
2428 release_region(myadapter->io_addr,
2429 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002433 Check the Host Adapter. If unsuccessful, abort further
2434 initialization.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002436 if (!blogic_checkadapter(myadapter)) {
2437 release_region(myadapter->io_addr,
2438 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 /*
2442 Initialize the Driver Options field if provided.
2443 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002444 if (drvr_optindex < blogic_drvr_options_count)
2445 myadapter->drvr_opts =
2446 &blogic_drvr_options[drvr_optindex++];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002448 Announce the Driver Version and Date, Author's Name,
2449 Copyright Notice, and Electronic Mail Address.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002451 blogic_announce_drvr(myadapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 Register the SCSI Host structure.
2454 */
2455
Khalid Aziz839cb992013-05-16 19:44:13 -06002456 host = scsi_host_alloc(&blogic_template,
2457 sizeof(struct blogic_adapter));
2458 if (host == NULL) {
2459 release_region(myadapter->io_addr,
2460 myadapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 continue;
2462 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002463 myadapter = (struct blogic_adapter *) host->hostdata;
2464 memcpy(myadapter, adapter, sizeof(struct blogic_adapter));
2465 myadapter->scsi_host = host;
2466 myadapter->host_no = host->host_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002468 Add Host Adapter to the end of the list of registered
2469 BusLogic Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002471 list_add_tail(&myadapter->host_list, &blogic_host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
2473 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002474 Read the Host Adapter Configuration, Configure the Host
2475 Adapter, Acquire the System Resources necessary to use
2476 the Host Adapter, then Create the Initial CCBs, Initialize
2477 the Host Adapter, and finally perform Target Device
2478 Inquiry. From this point onward, any failure will be
2479 assumed to be due to a problem with the Host Adapter,
2480 rather than due to having mistakenly identified this port
2481 as belonging to a BusLogic Host Adapter. The I/O Address
2482 range will not be released, thereby preventing it from
2483 being incorrectly identified as any other type of Host
2484 Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002486 if (blogic_rdconfig(myadapter) &&
2487 blogic_reportconfig(myadapter) &&
2488 blogic_getres(myadapter) &&
2489 blogic_create_initccbs(myadapter) &&
2490 blogic_initadapter(myadapter) &&
2491 blogic_inquiry(myadapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002493 Initialization has been completed successfully.
2494 Release and re-register usage of the I/O Address
2495 range so that the Model Name of the Host Adapter
2496 will appear, and initialize the SCSI Host structure.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002498 release_region(myadapter->io_addr,
2499 myadapter->addr_count);
2500 if (!request_region(myadapter->io_addr,
2501 myadapter->addr_count,
2502 myadapter->full_model)) {
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002503 printk(KERN_WARNING
2504 "BusLogic: Release and re-register of "
2505 "port 0x%04lx failed \n",
Khalid Aziz839cb992013-05-16 19:44:13 -06002506 (unsigned long)myadapter->io_addr);
2507 blogic_destroy_ccbs(myadapter);
2508 blogic_relres(myadapter);
2509 list_del(&myadapter->host_list);
2510 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002511 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002513 blogic_inithoststruct(myadapter,
2514 host);
2515 if (scsi_add_host(host, myadapter->pci_device
2516 ? &myadapter->pci_device->dev
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002517 : NULL)) {
2518 printk(KERN_WARNING
2519 "BusLogic: scsi_add_host()"
2520 "failed!\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06002521 blogic_destroy_ccbs(myadapter);
2522 blogic_relres(myadapter);
2523 list_del(&myadapter->host_list);
2524 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002525 ret = -ENODEV;
2526 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002527 scsi_scan_host(host);
2528 adapter_count++;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 }
2531 } else {
2532 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002533 An error occurred during Host Adapter Configuration
2534 Querying, Host Adapter Configuration, Resource
2535 Acquisition, CCB Creation, Host Adapter
2536 Initialization, or Target Device Inquiry, so
2537 remove Host Adapter from the list of registered
2538 BusLogic Host Adapters, destroy the CCBs, Release
2539 the System Resources, and Unregister the SCSI
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 Host.
2541 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002542 blogic_destroy_ccbs(myadapter);
2543 blogic_relres(myadapter);
2544 list_del(&myadapter->host_list);
2545 scsi_host_put(host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002546 ret = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 }
2548 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002549 kfree(adapter);
2550 kfree(blogic_probeinfo_list);
2551 blogic_probeinfo_list = NULL;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002552 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553}
2554
2555
2556/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002557 blogic_deladapter releases all resources previously acquired to
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 support a specific Host Adapter, including the I/O Address range, and
2559 unregisters the BusLogic Host Adapter.
2560*/
2561
Khalid Aziz839cb992013-05-16 19:44:13 -06002562static int __exit blogic_deladapter(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563{
Khalid Aziz839cb992013-05-16 19:44:13 -06002564 struct Scsi_Host *host = adapter->scsi_host;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Khalid Aziz839cb992013-05-16 19:44:13 -06002566 scsi_remove_host(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
2568 /*
2569 FlashPoint Host Adapters must first be released by the FlashPoint
2570 SCCB Manager.
2571 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002572 if (blogic_flashpoint_type(adapter))
2573 FlashPoint_ReleaseHostAdapter(adapter->cardhandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 /*
2575 Destroy the CCBs and release any system resources acquired to
2576 support Host Adapter.
2577 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002578 blogic_destroy_ccbs(adapter);
2579 blogic_relres(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 /*
2581 Release usage of the I/O Address range.
2582 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002583 release_region(adapter->io_addr, adapter->addr_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002585 Remove Host Adapter from the list of registered BusLogic
2586 Host Adapters.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002588 list_del(&adapter->host_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
Khalid Aziz839cb992013-05-16 19:44:13 -06002590 scsi_host_put(host);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return 0;
2592}
2593
2594
2595/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002596 blogic_qcompleted_ccb queues CCB for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597*/
2598
Khalid Aziz839cb992013-05-16 19:44:13 -06002599static void blogic_qcompleted_ccb(struct blogic_ccb *ccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600{
Khalid Aziz839cb992013-05-16 19:44:13 -06002601 struct blogic_adapter *adapter = ccb->adapter;
2602
2603 ccb->status = BLOGIC_CCB_COMPLETE;
2604 ccb->next = NULL;
2605 if (adapter->firstccb == NULL) {
2606 adapter->firstccb = ccb;
2607 adapter->lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06002609 adapter->lastccb->next = ccb;
2610 adapter->lastccb = ccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002612 adapter->active_cmds[ccb->tgt_id]--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613}
2614
2615
2616/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002617 blogic_resultcode computes a SCSI Subsystem Result Code from
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 the Host Adapter Status and Target Device Status.
2619*/
2620
Khalid Aziz839cb992013-05-16 19:44:13 -06002621static int blogic_resultcode(struct blogic_adapter *adapter,
2622 enum blogic_adapter_status adapter_status,
2623 enum blogic_tgt_status tgt_status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624{
Khalid Aziz839cb992013-05-16 19:44:13 -06002625 int hoststatus;
2626
2627 switch (adapter_status) {
2628 case BLOGIC_CMD_CMPLT_NORMAL:
2629 case BLOGIC_LINK_CMD_CMPLT:
2630 case BLOGIC_LINK_CMD_CMPLT_FLAG:
2631 hoststatus = DID_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002633 case BLOGIC_SELECT_TIMEOUT:
2634 hoststatus = DID_TIME_OUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002636 case BLOGIC_INVALID_OUTBOX_CODE:
2637 case BLOGIC_INVALID_CMD_CODE:
2638 case BLOGIC_BAD_CMD_PARAM:
2639 blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
2640 adapter, adapter_status);
2641 case BLOGIC_DATA_UNDERRUN:
2642 case BLOGIC_DATA_OVERRUN:
2643 case BLOGIC_NOEXPECT_BUSFREE:
2644 case BLOGIC_LINKCCB_BADLUN:
2645 case BLOGIC_AUTOREQSENSE_FAIL:
2646 case BLOGIC_TAGQUEUE_REJECT:
2647 case BLOGIC_BAD_MSG_RCVD:
2648 case BLOGIC_HW_FAIL:
2649 case BLOGIC_BAD_RECONNECT:
2650 case BLOGIC_ABRT_QUEUE:
2651 case BLOGIC_ADAPTER_SW_ERROR:
2652 case BLOGIC_HW_TIMEOUT:
2653 case BLOGIC_PARITY_ERR:
2654 hoststatus = DID_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002656 case BLOGIC_INVALID_BUSPHASE:
2657 case BLOGIC_NORESPONSE_TO_ATN:
2658 case BLOGIC_HW_RESET:
2659 case BLOGIC_RST_FROM_OTHERDEV:
2660 case BLOGIC_HW_BDR:
2661 hoststatus = DID_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 break;
2663 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06002664 blogic_warn("Unknown Host Adapter Status 0x%02X\n", adapter,
2665 adapter_status);
2666 hoststatus = DID_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 break;
2668 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002669 return (hoststatus << 16) | tgt_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670}
2671
2672
2673/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002674 blogic_scan_inbox scans the Incoming Mailboxes saving any
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 Incoming Mailbox entries for completion processing.
2676*/
2677
Khalid Aziz839cb992013-05-16 19:44:13 -06002678static void blogic_scan_inbox(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679{
2680 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002681 Scan through the Incoming Mailboxes in Strict Round Robin
2682 fashion, saving any completed CCBs for further processing. It
2683 is essential that for each CCB and SCSI Command issued, command
2684 completion processing is performed exactly once. Therefore,
2685 only Incoming Mailboxes with completion code Command Completed
2686 Without Error, Command Completed With Error, or Command Aborted
2687 At Host Request are saved for completion processing. When an
2688 Incoming Mailbox has a completion code of Aborted Command Not
2689 Found, the CCB had already completed or been aborted before the
2690 current Abort request was processed, and so completion processing
2691 has already occurred and no further action should be taken.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002693 struct blogic_inbox *next_inbox = adapter->next_inbox;
2694 enum blogic_cmplt_code comp_code;
2695
2696 while ((comp_code = next_inbox->comp_code) != BLOGIC_INBOX_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002698 We are only allowed to do this because we limit our
2699 architectures we run on to machines where bus_to_virt(
2700 actually works. There *needs* to be a dma_addr_to_virt()
2701 in the new PCI DMA mapping interface to replace
2702 bus_to_virt() or else this code is going to become very
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 innefficient.
2704 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002705 struct blogic_ccb *ccb =
2706 (struct blogic_ccb *) bus_to_virt(next_inbox->ccb);
2707 if (comp_code != BLOGIC_CMD_NOTFOUND) {
2708 if (ccb->status == BLOGIC_CCB_ACTIVE ||
2709 ccb->status == BLOGIC_CCB_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002711 Save the Completion Code for this CCB and
2712 queue the CCB for completion processing.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002714 ccb->comp_code = comp_code;
2715 blogic_qcompleted_ccb(ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 } else {
2717 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002718 If a CCB ever appears in an Incoming Mailbox
2719 and is not marked as status Active or Reset,
2720 then there is most likely a bug in
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 the Host Adapter firmware.
2722 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002723 blogic_warn("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 }
2725 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002726 next_inbox->comp_code = BLOGIC_INBOX_FREE;
2727 if (++next_inbox > adapter->last_inbox)
2728 next_inbox = adapter->first_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002730 adapter->next_inbox = next_inbox;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731}
2732
2733
2734/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002735 blogic_process_ccbs iterates over the completed CCBs for Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
2737 calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
2738 should already have been acquired by the caller.
2739*/
2740
Khalid Aziz839cb992013-05-16 19:44:13 -06002741static void blogic_process_ccbs(struct blogic_adapter *adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742{
Khalid Aziz839cb992013-05-16 19:44:13 -06002743 if (adapter->processing_ccbs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 return;
Khalid Aziz839cb992013-05-16 19:44:13 -06002745 adapter->processing_ccbs = true;
2746 while (adapter->firstccb != NULL) {
2747 struct blogic_ccb *ccb = adapter->firstccb;
2748 struct scsi_cmnd *command = ccb->command;
2749 adapter->firstccb = ccb->next;
2750 if (adapter->firstccb == NULL)
2751 adapter->lastccb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 /*
2753 Process the Completed CCB.
2754 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002755 if (ccb->opcode == BLOGIC_BDR) {
2756 int tgt_id = ccb->tgt_id;
2757
2758 blogic_warn("Bus Device Reset CCB #%ld to Target " "%d Completed\n", adapter, ccb->serial, tgt_id);
2759 blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
2760 adapter->tgt_flags[tgt_id].tagq_active = false;
2761 adapter->cmds_since_rst[tgt_id] = 0;
2762 adapter->last_resetdone[tgt_id] = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 /*
2764 Place CCB back on the Host Adapter's free list.
2765 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002766 blogic_dealloc_ccb(ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767#if 0 /* this needs to be redone different for new EH */
2768 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002769 Bus Device Reset CCBs have the command field
2770 non-NULL only when a Bus Device Reset was requested
2771 for a command that did not have a currently active
2772 CCB in the Host Adapter (i.e., a Synchronous Bus
2773 Device Reset), and hence would not have its
2774 Completion Routine called otherwise.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002776 while (command != NULL) {
2777 struct scsi_cmnd *nxt_cmd =
2778 command->reset_chain;
2779 command->reset_chain = NULL;
2780 command->result = DID_RESET << 16;
2781 command->scsi_done(command);
2782 command = nxt_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 }
2784#endif
2785 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002786 Iterate over the CCBs for this Host Adapter
2787 performing completion processing for any CCBs
2788 marked as Reset for this Target.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002790 for (ccb = adapter->all_ccbs; ccb != NULL;
2791 ccb = ccb->next_all)
2792 if (ccb->status == BLOGIC_CCB_RESET &&
2793 ccb->tgt_id == tgt_id) {
2794 command = ccb->command;
2795 blogic_dealloc_ccb(ccb);
2796 adapter->active_cmds[tgt_id]--;
2797 command->result = DID_RESET << 16;
2798 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002800 adapter->bdr_pend[tgt_id] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 } else {
2802 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002803 Translate the Completion Code, Host Adapter Status,
2804 and Target Device Status into a SCSI Subsystem
2805 Result Code.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002807 switch (ccb->comp_code) {
2808 case BLOGIC_INBOX_FREE:
2809 case BLOGIC_CMD_NOTFOUND:
2810 case BLOGIC_INVALID_CCB:
2811 blogic_warn("CCB #%ld to Target %d Impossible State\n", adapter, ccb->serial, ccb->tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002813 case BLOGIC_CMD_COMPLETE_GOOD:
2814 adapter->tgt_stats[ccb->tgt_id]
2815 .cmds_complete++;
2816 adapter->tgt_flags[ccb->tgt_id]
2817 .cmd_good = true;
2818 command->result = DID_OK << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002820 case BLOGIC_CMD_ABORT_BY_HOST:
2821 blogic_warn("CCB #%ld to Target %d Aborted\n",
2822 adapter, ccb->serial, ccb->tgt_id);
2823 blogic_inc_count(&adapter->tgt_stats[ccb->tgt_id].aborts_done);
2824 command->result = DID_ABORT << 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002826 case BLOGIC_CMD_COMPLETE_ERROR:
2827 command->result = blogic_resultcode(adapter,
2828 ccb->adapter_status, ccb->tgt_status);
2829 if (ccb->adapter_status != BLOGIC_SELECT_TIMEOUT) {
2830 adapter->tgt_stats[ccb->tgt_id]
2831 .cmds_complete++;
2832 if (blogic_global_options.trace_err) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 int i;
Khalid Aziz839cb992013-05-16 19:44:13 -06002834 blogic_notice("CCB #%ld Target %d: Result %X Host "
2835 "Adapter Status %02X " "Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
2836 blogic_notice("CDB ", adapter);
2837 for (i = 0; i < ccb->cdblen; i++)
2838 blogic_notice(" %02X", adapter, ccb->cdb[i]);
2839 blogic_notice("\n", adapter);
2840 blogic_notice("Sense ", adapter);
2841 for (i = 0; i < ccb->sense_datalen; i++)
2842 blogic_notice(" %02X", adapter, command->sense_buffer[i]);
2843 blogic_notice("\n", adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 }
2845 }
2846 break;
2847 }
2848 /*
2849 When an INQUIRY command completes normally, save the
2850 CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
2851 Wide Data Transfers Supported) bits.
2852 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002853 if (ccb->cdb[0] == INQUIRY && ccb->cdb[1] == 0 &&
2854 ccb->adapter_status == BLOGIC_CMD_CMPLT_NORMAL) {
2855 struct blogic_tgt_flags *tgt_flags =
2856 &adapter->tgt_flags[ccb->tgt_id];
2857 struct scsi_inquiry *inquiry =
2858 (struct scsi_inquiry *) scsi_sglist(command);
2859 tgt_flags->tgt_exists = true;
2860 tgt_flags->tagq_ok = inquiry->CmdQue;
2861 tgt_flags->wide_ok = inquiry->WBus16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 }
2863 /*
2864 Place CCB back on the Host Adapter's free list.
2865 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002866 blogic_dealloc_ccb(ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 /*
2868 Call the SCSI Command Completion Routine.
2869 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002870 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 }
2872 }
Khalid Aziz839cb992013-05-16 19:44:13 -06002873 adapter->processing_ccbs = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874}
2875
2876
2877/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002878 blogic_inthandler handles hardware interrupts from BusLogic Host
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879 Adapters.
2880*/
2881
Khalid Aziz839cb992013-05-16 19:44:13 -06002882static irqreturn_t blogic_inthandler(int irq_ch, void *devid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883{
Khalid Aziz839cb992013-05-16 19:44:13 -06002884 struct blogic_adapter *adapter = (struct blogic_adapter *) devid;
2885 unsigned long processor_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 /*
2887 Acquire exclusive access to Host Adapter.
2888 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002889 spin_lock_irqsave(adapter->scsi_host->host_lock, processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 /*
2891 Handle Interrupts appropriately for each Host Adapter type.
2892 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002893 if (blogic_multimaster_type(adapter)) {
2894 union blogic_int_reg intreg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895 /*
2896 Read the Host Adapter Interrupt Register.
2897 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002898 intreg.all = blogic_rdint(adapter);
2899 if (intreg.ir.int_valid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 /*
2901 Acknowledge the interrupt and reset the Host Adapter
2902 Interrupt Register.
2903 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002904 blogic_intreset(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002906 Process valid External SCSI Bus Reset and Incoming
2907 Mailbox Loaded Interrupts. Command Complete
2908 Interrupts are noted, and Outgoing Mailbox Available
2909 Interrupts are ignored, as they are never enabled.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002911 if (intreg.ir.ext_busreset)
2912 adapter->adapter_extreset = true;
2913 else if (intreg.ir.mailin_loaded)
2914 blogic_scan_inbox(adapter);
2915 else if (intreg.ir.cmd_complete)
2916 adapter->adapter_cmd_complete = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917 }
2918 } else {
2919 /*
2920 Check if there is a pending interrupt for this Host Adapter.
2921 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002922 if (FlashPoint_InterruptPending(adapter->cardhandle))
2923 switch (FlashPoint_HandleInterrupt(adapter->cardhandle)) {
2924 case FPOINT_NORMAL_INT:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002926 case FPOINT_EXT_RESET:
2927 adapter->adapter_extreset = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06002929 case FPOINT_INTERN_ERR:
2930 blogic_warn("Internal FlashPoint Error detected - Resetting Host Adapter\n", adapter);
2931 adapter->adapter_intern_err = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 break;
2933 }
2934 }
2935 /*
2936 Process any completed CCBs.
2937 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002938 if (adapter->firstccb != NULL)
2939 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 /*
2941 Reset the Host Adapter if requested.
2942 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002943 if (adapter->adapter_extreset) {
2944 blogic_warn("Resetting %s due to External SCSI Bus Reset\n", adapter, adapter->full_model);
2945 blogic_inc_count(&adapter->ext_resets);
2946 blogic_resetadapter(adapter, false);
2947 adapter->adapter_extreset = false;
2948 } else if (adapter->adapter_intern_err) {
2949 blogic_warn("Resetting %s due to Host Adapter Internal Error\n", adapter, adapter->full_model);
2950 blogic_inc_count(&adapter->adapter_intern_errors);
2951 blogic_resetadapter(adapter, true);
2952 adapter->adapter_intern_err = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 }
2954 /*
2955 Release exclusive access to Host Adapter.
2956 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002957 spin_unlock_irqrestore(adapter->scsi_host->host_lock, processor_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 return IRQ_HANDLED;
2959}
2960
2961
2962/*
Khalid Aziz839cb992013-05-16 19:44:13 -06002963 blogic_write_outbox places CCB and Action Code into an Outgoing
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 Mailbox for execution by Host Adapter. The Host Adapter's Lock should
2965 already have been acquired by the caller.
2966*/
2967
Khalid Aziz839cb992013-05-16 19:44:13 -06002968static bool blogic_write_outbox(struct blogic_adapter *adapter,
2969 enum blogic_action action, struct blogic_ccb *ccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970{
Khalid Aziz839cb992013-05-16 19:44:13 -06002971 struct blogic_outbox *next_outbox;
2972
2973 next_outbox = adapter->next_outbox;
2974 if (next_outbox->action == BLOGIC_OUTBOX_FREE) {
2975 ccb->status = BLOGIC_CCB_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06002977 The CCB field must be written before the Action Code field
2978 since the Host Adapter is operating asynchronously and the
2979 locking code does not protect against simultaneous access
2980 by the Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 */
Khalid Aziz839cb992013-05-16 19:44:13 -06002982 next_outbox->ccb = ccb->dma_handle;
2983 next_outbox->action = action;
2984 blogic_execmbox(adapter);
2985 if (++next_outbox > adapter->last_outbox)
2986 next_outbox = adapter->first_outbox;
2987 adapter->next_outbox = next_outbox;
2988 if (action == BLOGIC_MBOX_START) {
2989 adapter->active_cmds[ccb->tgt_id]++;
2990 if (ccb->opcode != BLOGIC_BDR)
2991 adapter->tgt_stats[ccb->tgt_id].cmds_tried++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 }
2993 return true;
2994 }
2995 return false;
2996}
2997
2998/* Error Handling (EH) support */
2999
Khalid Aziz839cb992013-05-16 19:44:13 -06003000static int blogic_hostreset(struct scsi_cmnd *SCpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001{
Khalid Aziz839cb992013-05-16 19:44:13 -06003002 struct blogic_adapter *adapter =
3003 (struct blogic_adapter *) SCpnt->device->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004
3005 unsigned int id = SCpnt->device->id;
Khalid Aziz839cb992013-05-16 19:44:13 -06003006 struct blogic_tgt_stats *stats = &adapter->tgt_stats[id];
Jeff Garzik df0ae242005-05-28 07:57:14 -04003007 int rc;
3008
3009 spin_lock_irq(SCpnt->device->host->host_lock);
3010
Khalid Aziz839cb992013-05-16 19:44:13 -06003011 blogic_inc_count(&stats->adatper_reset_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Khalid Aziz839cb992013-05-16 19:44:13 -06003013 rc = blogic_resetadapter(adapter, false);
Jeff Garzik df0ae242005-05-28 07:57:14 -04003014 spin_unlock_irq(SCpnt->device->host->host_lock);
3015 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016}
3017
3018/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003019 blogic_qcmd creates a CCB for Command and places it into an
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 Outgoing Mailbox for execution by the associated Host Adapter.
3021*/
3022
Khalid Aziz839cb992013-05-16 19:44:13 -06003023static int blogic_qcmd_lck(struct scsi_cmnd *command,
3024 void (*comp_cb) (struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025{
Khalid Aziz839cb992013-05-16 19:44:13 -06003026 struct blogic_adapter *adapter =
3027 (struct blogic_adapter *) command->device->host->hostdata;
3028 struct blogic_tgt_flags *tgt_flags =
3029 &adapter->tgt_flags[command->device->id];
3030 struct blogic_tgt_stats *tgt_stats = adapter->tgt_stats;
3031 unsigned char *cdb = command->cmnd;
3032 int cdblen = command->cmd_len;
3033 int tgt_id = command->device->id;
3034 int lun = command->device->lun;
3035 int buflen = scsi_bufflen(command);
3036 int count;
3037 struct blogic_ccb *ccb;
3038
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003040 SCSI REQUEST_SENSE commands will be executed automatically by the
3041 Host Adapter for any errors, so they should not be executed
3042 explicitly unless the Sense Data is zero indicating that no error
3043 occurred.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003045 if (cdb[0] == REQUEST_SENSE && command->sense_buffer[0] != 0) {
3046 command->result = DID_OK << 16;
3047 comp_cb(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 return 0;
3049 }
3050 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003051 Allocate a CCB from the Host Adapter's free list. In the unlikely
3052 event that there are none available and memory allocation fails,
3053 wait 1 second and try again. If that fails, the Host Adapter is
3054 probably hung so signal an error as a Host Adapter Hard Reset
3055 should be initiated soon.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003057 ccb = blogic_alloc_ccb(adapter);
3058 if (ccb == NULL) {
3059 spin_unlock_irq(adapter->scsi_host->host_lock);
3060 blogic_delay(1);
3061 spin_lock_irq(adapter->scsi_host->host_lock);
3062 ccb = blogic_alloc_ccb(adapter);
3063 if (ccb == NULL) {
3064 command->result = DID_ERROR << 16;
3065 comp_cb(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 return 0;
3067 }
3068 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003069
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 /*
3071 Initialize the fields in the BusLogic Command Control Block (CCB).
3072 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003073 count = scsi_dma_map(command);
3074 BUG_ON(count < 0);
3075 if (count) {
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003076 struct scatterlist *sg;
3077 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
Khalid Aziz839cb992013-05-16 19:44:13 -06003079 ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
3080 ccb->datalen = count * sizeof(struct blogic_sg_seg);
3081 if (blogic_multimaster_type(adapter))
3082 ccb->data = (unsigned int) ccb->dma_handle +
3083 ((unsigned long) &ccb->sglist -
3084 (unsigned long) ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003086 ccb->data = virt_to_32bit_virt(ccb->sglist);
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003087
Khalid Aziz839cb992013-05-16 19:44:13 -06003088 scsi_for_each_sg(command, sg, count, i) {
3089 ccb->sglist[i].segbytes = sg_dma_len(sg);
3090 ccb->sglist[i].segdata = sg_dma_address(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003092 } else if (!count) {
3093 ccb->opcode = BLOGIC_INITIATOR_CCB;
3094 ccb->datalen = buflen;
3095 ccb->data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09003097
Khalid Aziz839cb992013-05-16 19:44:13 -06003098 switch (cdb[0]) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 case READ_6:
3100 case READ_10:
Khalid Aziz839cb992013-05-16 19:44:13 -06003101 ccb->datadir = BLOGIC_DATAIN_CHECKED;
3102 tgt_stats[tgt_id].read_cmds++;
3103 blogic_addcount(&tgt_stats[tgt_id].bytesread, buflen);
3104 blogic_incszbucket(tgt_stats[tgt_id].read_sz_buckets, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 break;
3106 case WRITE_6:
3107 case WRITE_10:
Khalid Aziz839cb992013-05-16 19:44:13 -06003108 ccb->datadir = BLOGIC_DATAOUT_CHECKED;
3109 tgt_stats[tgt_id].write_cmds++;
3110 blogic_addcount(&tgt_stats[tgt_id].byteswritten, buflen);
3111 blogic_incszbucket(tgt_stats[tgt_id].write_sz_buckets, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 break;
3113 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06003114 ccb->datadir = BLOGIC_UNCHECKED_TX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 break;
3116 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003117 ccb->cdblen = cdblen;
3118 ccb->adapter_status = 0;
3119 ccb->tgt_status = 0;
3120 ccb->tgt_id = tgt_id;
3121 ccb->lun = lun;
3122 ccb->tag_enable = false;
3123 ccb->legacytag_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003125 BusLogic recommends that after a Reset the first couple of
3126 commands that are sent to a Target Device be sent in a non
3127 Tagged Queue fashion so that the Host Adapter and Target Device
3128 can establish Synchronous and Wide Transfer before Queue Tag
3129 messages can interfere with the Synchronous and Wide Negotiation
3130 messages. By waiting to enable Tagged Queuing until after the
3131 first BLOGIC_MAX_TAG_DEPTH commands have been queued, it is
3132 assured that after a Reset any pending commands are requeued
3133 before Tagged Queuing is enabled and that the Tagged Queuing
3134 message will not occur while the partition table is being printed.
3135 In addition, some devices do not properly handle the transition
3136 from non-tagged to tagged commands, so it is necessary to wait
3137 until there are no pending commands for a target device
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 before queuing tagged commands.
3139 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003140 if (adapter->cmds_since_rst[tgt_id]++ >= BLOGIC_MAX_TAG_DEPTH &&
3141 !tgt_flags->tagq_active &&
3142 adapter->active_cmds[tgt_id] == 0
3143 && tgt_flags->tagq_ok &&
3144 (adapter->tagq_ok & (1 << tgt_id))) {
3145 tgt_flags->tagq_active = true;
3146 blogic_notice("Tagged Queuing now active for Target %d\n",
3147 adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003149 if (tgt_flags->tagq_active) {
3150 enum blogic_queuetag queuetag = BLOGIC_SIMPLETAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003152 When using Tagged Queuing with Simple Queue Tags, it
3153 appears that disk drive controllers do not guarantee that
3154 a queued command will not remain in a disconnected state
3155 indefinitely if commands that read or write nearer the
3156 head position continue to arrive without interruption.
3157 Therefore, for each Target Device this driver keeps track
3158 of the last time either the queue was empty or an Ordered
3159 Queue Tag was issued. If more than 4 seconds (one fifth
3160 of the 20 second disk timeout) have elapsed since this
3161 last sequence point, this command will be issued with an
3162 Ordered Queue Tag rather than a Simple Queue Tag, which
3163 forces the Target Device to complete all previously
3164 queued commands before this command may be executed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003166 if (adapter->active_cmds[tgt_id] == 0)
3167 adapter->last_seqpoint[tgt_id] = jiffies;
3168 else if (time_after(jiffies,
3169 adapter->last_seqpoint[tgt_id] + 4 * HZ)) {
3170 adapter->last_seqpoint[tgt_id] = jiffies;
3171 queuetag = BLOGIC_ORDEREDTAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003173 if (adapter->ext_lun) {
3174 ccb->tag_enable = true;
3175 ccb->queuetag = queuetag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003177 ccb->legacytag_enable = true;
3178 ccb->legacy_tag = queuetag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 }
3180 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003181 memcpy(ccb->cdb, cdb, cdblen);
3182 ccb->sense_datalen = SCSI_SENSE_BUFFERSIZE;
3183 ccb->sensedata = pci_map_single(adapter->pci_device,
3184 command->sense_buffer, ccb->sense_datalen,
3185 PCI_DMA_FROMDEVICE);
3186 ccb->command = command;
3187 command->scsi_done = comp_cb;
3188 if (blogic_multimaster_type(adapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003190 Place the CCB in an Outgoing Mailbox. The higher levels
3191 of the SCSI Subsystem should not attempt to queue more
3192 commands than can be placed in Outgoing Mailboxes, so
3193 there should always be one free. In the unlikely event
3194 that there are none available, wait 1 second and try
3195 again. If that fails, the Host Adapter is probably hung
3196 so signal an error as a Host Adapter Hard Reset should
3197 be initiated soon.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003199 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
3200 spin_unlock_irq(adapter->scsi_host->host_lock);
3201 blogic_warn("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", adapter);
3202 blogic_delay(1);
3203 spin_lock_irq(adapter->scsi_host->host_lock);
3204 if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
3205 ccb)) {
3206 blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter);
3207 blogic_dealloc_ccb(ccb);
3208 command->result = DID_ERROR << 16;
3209 command->scsi_done(command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 }
3211 }
3212 } else {
3213 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003214 Call the FlashPoint SCCB Manager to start execution of
3215 the CCB.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003217 ccb->status = BLOGIC_CCB_ACTIVE;
3218 adapter->active_cmds[tgt_id]++;
3219 tgt_stats[tgt_id].cmds_tried++;
3220 FlashPoint_StartCCB(adapter->cardhandle, ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003222 The Command may have already completed and
3223 blogic_qcompleted_ccb been called, or it may still be
3224 pending.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003226 if (ccb->status == BLOGIC_CCB_COMPLETE)
3227 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 }
3229 return 0;
3230}
3231
Khalid Aziz839cb992013-05-16 19:44:13 -06003232static DEF_SCSI_QCMD(blogic_qcmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07003234#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003236 blogic_abort aborts Command if possible.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237*/
3238
Khalid Aziz839cb992013-05-16 19:44:13 -06003239static int blogic_abort(struct scsi_cmnd *command)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240{
Khalid Aziz839cb992013-05-16 19:44:13 -06003241 struct blogic_adapter *adapter =
3242 (struct blogic_adapter *) command->device->host->hostdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Khalid Aziz839cb992013-05-16 19:44:13 -06003244 int tgt_id = command->device->id;
3245 struct blogic_ccb *ccb;
3246 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_request);
3247
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003249 Attempt to find an Active CCB for this Command. If no Active
3250 CCB for this Command is found, then no Abort is necessary.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003252 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3253 if (ccb->command == command)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003255 if (ccb == NULL) {
3256 blogic_warn("Unable to Abort Command to Target %d - No CCB Found\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 return SUCCESS;
Khalid Aziz839cb992013-05-16 19:44:13 -06003258 } else if (ccb->status == BLOGIC_CCB_COMPLETE) {
3259 blogic_warn("Unable to Abort Command to Target %d - CCB Completed\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 return SUCCESS;
Khalid Aziz839cb992013-05-16 19:44:13 -06003261 } else if (ccb->status == BLOGIC_CCB_RESET) {
3262 blogic_warn("Unable to Abort Command to Target %d - CCB Reset\n", adapter, tgt_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 return SUCCESS;
3264 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003265 if (blogic_multimaster_type(adapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003267 Attempt to Abort this CCB. MultiMaster Firmware versions
3268 prior to 5.xx do not generate Abort Tag messages, but only
3269 generate the non-tagged Abort message. Since non-tagged
3270 commands are not sent by the Host Adapter until the queue
3271 of outstanding tagged commands has completed, and the
3272 Abort message is treated as a non-tagged command, it is
3273 effectively impossible to abort commands when Tagged
3274 Queuing is active. Firmware version 5.xx does generate
3275 Abort Tag messages, so it is possible to abort commands
3276 when Tagged Queuing is active.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003278 if (adapter->tgt_flags[tgt_id].tagq_active &&
3279 adapter->fw_ver[0] < '5') {
3280 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 -07003281 return FAILURE;
Khalid Aziz839cb992013-05-16 19:44:13 -06003282 } else if (blogic_write_outbox(adapter, BLOGIC_MBOX_ABORT,
3283 ccb)) {
3284 blogic_warn("Aborting CCB #%ld to Target %d\n",
3285 adapter, ccb->serial, tgt_id);
3286 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 return SUCCESS;
3288 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003289 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 -07003290 return FAILURE;
3291 }
3292 } else {
3293 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003294 Call the FlashPoint SCCB Manager to abort execution of
3295 the CCB.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003297 blogic_warn("Aborting CCB #%ld to Target %d\n", adapter,
3298 ccb->serial, tgt_id);
3299 blogic_inc_count(&adapter->tgt_stats[tgt_id].aborts_tried);
3300 FlashPoint_AbortCCB(adapter->cardhandle, ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301 /*
3302 The Abort may have already been completed and
Khalid Aziz839cb992013-05-16 19:44:13 -06003303 blogic_qcompleted_ccb been called, or it
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 may still be pending.
3305 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003306 if (ccb->status == BLOGIC_CCB_COMPLETE)
3307 blogic_process_ccbs(adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308 return SUCCESS;
3309 }
3310 return SUCCESS;
3311}
3312
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07003313#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003315 blogic_resetadapter resets Host Adapter if possible, marking all
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 currently executing SCSI Commands as having been Reset.
3317*/
3318
Khalid Aziz839cb992013-05-16 19:44:13 -06003319static int blogic_resetadapter(struct blogic_adapter *adapter, bool hard_reset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320{
Khalid Aziz839cb992013-05-16 19:44:13 -06003321 struct blogic_ccb *ccb;
3322 int tgt_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
3324 /*
3325 * Attempt to Reset and Reinitialize the Host Adapter.
3326 */
3327
Khalid Aziz839cb992013-05-16 19:44:13 -06003328 if (!(blogic_hwreset(adapter, hard_reset) &&
3329 blogic_initadapter(adapter))) {
3330 blogic_err("Resetting %s Failed\n", adapter,
3331 adapter->full_model);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 return FAILURE;
3333 }
3334
3335 /*
3336 * Deallocate all currently executing CCBs.
3337 */
3338
Khalid Aziz839cb992013-05-16 19:44:13 -06003339 for (ccb = adapter->all_ccbs; ccb != NULL; ccb = ccb->next_all)
3340 if (ccb->status == BLOGIC_CCB_ACTIVE)
3341 blogic_dealloc_ccb(ccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 /*
3343 * Wait a few seconds between the Host Adapter Hard Reset which
3344 * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
3345 * SCSI devices get confused if they receive SCSI Commands too soon
3346 * after a SCSI Bus Reset.
3347 */
3348
Khalid Aziz839cb992013-05-16 19:44:13 -06003349 if (hard_reset) {
3350 spin_unlock_irq(adapter->scsi_host->host_lock);
3351 blogic_delay(adapter->bus_settle_time);
3352 spin_lock_irq(adapter->scsi_host->host_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 }
3354
Khalid Aziz839cb992013-05-16 19:44:13 -06003355 for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++) {
3356 adapter->last_resettried[tgt_id] = jiffies;
3357 adapter->last_resetdone[tgt_id] = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 }
3359 return SUCCESS;
3360}
3361
3362/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003363 blogic_diskparam returns the Heads/Sectors/Cylinders BIOS Disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
3365 the appropriate number of cylinders so as not to exceed drive capacity. In
3366 order for disks equal to or larger than 1 GB to be addressable by the BIOS
3367 without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
3368 may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
3369 series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
3370 series MultiMaster Host Adapters. With Extended Translation enabled, drives
3371 between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
3372 heads and 32 sectors, and drives above 2 GB inclusive are given a disk
3373 geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
3374 Extended Translation setting does not match the geometry in the partition
3375 table, then the translation inferred from the partition table will be used by
3376 the BIOS, and a warning may be displayed.
3377*/
3378
Khalid Aziz839cb992013-05-16 19:44:13 -06003379static int blogic_diskparam(struct scsi_device *sdev, struct block_device *dev,
3380 sector_t capacity, int *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381{
Khalid Aziz839cb992013-05-16 19:44:13 -06003382 struct blogic_adapter *adapter =
3383 (struct blogic_adapter *) sdev->host->hostdata;
3384 struct bios_diskparam *diskparam = (struct bios_diskparam *) params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 unsigned char *buf;
Khalid Aziz839cb992013-05-16 19:44:13 -06003386
3387 if (adapter->ext_trans_enable && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */) {
3388 if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */) {
3389 diskparam->heads = 255;
3390 diskparam->sectors = 63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003392 diskparam->heads = 128;
3393 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 }
3395 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003396 diskparam->heads = 64;
3397 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003399 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3400 buf = scsi_bios_ptable(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 if (buf == NULL)
3402 return 0;
3403 /*
Khalid Aziz839cb992013-05-16 19:44:13 -06003404 If the boot sector partition table flag is valid, search for
3405 a partition table entry whose end_head matches one of the
3406 standard BusLogic geometry translations (64/32, 128/32, or 255/63).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 */
3408 if (*(unsigned short *) (buf + 64) == 0xAA55) {
Khalid Aziz839cb992013-05-16 19:44:13 -06003409 struct partition *part1_entry = (struct partition *) buf;
3410 struct partition *part_entry = part1_entry;
3411 int saved_cyl = diskparam->cylinders, part_no;
3412 unsigned char part_end_head = 0, part_end_sector = 0;
3413
3414 for (part_no = 0; part_no < 4; part_no++) {
3415 part_end_head = part_entry->end_head;
3416 part_end_sector = part_entry->end_sector & 0x3F;
3417 if (part_end_head == 64 - 1) {
3418 diskparam->heads = 64;
3419 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003421 } else if (part_end_head == 128 - 1) {
3422 diskparam->heads = 128;
3423 diskparam->sectors = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 break;
Khalid Aziz839cb992013-05-16 19:44:13 -06003425 } else if (part_end_head == 255 - 1) {
3426 diskparam->heads = 255;
3427 diskparam->sectors = 63;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428 break;
3429 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003430 part_entry++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003432 if (part_no == 4) {
3433 part_end_head = part1_entry->end_head;
3434 part_end_sector = part1_entry->end_sector & 0x3F;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003436 diskparam->cylinders = (unsigned long) capacity / (diskparam->heads * diskparam->sectors);
3437 if (part_no < 4 && part_end_sector == diskparam->sectors) {
3438 if (diskparam->cylinders != saved_cyl)
3439 blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
3440 } else if (part_end_head > 0 || part_end_sector > 0) {
3441 blogic_warn("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
3442 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 -07003443 }
3444 }
3445 kfree(buf);
3446 return 0;
3447}
3448
3449
3450/*
3451 BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
3452*/
3453
Khalid Aziz839cb992013-05-16 19:44:13 -06003454static int blogic_write_info(struct Scsi_Host *shost, char *procbuf,
3455 int bytes_avail)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456{
Khalid Aziz839cb992013-05-16 19:44:13 -06003457 struct blogic_adapter *adapter =
3458 (struct blogic_adapter *) shost->hostdata;
3459 struct blogic_tgt_stats *tgt_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Khalid Aziz839cb992013-05-16 19:44:13 -06003461 tgt_stats = adapter->tgt_stats;
3462 adapter->ext_resets = 0;
3463 adapter->adapter_intern_errors = 0;
3464 memset(tgt_stats, 0, BLOGIC_MAXDEV * sizeof(struct blogic_tgt_stats));
Al Viro25daa962013-03-31 01:52:13 -04003465 return 0;
3466}
3467
Khalid Aziz839cb992013-05-16 19:44:13 -06003468static int blogic_show_info(struct seq_file *m, struct Scsi_Host *shost)
Al Viro25daa962013-03-31 01:52:13 -04003469{
Khalid Aziz839cb992013-05-16 19:44:13 -06003470 struct blogic_adapter *adapter = (struct blogic_adapter *) shost->hostdata;
3471 struct blogic_tgt_stats *tgt_stats;
3472 int tgt;
Al Viro25daa962013-03-31 01:52:13 -04003473
Khalid Aziz839cb992013-05-16 19:44:13 -06003474 tgt_stats = adapter->tgt_stats;
3475 seq_write(m, adapter->msgbuf, adapter->msgbuflen);
Al Viro25daa962013-03-31 01:52:13 -04003476 seq_printf(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477Current Driver Queue Depth: %d\n\
Khalid Aziz839cb992013-05-16 19:44:13 -06003478Currently Allocated CCBs: %d\n", adapter->drvr_qdepth, adapter->alloc_ccbs);
Al Viro25daa962013-03-31 01:52:13 -04003479 seq_printf(m, "\n\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 DATA TRANSFER STATISTICS\n\
3481\n\
3482Target Tagged Queuing Queue Depth Active Attempted Completed\n\
3483====== ============== =========== ====== ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003484 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3485 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3486 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06003488 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 -07003489 ? " Permitted" : " Disabled"))
3490 : "Not Supported"));
Al Viro25daa962013-03-31 01:52:13 -04003491 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003492 " %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 -07003493 }
Al Viro25daa962013-03-31 01:52:13 -04003494 seq_printf(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
3496====== ============= ============== =================== ===================\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003497 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3498 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3499 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 continue;
Khalid Aziz839cb992013-05-16 19:44:13 -06003501 seq_printf(m, " %2d %9u %9u", tgt, tgt_stats[tgt].read_cmds, tgt_stats[tgt].write_cmds);
3502 if (tgt_stats[tgt].bytesread.billions > 0)
3503 seq_printf(m, " %9u%09u", tgt_stats[tgt].bytesread.billions, tgt_stats[tgt].bytesread.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003505 seq_printf(m, " %9u", tgt_stats[tgt].bytesread.units);
3506 if (tgt_stats[tgt].byteswritten.billions > 0)
3507 seq_printf(m, " %9u%09u\n", tgt_stats[tgt].byteswritten.billions, tgt_stats[tgt].byteswritten.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003509 seq_printf(m, " %9u\n", tgt_stats[tgt].byteswritten.units);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 }
Al Viro25daa962013-03-31 01:52:13 -04003511 seq_printf(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
3513====== ======= ========= ========= ========= ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003514 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3515 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3516 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517 continue;
Al Viro25daa962013-03-31 01:52:13 -04003518 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003519 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3520 tgt_stats[tgt].read_sz_buckets[0],
3521 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 -04003522 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003523 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3524 tgt_stats[tgt].write_sz_buckets[0],
3525 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 -07003526 }
Al Viro25daa962013-03-31 01:52:13 -04003527 seq_printf(m, "\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
3529====== ======= ========= ========= ========= ========= =========\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003530 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3531 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3532 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 continue;
Al Viro25daa962013-03-31 01:52:13 -04003534 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003535 " %2d Read %9u %9u %9u %9u %9u\n", tgt,
3536 tgt_stats[tgt].read_sz_buckets[5],
3537 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 -04003538 seq_printf(m,
Khalid Aziz839cb992013-05-16 19:44:13 -06003539 " %2d Write %9u %9u %9u %9u %9u\n", tgt,
3540 tgt_stats[tgt].write_sz_buckets[5],
3541 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 -07003542 }
Al Viro25daa962013-03-31 01:52:13 -04003543 seq_printf(m, "\n\n\
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 ERROR RECOVERY STATISTICS\n\
3545\n\
3546 Command Aborts Bus Device Resets Host Adapter Resets\n\
3547Target Requested Completed Requested Completed Requested Completed\n\
3548 ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
3549====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
Khalid Aziz839cb992013-05-16 19:44:13 -06003550 for (tgt = 0; tgt < adapter->maxdev; tgt++) {
3551 struct blogic_tgt_flags *tgt_flags = &adapter->tgt_flags[tgt];
3552 if (!tgt_flags->tgt_exists)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 continue;
Al Viro25daa962013-03-31 01:52:13 -04003554 seq_printf(m, "\
Khalid Aziz839cb992013-05-16 19:44:13 -06003555 %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", tgt, tgt_stats[tgt].aborts_request, tgt_stats[tgt].aborts_tried, tgt_stats[tgt].aborts_done, tgt_stats[tgt].bdr_request, tgt_stats[tgt].bdr_tried, tgt_stats[tgt].bdr_done, tgt_stats[tgt].adatper_reset_req, tgt_stats[tgt].adapter_reset_attempt, tgt_stats[tgt].adapter_reset_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003557 seq_printf(m, "\nExternal Host Adapter Resets: %d\n", adapter->ext_resets);
3558 seq_printf(m, "Host Adapter Internal Errors: %d\n", adapter->adapter_intern_errors);
Al Viro25daa962013-03-31 01:52:13 -04003559 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560}
3561
3562
3563/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003564 blogic_msg prints Driver Messages.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565*/
3566
Khalid Aziz839cb992013-05-16 19:44:13 -06003567static void blogic_msg(enum blogic_msglevel msglevel, char *fmt,
3568 struct blogic_adapter *adapter, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569{
Khalid Aziz839cb992013-05-16 19:44:13 -06003570 static char buf[BLOGIC_LINEBUF_SIZE];
3571 static bool begin = true;
3572 va_list args;
3573 int len = 0;
3574
3575 va_start(args, adapter);
3576 len = vsprintf(buf, fmt, args);
3577 va_end(args);
3578 if (msglevel == BLOGIC_ANNOUNCE_LEVEL) {
3579 static int msglines = 0;
3580 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3581 adapter->msgbuflen += len;
3582 if (++msglines <= 2)
3583 printk("%sscsi: %s", blogic_msglevelmap[msglevel], buf);
3584 } else if (msglevel == BLOGIC_INFO_LEVEL) {
3585 strcpy(&adapter->msgbuf[adapter->msgbuflen], buf);
3586 adapter->msgbuflen += len;
3587 if (begin) {
3588 if (buf[0] != '\n' || len > 1)
3589 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06003591 printk("%s", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003593 if (begin) {
3594 if (adapter != NULL && adapter->adapter_initd)
3595 printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 else
Khalid Aziz839cb992013-05-16 19:44:13 -06003597 printk("%s%s", blogic_msglevelmap[msglevel], buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06003599 printk("%s", buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003601 begin = (buf[len - 1] == '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602}
3603
3604
3605/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003606 blogic_parse parses an individual option keyword. It returns true
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 and updates the pointer if the keyword is recognized and false otherwise.
3608*/
3609
Khalid Aziz839cb992013-05-16 19:44:13 -06003610static bool __init blogic_parse(char **str, char *keyword)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611{
Khalid Aziz839cb992013-05-16 19:44:13 -06003612 char *pointer = *str;
3613 while (*keyword != '\0') {
3614 char strch = *pointer++;
3615 char keywordch = *keyword++;
3616 if (strch >= 'A' && strch <= 'Z')
3617 strch += 'a' - 'Z';
3618 if (keywordch >= 'A' && keywordch <= 'Z')
3619 keywordch += 'a' - 'Z';
3620 if (strch != keywordch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 return false;
3622 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003623 *str = pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 return true;
3625}
3626
3627
3628/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003629 blogic_parseopts handles processing of BusLogic Driver Options
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 specifications.
3631
3632 BusLogic Driver Options may be specified either via the Linux Kernel Command
3633 Line or via the Loadable Kernel Module Installation Facility. Driver Options
3634 for multiple host adapters may be specified either by separating the option
3635 strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
3636 command line. Individual option specifications for a single host adapter are
3637 separated by commas. The Probing and Debugging Options apply to all host
3638 adapters whereas the remaining options apply individually only to the
3639 selected host adapter.
3640
3641 The BusLogic Driver Probing Options are described in
3642 <file:Documentation/scsi/BusLogic.txt>.
3643*/
3644
Khalid Aziz839cb992013-05-16 19:44:13 -06003645static int __init blogic_parseopts(char *options)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646{
3647 while (true) {
Khalid Aziz839cb992013-05-16 19:44:13 -06003648 struct blogic_drvr_options *drvr_opts =
3649 &blogic_drvr_options[blogic_drvr_options_count++];
3650 int tgt_id;
3651
3652 memset(drvr_opts, 0, sizeof(struct blogic_drvr_options));
3653 while (*options != '\0' && *options != ';') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 /* Probing Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003655 if (blogic_parse(&options, "IO:")) {
3656 unsigned long io_addr = simple_strtoul(options,
3657 &options, 0);
3658 blogic_probe_options.limited_isa = true;
3659 switch (io_addr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 case 0x330:
Khalid Aziz839cb992013-05-16 19:44:13 -06003661 blogic_probe_options.probe330 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 break;
3663 case 0x334:
Khalid Aziz839cb992013-05-16 19:44:13 -06003664 blogic_probe_options.probe334 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 break;
3666 case 0x230:
Khalid Aziz839cb992013-05-16 19:44:13 -06003667 blogic_probe_options.probe230 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668 break;
3669 case 0x234:
Khalid Aziz839cb992013-05-16 19:44:13 -06003670 blogic_probe_options.probe234 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 break;
3672 case 0x130:
Khalid Aziz839cb992013-05-16 19:44:13 -06003673 blogic_probe_options.probe130 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674 break;
3675 case 0x134:
Khalid Aziz839cb992013-05-16 19:44:13 -06003676 blogic_probe_options.probe134 = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 break;
3678 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06003679 blogic_err("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, io_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680 return 0;
3681 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003682 } else if (blogic_parse(&options, "NoProbeISA"))
3683 blogic_probe_options.noprobe_isa = true;
3684 else if (blogic_parse(&options, "NoProbePCI"))
3685 blogic_probe_options.noprobe_pci = true;
3686 else if (blogic_parse(&options, "NoProbe"))
3687 blogic_probe_options.noprobe = true;
3688 else if (blogic_parse(&options, "NoSortPCI"))
3689 blogic_probe_options.nosort_pci = true;
3690 else if (blogic_parse(&options, "MultiMasterFirst"))
3691 blogic_probe_options.multimaster_first = true;
3692 else if (blogic_parse(&options, "FlashPointFirst"))
3693 blogic_probe_options.flashpoint_first = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 /* Tagged Queuing Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003695 else if (blogic_parse(&options, "QueueDepth:[") ||
3696 blogic_parse(&options, "QD:[")) {
3697 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
3698 unsigned short qdepth = simple_strtoul(options, &options, 0);
3699 if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
3700 blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 return 0;
3702 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003703 drvr_opts->qdepth[tgt_id] = qdepth;
3704 if (*options == ',')
3705 options++;
3706 else if (*options == ']')
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 break;
3708 else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003709 blogic_err("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 return 0;
3711 }
3712 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003713 if (*options != ']') {
3714 blogic_err("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, options);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 return 0;
3716 } else
Khalid Aziz839cb992013-05-16 19:44:13 -06003717 options++;
3718 } else if (blogic_parse(&options, "QueueDepth:") || blogic_parse(&options, "QD:")) {
3719 unsigned short qdepth = simple_strtoul(options, &options, 0);
3720 if (qdepth == 0 ||
3721 qdepth > BLOGIC_MAX_TAG_DEPTH) {
3722 blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 return 0;
3724 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003725 drvr_opts->common_qdepth = qdepth;
3726 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3727 drvr_opts->qdepth[tgt_id] = qdepth;
3728 } else if (blogic_parse(&options, "TaggedQueuing:") ||
3729 blogic_parse(&options, "TQ:")) {
3730 if (blogic_parse(&options, "Default")) {
3731 drvr_opts->tagq_ok = 0x0000;
3732 drvr_opts->tagq_ok_mask = 0x0000;
3733 } else if (blogic_parse(&options, "Enable")) {
3734 drvr_opts->tagq_ok = 0xFFFF;
3735 drvr_opts->tagq_ok_mask = 0xFFFF;
3736 } else if (blogic_parse(&options, "Disable")) {
3737 drvr_opts->tagq_ok = 0x0000;
3738 drvr_opts->tagq_ok_mask = 0xFFFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 } else {
Khalid Aziz839cb992013-05-16 19:44:13 -06003740 unsigned short tgt_bit;
3741 for (tgt_id = 0, tgt_bit = 1;
3742 tgt_id < BLOGIC_MAXDEV;
3743 tgt_id++, tgt_bit <<= 1)
3744 switch (*options++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 case 'Y':
Khalid Aziz839cb992013-05-16 19:44:13 -06003746 drvr_opts->tagq_ok |= tgt_bit;
3747 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 break;
3749 case 'N':
Khalid Aziz839cb992013-05-16 19:44:13 -06003750 drvr_opts->tagq_ok &= ~tgt_bit;
3751 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 break;
3753 case 'X':
3754 break;
3755 default:
Khalid Aziz839cb992013-05-16 19:44:13 -06003756 options--;
3757 tgt_id = BLOGIC_MAXDEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 break;
3759 }
3760 }
3761 }
3762 /* Miscellaneous Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003763 else if (blogic_parse(&options, "BusSettleTime:") ||
3764 blogic_parse(&options, "BST:")) {
3765 unsigned short bus_settle_time =
3766 simple_strtoul(options, &options, 0);
3767 if (bus_settle_time > 5 * 60) {
3768 blogic_err("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 return 0;
3770 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003771 drvr_opts->bus_settle_time = bus_settle_time;
3772 } else if (blogic_parse(&options,
3773 "InhibitTargetInquiry"))
3774 drvr_opts->stop_tgt_inquiry = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 /* Debugging Options. */
Khalid Aziz839cb992013-05-16 19:44:13 -06003776 else if (blogic_parse(&options, "TraceProbe"))
3777 blogic_global_options.trace_probe = true;
3778 else if (blogic_parse(&options, "TraceHardwareReset"))
3779 blogic_global_options.trace_hw_reset = true;
3780 else if (blogic_parse(&options, "TraceConfiguration"))
3781 blogic_global_options.trace_config = true;
3782 else if (blogic_parse(&options, "TraceErrors"))
3783 blogic_global_options.trace_err = true;
3784 else if (blogic_parse(&options, "Debug")) {
3785 blogic_global_options.trace_probe = true;
3786 blogic_global_options.trace_hw_reset = true;
3787 blogic_global_options.trace_config = true;
3788 blogic_global_options.trace_err = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003790 if (*options == ',')
3791 options++;
3792 else if (*options != ';' && *options != '\0') {
3793 blogic_err("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, options);
3794 *options = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 }
3796 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003797 if (!(blogic_drvr_options_count == 0 ||
3798 blogic_probeinfo_count == 0 ||
3799 blogic_drvr_options_count == blogic_probeinfo_count)) {
3800 blogic_err("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 return 0;
3802 }
3803 /*
3804 Tagged Queuing is disabled when the Queue Depth is 1 since queuing
3805 multiple commands is not possible.
3806 */
Khalid Aziz839cb992013-05-16 19:44:13 -06003807 for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++)
3808 if (drvr_opts->qdepth[tgt_id] == 1) {
3809 unsigned short tgt_bit = 1 << tgt_id;
3810 drvr_opts->tagq_ok &= ~tgt_bit;
3811 drvr_opts->tagq_ok_mask |= tgt_bit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 }
Khalid Aziz839cb992013-05-16 19:44:13 -06003813 if (*options == ';')
3814 options++;
3815 if (*options == '\0')
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 return 0;
3817 }
3818 return 1;
3819}
3820
3821/*
3822 Get it all started
3823*/
3824
Khalid Aziz839cb992013-05-16 19:44:13 -06003825static struct scsi_host_template blogic_template = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 .module = THIS_MODULE,
3827 .proc_name = "BusLogic",
Khalid Aziz839cb992013-05-16 19:44:13 -06003828 .write_info = blogic_write_info,
3829 .show_info = blogic_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 .name = "BusLogic",
Khalid Aziz839cb992013-05-16 19:44:13 -06003831 .info = blogic_drvr_info,
3832 .queuecommand = blogic_qcmd,
3833 .slave_configure = blogic_slaveconfig,
3834 .bios_param = blogic_diskparam,
3835 .eh_host_reset_handler = blogic_hostreset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836#if 0
Khalid Aziz839cb992013-05-16 19:44:13 -06003837 .eh_abort_handler = blogic_abort,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838#endif
3839 .unchecked_isa_dma = 1,
3840 .max_sectors = 128,
3841 .use_clustering = ENABLE_CLUSTERING,
3842};
3843
3844/*
Khalid Aziz839cb992013-05-16 19:44:13 -06003845 blogic_setup handles processing of Kernel Command Line Arguments.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846*/
3847
Khalid Aziz839cb992013-05-16 19:44:13 -06003848static int __init blogic_setup(char *str)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849{
3850 int ints[3];
3851
3852 (void) get_options(str, ARRAY_SIZE(ints), ints);
3853
3854 if (ints[0] != 0) {
Khalid Aziz839cb992013-05-16 19:44:13 -06003855 blogic_err("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 return 0;
3857 }
3858 if (str == NULL || *str == '\0')
3859 return 0;
Khalid Aziz839cb992013-05-16 19:44:13 -06003860 return blogic_parseopts(str);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861}
3862
3863/*
3864 * Exit function. Deletes all hosts associated with this driver.
3865 */
3866
Khalid Aziz839cb992013-05-16 19:44:13 -06003867static void __exit blogic_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868{
Khalid Aziz839cb992013-05-16 19:44:13 -06003869 struct blogic_adapter *ha, *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Khalid Aziz839cb992013-05-16 19:44:13 -06003871 list_for_each_entry_safe(ha, next, &blogic_host_list, host_list)
3872 blogic_deladapter(ha);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873}
3874
Khalid Aziz839cb992013-05-16 19:44:13 -06003875__setup("BusLogic=", blogic_setup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003877#ifdef MODULE
Khalid Aziz839cb992013-05-16 19:44:13 -06003878/*static struct pci_device_id blogic_pci_tbl[] = {
Ben Collins745b5712006-10-18 08:36:57 -04003879 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
3880 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3881 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
3882 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3883 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
3884 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3885 { }
Khalid Aziz839cb992013-05-16 19:44:13 -06003886};*/
3887static DEFINE_PCI_DEVICE_TABLE(blogic_pci_tbl) = {
3888 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER)},
3889 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC)},
3890 {PCI_DEVICE(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT)},
3891 {0, },
Ben Collins745b5712006-10-18 08:36:57 -04003892};
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003893#endif
Khalid Aziz839cb992013-05-16 19:44:13 -06003894MODULE_DEVICE_TABLE(pci, blogic_pci_tbl);
Ben Collins745b5712006-10-18 08:36:57 -04003895
Khalid Aziz839cb992013-05-16 19:44:13 -06003896module_init(blogic_init);
3897module_exit(blogic_exit);