blob: 4d3ebb1af49022e9777a6472f368d96e1a6dec45 [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
29#define BusLogic_DriverVersion "2.1.16"
30#define BusLogic_DriverDate "18 July 2002"
31
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <scsi/scsicam.h>
46
47#include <asm/dma.h>
48#include <asm/io.h>
49#include <asm/system.h>
50
51#include <scsi/scsi.h>
52#include <scsi/scsi_cmnd.h>
53#include <scsi/scsi_device.h>
54#include <scsi/scsi_host.h>
55#include <scsi/scsi_tcq.h>
56#include "BusLogic.h"
57#include "FlashPoint.c"
58
59#ifndef FAILURE
60#define FAILURE (-1)
61#endif
62
63static struct scsi_host_template Bus_Logic_template;
64
65/*
66 BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
67 Options specifications provided via the Linux Kernel Command Line or via
68 the Loadable Kernel Module Installation Facility.
69*/
70
71static int BusLogic_DriverOptionsCount;
72
73
74/*
75 BusLogic_DriverOptions is an array of Driver Options structures representing
76 BusLogic Driver Options specifications provided via the Linux Kernel Command
77 Line or via the Loadable Kernel Module Installation Facility.
78*/
79
80static struct BusLogic_DriverOptions BusLogic_DriverOptions[BusLogic_MaxHostAdapters];
81
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/*
95 BusLogic_ProbeOptions is a set of Probe Options to be applied across
96 all BusLogic Host Adapters.
97*/
98
99static struct BusLogic_ProbeOptions BusLogic_ProbeOptions;
100
101
102/*
103 BusLogic_GlobalOptions is a set of Global Options to be applied across
104 all BusLogic Host Adapters.
105*/
106
107static struct BusLogic_GlobalOptions BusLogic_GlobalOptions;
108
109static LIST_HEAD(BusLogic_host_list);
110
111/*
112 BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
113*/
114
115static int BusLogic_ProbeInfoCount;
116
117
118/*
119 BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information
120 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
125static struct BusLogic_ProbeInfo *BusLogic_ProbeInfoList;
126
127
128/*
129 BusLogic_CommandFailureReason holds a string identifying the reason why a
130 call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command
131 returns a failure code.
132*/
133
134static char *BusLogic_CommandFailureReason;
135
136/*
137 BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
138 Name, Copyright Notice, and Electronic Mail Address.
139*/
140
141static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter)
142{
143 BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter);
144 BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", HostAdapter);
145}
146
147
148/*
149 BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI
150 Driver and Host Adapter.
151*/
152
153static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
154{
155 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
156 return HostAdapter->FullModelName;
157}
158
159/*
160 BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
161 for Host Adapter from the BlockSize bytes located at BlockPointer. The newly
162 created CCBs are added to Host Adapter's free list.
163*/
164
165static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle)
166{
167 struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
168 unsigned int offset = 0;
169 memset(BlockPointer, 0, BlockSize);
170 CCB->AllocationGroupHead = BlockPointerHandle;
171 CCB->AllocationGroupSize = BlockSize;
172 while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) {
173 CCB->Status = BusLogic_CCB_Free;
174 CCB->HostAdapter = HostAdapter;
175 CCB->DMA_Handle = (u32) BlockPointerHandle + offset;
176 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
177 CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
178 CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
179 }
180 CCB->Next = HostAdapter->Free_CCBs;
181 CCB->NextAll = HostAdapter->All_CCBs;
182 HostAdapter->Free_CCBs = CCB;
183 HostAdapter->All_CCBs = CCB;
184 HostAdapter->AllocatedCCBs++;
185 CCB++;
186 offset += sizeof(struct BusLogic_CCB);
187 }
188}
189
190
191/*
192 BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
193*/
194
Richard Knutsson2065e312007-02-05 16:39:01 -0800195static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196{
197 int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
198 void *BlockPointer;
199 dma_addr_t BlockPointerHandle;
200 while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) {
201 BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
202 if (BlockPointer == NULL) {
203 BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter);
204 return false;
205 }
206 BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
207 }
208 return true;
209}
210
211
212/*
213 BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
214*/
215
216static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
217{
218 struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
219 HostAdapter->All_CCBs = NULL;
220 HostAdapter->Free_CCBs = NULL;
221 while ((CCB = NextCCB) != NULL) {
222 NextCCB = CCB->NextAll;
223 if (CCB->AllocationGroupHead) {
224 if (Last_CCB)
225 pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
226 Last_CCB = CCB;
227 }
228 }
229 if (Last_CCB)
230 pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
231}
232
233
234/*
235 BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If
236 allocation fails and there are no remaining CCBs available, the Driver Queue
237 Depth is decreased to a known safe value to avoid potential deadlocks when
238 multiple host adapters share the same IRQ Channel.
239*/
240
Richard Knutsson2065e312007-02-05 16:39:01 -0800241static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242{
243 int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
244 int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
245 void *BlockPointer;
246 dma_addr_t BlockPointerHandle;
247 if (AdditionalCCBs <= 0)
248 return;
249 while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) {
250 BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
251 if (BlockPointer == NULL)
252 break;
253 BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
254 }
255 if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) {
256 if (SuccessMessageP)
257 BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs);
258 return;
259 }
260 BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
261 if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) {
262 HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
263 HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
264 }
265}
266
267/*
268 BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,
269 allocating more memory from the Kernel if necessary. The Host Adapter's
270 Lock should already have been acquired by the caller.
271*/
272
273static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
274 *HostAdapter)
275{
276 static unsigned long SerialNumber = 0;
277 struct BusLogic_CCB *CCB;
278 CCB = HostAdapter->Free_CCBs;
279 if (CCB != NULL) {
280 CCB->SerialNumber = ++SerialNumber;
281 HostAdapter->Free_CCBs = CCB->Next;
282 CCB->Next = NULL;
283 if (HostAdapter->Free_CCBs == NULL)
284 BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
285 return CCB;
286 }
287 BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
288 CCB = HostAdapter->Free_CCBs;
289 if (CCB == NULL)
290 return NULL;
291 CCB->SerialNumber = ++SerialNumber;
292 HostAdapter->Free_CCBs = CCB->Next;
293 CCB->Next = NULL;
294 return CCB;
295}
296
297
298/*
299 BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
300 free list. The Host Adapter's Lock should already have been acquired by the
301 caller.
302*/
303
304static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
305{
306 struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +0900308 scsi_dma_unmap(CCB->Command);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +0900310 CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 CCB->Command = NULL;
313 CCB->Status = BusLogic_CCB_Free;
314 CCB->Next = HostAdapter->Free_CCBs;
315 HostAdapter->Free_CCBs = CCB;
316}
317
318
319/*
320 BusLogic_Command sends the command OperationCode to HostAdapter, optionally
321 providing ParameterLength bytes of ParameterData and receiving at most
322 ReplyLength bytes of ReplyData; any excess reply data is received but
323 discarded.
324
325 On success, this function returns the number of reply bytes read from
326 the Host Adapter (including any discarded data); on failure, it returns
327 -1 if the command was invalid, or -2 if a timeout occurred.
328
329 BusLogic_Command is called exclusively during host adapter detection and
330 initialization, so performance and latency are not critical, and exclusive
331 access to the Host Adapter hardware is assumed. Once the host adapter and
332 driver are initialized, the only Host Adapter command that is issued is the
333 single byte Execute Mailbox Command operation code, which does not require
334 waiting for the Host Adapter Ready bit to be set in the Status Register.
335*/
336
337static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength)
338{
339 unsigned char *ParameterPointer = (unsigned char *) ParameterData;
340 unsigned char *ReplyPointer = (unsigned char *) ReplyData;
341 union BusLogic_StatusRegister StatusRegister;
342 union BusLogic_InterruptRegister InterruptRegister;
343 unsigned long ProcessorFlags = 0;
344 int ReplyBytes = 0, Result;
345 long TimeoutCounter;
346 /*
347 Clear out the Reply Data if provided.
348 */
349 if (ReplyLength > 0)
350 memset(ReplyData, 0, ReplyLength);
351 /*
352 If the IRQ Channel has not yet been acquired, then interrupts must be
353 disabled while issuing host adapter commands since a Command Complete
354 interrupt could occur if the IRQ Channel was previously enabled by another
355 BusLogic Host Adapter or another driver sharing the same IRQ Channel.
356 */
Jiri Kosina44746432007-02-01 16:43:07 -0800357 if (!HostAdapter->IRQ_ChannelAcquired)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 local_irq_save(ProcessorFlags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /*
360 Wait for the Host Adapter Ready bit to be set and the Command/Parameter
361 Register Busy bit to be reset in the Status Register.
362 */
363 TimeoutCounter = 10000;
364 while (--TimeoutCounter >= 0) {
365 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
366 if (StatusRegister.sr.HostAdapterReady && !StatusRegister.sr.CommandParameterRegisterBusy)
367 break;
368 udelay(100);
369 }
370 if (TimeoutCounter < 0) {
371 BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
372 Result = -2;
373 goto Done;
374 }
375 /*
376 Write the OperationCode to the Command/Parameter Register.
377 */
378 HostAdapter->HostAdapterCommandCompleted = false;
379 BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
380 /*
381 Write any additional Parameter Bytes.
382 */
383 TimeoutCounter = 10000;
384 while (ParameterLength > 0 && --TimeoutCounter >= 0) {
385 /*
386 Wait 100 microseconds to give the Host Adapter enough time to determine
387 whether the last value written to the Command/Parameter Register was
388 valid or not. If the Command Complete bit is set in the Interrupt
389 Register, then the Command Invalid bit in the Status Register will be
390 reset if the Operation Code or Parameter was valid and the command
391 has completed, or set if the Operation Code or Parameter was invalid.
392 If the Data In Register Ready bit is set in the Status Register, then
393 the Operation Code was valid, and data is waiting to be read back
394 from the Host Adapter. Otherwise, wait for the Command/Parameter
395 Register Busy bit in the Status Register to be reset.
396 */
397 udelay(100);
398 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
399 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
400 if (InterruptRegister.ir.CommandComplete)
401 break;
402 if (HostAdapter->HostAdapterCommandCompleted)
403 break;
404 if (StatusRegister.sr.DataInRegisterReady)
405 break;
406 if (StatusRegister.sr.CommandParameterRegisterBusy)
407 continue;
408 BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
409 ParameterLength--;
410 }
411 if (TimeoutCounter < 0) {
412 BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance";
413 Result = -2;
414 goto Done;
415 }
416 /*
417 The Modify I/O Address command does not cause a Command Complete Interrupt.
418 */
419 if (OperationCode == BusLogic_ModifyIOAddress) {
420 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
421 if (StatusRegister.sr.CommandInvalid) {
422 BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
423 Result = -1;
424 goto Done;
425 }
426 if (BusLogic_GlobalOptions.TraceConfiguration)
427 BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All);
428 Result = 0;
429 goto Done;
430 }
431 /*
432 Select an appropriate timeout value for awaiting command completion.
433 */
434 switch (OperationCode) {
435 case BusLogic_InquireInstalledDevicesID0to7:
436 case BusLogic_InquireInstalledDevicesID8to15:
437 case BusLogic_InquireTargetDevices:
438 /* Approximately 60 seconds. */
439 TimeoutCounter = 60 * 10000;
440 break;
441 default:
442 /* Approximately 1 second. */
443 TimeoutCounter = 10000;
444 break;
445 }
446 /*
447 Receive any Reply Bytes, waiting for either the Command Complete bit to
448 be set in the Interrupt Register, or for the Interrupt Handler to set the
449 Host Adapter Command Completed bit in the Host Adapter structure.
450 */
451 while (--TimeoutCounter >= 0) {
452 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
453 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
454 if (InterruptRegister.ir.CommandComplete)
455 break;
456 if (HostAdapter->HostAdapterCommandCompleted)
457 break;
458 if (StatusRegister.sr.DataInRegisterReady) {
459 if (++ReplyBytes <= ReplyLength)
460 *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
461 else
462 BusLogic_ReadDataInRegister(HostAdapter);
463 }
464 if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.HostAdapterReady)
465 break;
466 udelay(100);
467 }
468 if (TimeoutCounter < 0) {
469 BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
470 Result = -2;
471 goto Done;
472 }
473 /*
474 Clear any pending Command Complete Interrupt.
475 */
476 BusLogic_InterruptReset(HostAdapter);
477 /*
478 Provide tracing information if requested.
479 */
480 if (BusLogic_GlobalOptions.TraceConfiguration) {
481 int i;
482 BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes);
483 if (ReplyLength > ReplyBytes)
484 ReplyLength = ReplyBytes;
485 for (i = 0; i < ReplyLength; i++)
486 BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]);
487 BusLogic_Notice("\n", HostAdapter);
488 }
489 /*
490 Process Command Invalid conditions.
491 */
492 if (StatusRegister.sr.CommandInvalid) {
493 /*
494 Some early BusLogic Host Adapters may not recover properly from
495 a Command Invalid condition, so if this appears to be the case,
496 a Soft Reset is issued to the Host Adapter. Potentially invalid
497 commands are never attempted after Mailbox Initialization is
498 performed, so there should be no Host Adapter state lost by a
499 Soft Reset in response to a Command Invalid condition.
500 */
501 udelay(1000);
502 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
503 if (StatusRegister.sr.CommandInvalid ||
504 StatusRegister.sr.Reserved ||
505 StatusRegister.sr.DataInRegisterReady ||
506 StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.DiagnosticFailure) {
507 BusLogic_SoftReset(HostAdapter);
508 udelay(1000);
509 }
510 BusLogic_CommandFailureReason = "Command Invalid";
511 Result = -1;
512 goto Done;
513 }
514 /*
515 Handle Excess Parameters Supplied conditions.
516 */
517 if (ParameterLength > 0) {
518 BusLogic_CommandFailureReason = "Excess Parameters Supplied";
519 Result = -1;
520 goto Done;
521 }
522 /*
523 Indicate the command completed successfully.
524 */
525 BusLogic_CommandFailureReason = NULL;
526 Result = ReplyBytes;
527 /*
528 Restore the interrupt status if necessary and return.
529 */
530 Done:
531 if (!HostAdapter->IRQ_ChannelAcquired)
532 local_irq_restore(ProcessorFlags);
533 return Result;
534}
535
536
537/*
538 BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list
539 of I/O Address and Bus Probe Information to be checked for potential BusLogic
540 Host Adapters.
541*/
542
543static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address)
544{
545 struct BusLogic_ProbeInfo *ProbeInfo;
546 if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
547 return;
548 ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
549 ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
550 ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
551 ProbeInfo->IO_Address = IO_Address;
552 ProbeInfo->PCI_Device = NULL;
553}
554
555
556/*
557 BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and
558 Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
559 only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
560*/
561
562static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter
563 *PrototypeHostAdapter)
564{
565 /*
566 If BusLogic Driver Options specifications requested that ISA Bus Probes
567 be inhibited, do not proceed further.
568 */
569 if (BusLogic_ProbeOptions.NoProbeISA)
570 return;
571 /*
572 Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
573 */
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500574 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 BusLogic_AppendProbeAddressISA(0x330);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500576 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 BusLogic_AppendProbeAddressISA(0x334);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500578 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 BusLogic_AppendProbeAddressISA(0x230);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500580 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 BusLogic_AppendProbeAddressISA(0x234);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500582 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 BusLogic_AppendProbeAddressISA(0x130);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500584 if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 BusLogic_AppendProbeAddressISA(0x134);
586}
587
588
589#ifdef CONFIG_PCI
590
591
592/*
593 BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order
594 of increasing PCI Bus and Device Number.
595*/
596
597static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount)
598{
599 int LastInterchange = ProbeInfoCount - 1, Bound, j;
600 while (LastInterchange > 0) {
601 Bound = LastInterchange;
602 LastInterchange = 0;
603 for (j = 0; j < Bound; j++) {
604 struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
605 struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1];
606 if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) {
607 struct BusLogic_ProbeInfo TempProbeInfo;
608 memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
609 memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
610 memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
611 LastInterchange = j;
612 }
613 }
614 }
615}
616
617
618/*
619 BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address
620 and Bus Probe Information to be checked for potential BusLogic MultiMaster
621 SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
622 machines as well as from the list of standard BusLogic MultiMaster ISA
623 I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
624*/
625
626static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter
627 *PrototypeHostAdapter)
628{
629 struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
630 int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
631 int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
Richard Knutsson2065e312007-02-05 16:39:01 -0800632 bool ForceBusDeviceScanningOrder = false;
633 bool ForceBusDeviceScanningOrderChecked = false;
634 bool StandardAddressSeen[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 struct pci_dev *PCI_Device = NULL;
636 int i;
637 if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
638 return 0;
639 BusLogic_ProbeInfoCount++;
640 for (i = 0; i < 6; i++)
641 StandardAddressSeen[i] = false;
642 /*
643 Iterate over the MultiMaster PCI Host Adapters. For each enumerated host
644 adapter, determine whether its ISA Compatible I/O Port is enabled and if
645 so, whether it is assigned the Primary I/O Address. A host adapter that is
646 assigned the Primary I/O Address will always be the preferred boot device.
647 The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
648 Address, then any other PCI host adapters, and finally any host adapters
649 located at the remaining standard ISA I/O Addresses. When a PCI host
650 adapter is found with its ISA Compatible I/O Port enabled, a command is
651 issued to disable the ISA Compatible I/O Port, and it is noted that the
652 particular standard ISA I/O Address need not be probed.
653 */
654 PrimaryProbeInfo->IO_Address = 0;
Alan Coxa07f3532006-09-15 15:34:32 +0100655 while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_Device)) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
657 struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
658 enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
659 unsigned char Bus;
660 unsigned char Device;
661 unsigned int IRQ_Channel;
662 unsigned long BaseAddress0;
663 unsigned long BaseAddress1;
664 unsigned long IO_Address;
665 unsigned long PCI_Address;
666
667 if (pci_enable_device(PCI_Device))
668 continue;
669
Matthias Gehre910638a2006-03-28 01:56:48 -0800670 if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK ))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 continue;
672
673 Bus = PCI_Device->bus->number;
674 Device = PCI_Device->devfn >> 3;
675 IRQ_Channel = PCI_Device->irq;
676 IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
677 PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
678
679 if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
680 BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0);
681 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
682 continue;
683 }
684 if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
685 BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1);
686 BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
687 continue;
688 }
689 if (IRQ_Channel == 0) {
690 BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
691 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
692 continue;
693 }
694 if (BusLogic_GlobalOptions.TraceProbe) {
695 BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
696 BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
697 }
698 /*
699 Issue the Inquire PCI Host Adapter Information command to determine
700 the ISA Compatible I/O Port. If the ISA Compatible I/O Port is
701 known and enabled, note that the particular Standard ISA I/O
702 Address should not be probed.
703 */
704 HostAdapter->IO_Address = IO_Address;
705 BusLogic_InterruptReset(HostAdapter);
706 if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
707 == sizeof(PCIHostAdapterInformation)) {
708 if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
709 StandardAddressSeen[PCIHostAdapterInformation.ISACompatibleIOPort] = true;
710 } else
711 PCIHostAdapterInformation.ISACompatibleIOPort = BusLogic_IO_Disable;
712 /*
713 * Issue the Modify I/O Address command to disable the ISA Compatible
714 * I/O Port. On PCI Host Adapters, the Modify I/O Address command
715 * allows modification of the ISA compatible I/O Address that the Host
716 * Adapter responds to; it does not affect the PCI compliant I/O Address
717 * assigned at system initialization.
718 */
719 ModifyIOAddressRequest = BusLogic_IO_Disable;
720 BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, &ModifyIOAddressRequest, sizeof(ModifyIOAddressRequest), NULL, 0);
721 /*
722 For the first MultiMaster Host Adapter enumerated, issue the Fetch
723 Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
724 for the setting of the "Use Bus And Device # For PCI Scanning Seq."
725 option. Issue the Inquire Board ID command since this option is
726 only valid for the BT-948/958/958D.
727 */
728 if (!ForceBusDeviceScanningOrderChecked) {
729 struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
730 struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
731 struct BusLogic_BoardID BoardID;
732 FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset + 45;
733 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45);
734 BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIByte45, sizeof(AutoSCSIByte45));
735 BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID));
736 if (BoardID.FirmwareVersion1stDigit == '5')
737 ForceBusDeviceScanningOrder = AutoSCSIByte45.ForceBusDeviceScanningOrder;
738 ForceBusDeviceScanningOrderChecked = true;
739 }
740 /*
741 Determine whether this MultiMaster Host Adapter has its ISA
742 Compatible I/O Port enabled and is assigned the Primary I/O Address.
743 If it does, then it is the Primary MultiMaster Host Adapter and must
744 be recognized first. If it does not, then it is added to the list
745 for probing after any Primary MultiMaster Host Adapter is probed.
746 */
747 if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) {
748 PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
749 PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
750 PrimaryProbeInfo->IO_Address = IO_Address;
751 PrimaryProbeInfo->PCI_Address = PCI_Address;
752 PrimaryProbeInfo->Bus = Bus;
753 PrimaryProbeInfo->Device = Device;
754 PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
Alan Coxa07f3532006-09-15 15:34:32 +0100755 PrimaryProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 PCIMultiMasterCount++;
757 } else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
758 struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
759 ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
760 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
761 ProbeInfo->IO_Address = IO_Address;
762 ProbeInfo->PCI_Address = PCI_Address;
763 ProbeInfo->Bus = Bus;
764 ProbeInfo->Device = Device;
765 ProbeInfo->IRQ_Channel = IRQ_Channel;
Alan Coxa07f3532006-09-15 15:34:32 +0100766 ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 NonPrimaryPCIMultiMasterCount++;
768 PCIMultiMasterCount++;
769 } else
770 BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
771 }
772 /*
773 If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
774 for the first enumerated MultiMaster Host Adapter, and if that host adapter
775 is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
776 Host Adapters in the order of increasing PCI Bus and Device Number. In
777 that case, sort the probe information into the same order the BIOS uses.
778 If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
779 Host Adapters in the order they are enumerated by the PCI BIOS, and hence
780 no sorting is necessary.
781 */
782 if (ForceBusDeviceScanningOrder)
783 BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[NonPrimaryPCIMultiMasterIndex], NonPrimaryPCIMultiMasterCount);
784 /*
785 If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
786 then the Primary I/O Address must be probed explicitly before any PCI
787 host adapters are probed.
788 */
789 if (!BusLogic_ProbeOptions.NoProbeISA)
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500790 if (PrimaryProbeInfo->IO_Address == 0 &&
791 (!BusLogic_ProbeOptions.LimitedProbeISA ||
792 BusLogic_ProbeOptions.Probe330)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
794 PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
795 PrimaryProbeInfo->IO_Address = 0x330;
796 }
797 /*
798 Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
799 omitting the Primary I/O Address which has already been handled.
800 */
801 if (!BusLogic_ProbeOptions.NoProbeISA) {
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500802 if (!StandardAddressSeen[1] &&
803 (!BusLogic_ProbeOptions.LimitedProbeISA ||
804 BusLogic_ProbeOptions.Probe334))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 BusLogic_AppendProbeAddressISA(0x334);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500806 if (!StandardAddressSeen[2] &&
807 (!BusLogic_ProbeOptions.LimitedProbeISA ||
808 BusLogic_ProbeOptions.Probe230))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 BusLogic_AppendProbeAddressISA(0x230);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500810 if (!StandardAddressSeen[3] &&
811 (!BusLogic_ProbeOptions.LimitedProbeISA ||
812 BusLogic_ProbeOptions.Probe234))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 BusLogic_AppendProbeAddressISA(0x234);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500814 if (!StandardAddressSeen[4] &&
815 (!BusLogic_ProbeOptions.LimitedProbeISA ||
816 BusLogic_ProbeOptions.Probe130))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 BusLogic_AppendProbeAddressISA(0x130);
Zachary Amsden1079a2d2007-04-10 08:53:08 -0500818 if (!StandardAddressSeen[5] &&
819 (!BusLogic_ProbeOptions.LimitedProbeISA ||
820 BusLogic_ProbeOptions.Probe134))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 BusLogic_AppendProbeAddressISA(0x134);
822 }
823 /*
824 Iterate over the older non-compliant MultiMaster PCI Host Adapters,
825 noting the PCI bus location and assigned IRQ Channel.
826 */
827 PCI_Device = NULL;
Alan Coxa07f3532006-09-15 15:34:32 +0100828 while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, PCI_Device)) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 unsigned char Bus;
830 unsigned char Device;
831 unsigned int IRQ_Channel;
832 unsigned long IO_Address;
833
834 if (pci_enable_device(PCI_Device))
835 continue;
836
Matthias Gehre910638a2006-03-28 01:56:48 -0800837 if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 continue;
839
840 Bus = PCI_Device->bus->number;
841 Device = PCI_Device->devfn >> 3;
842 IRQ_Channel = PCI_Device->irq;
843 IO_Address = pci_resource_start(PCI_Device, 0);
844
845 if (IO_Address == 0 || IRQ_Channel == 0)
846 continue;
847 for (i = 0; i < BusLogic_ProbeInfoCount; i++) {
848 struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
849 if (ProbeInfo->IO_Address == IO_Address && ProbeInfo->HostAdapterType == BusLogic_MultiMaster) {
850 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
851 ProbeInfo->PCI_Address = 0;
852 ProbeInfo->Bus = Bus;
853 ProbeInfo->Device = Device;
854 ProbeInfo->IRQ_Channel = IRQ_Channel;
Alan Coxa07f3532006-09-15 15:34:32 +0100855 ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 break;
857 }
858 }
859 }
860 return PCIMultiMasterCount;
861}
862
863
864/*
865 BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address
866 and Bus Probe Information to be checked for potential BusLogic FlashPoint
867 Host Adapters by interrogating the PCI Configuration Space. It returns the
868 number of FlashPoint Host Adapters found.
869*/
870
871static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAdapter
872 *PrototypeHostAdapter)
873{
874 int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
875 struct pci_dev *PCI_Device = NULL;
876 /*
877 Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
878 */
Alan Coxa07f3532006-09-15 15:34:32 +0100879 while ((PCI_Device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, PCI_Device)) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 unsigned char Bus;
881 unsigned char Device;
882 unsigned int IRQ_Channel;
883 unsigned long BaseAddress0;
884 unsigned long BaseAddress1;
885 unsigned long IO_Address;
886 unsigned long PCI_Address;
887
888 if (pci_enable_device(PCI_Device))
889 continue;
890
Matthias Gehre910638a2006-03-28 01:56:48 -0800891 if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 continue;
893
894 Bus = PCI_Device->bus->number;
895 Device = PCI_Device->devfn >> 3;
896 IRQ_Channel = PCI_Device->irq;
897 IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
898 PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
899#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
900 if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
901 BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
902 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
903 continue;
904 }
905 if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
906 BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1);
907 BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
908 continue;
909 }
910 if (IRQ_Channel == 0) {
911 BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
912 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
913 continue;
914 }
915 if (BusLogic_GlobalOptions.TraceProbe) {
916 BusLogic_Notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
917 BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
918 }
919 if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
920 struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
921 ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
922 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
923 ProbeInfo->IO_Address = IO_Address;
924 ProbeInfo->PCI_Address = PCI_Address;
925 ProbeInfo->Bus = Bus;
926 ProbeInfo->Device = Device;
927 ProbeInfo->IRQ_Channel = IRQ_Channel;
Alan Coxa07f3532006-09-15 15:34:32 +0100928 ProbeInfo->PCI_Device = pci_dev_get(PCI_Device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 FlashPointCount++;
930 } else
931 BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
932#else
933 BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device);
934 BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
935 BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
936#endif
937 }
938 /*
939 The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
940 increasing PCI Bus and Device Number, so sort the probe information into
941 the same order the BIOS uses.
942 */
943 BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], FlashPointCount);
944 return FlashPointCount;
945}
946
947
948/*
949 BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus
950 Probe Information to be checked for potential BusLogic SCSI Host Adapters by
951 interrogating the PCI Configuration Space on PCI machines as well as from the
952 list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
953 FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
954 probe for FlashPoint Host Adapters first unless the BIOS primary disk is
955 controlled by the first PCI MultiMaster Host Adapter, in which case
956 MultiMaster Host Adapters will be probed first. The BusLogic Driver Options
957 specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
958 a particular probe order.
959*/
960
961static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
962 *PrototypeHostAdapter)
963{
964 /*
965 If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
966 Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
967 */
968 if (!BusLogic_ProbeOptions.NoProbePCI) {
969 if (BusLogic_ProbeOptions.MultiMasterFirst) {
970 BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
971 BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
972 } else if (BusLogic_ProbeOptions.FlashPointFirst) {
973 BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
974 BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
975 } else {
976 int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
977 int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
978 if (FlashPointCount > 0 && PCIMultiMasterCount > 0) {
979 struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[FlashPointCount];
980 struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
981 struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
982 struct BusLogic_BIOSDriveMapByte Drive0MapByte;
983 while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
984 ProbeInfo++;
985 HostAdapter->IO_Address = ProbeInfo->IO_Address;
986 FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
987 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(Drive0MapByte);
988 BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &Drive0MapByte, sizeof(Drive0MapByte));
989 /*
990 If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
991 is controlled by this PCI MultiMaster Host Adapter, then
992 reverse the probe order so that MultiMaster Host Adapters are
993 probed before FlashPoint Host Adapters.
994 */
995 if (Drive0MapByte.DiskGeometry != BusLogic_BIOS_Disk_Not_Installed) {
996 struct BusLogic_ProbeInfo SavedProbeInfo[BusLogic_MaxHostAdapters];
997 int MultiMasterCount = BusLogic_ProbeInfoCount - FlashPointCount;
998 memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, BusLogic_ProbeInfoCount * sizeof(struct BusLogic_ProbeInfo));
999 memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
1000 memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], &SavedProbeInfo[0], FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
1001 }
1002 }
1003 }
1004 } else
1005 BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
1006}
1007
1008
1009#endif /* CONFIG_PCI */
1010
1011
1012/*
1013 BusLogic_Failure prints a standardized error message, and then returns false.
1014*/
1015
Richard Knutsson2065e312007-02-05 16:39:01 -08001016static bool BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017{
1018 BusLogic_AnnounceDriver(HostAdapter);
1019 if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
1020 BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", HostAdapter);
1021 BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device, HostAdapter->IO_Address, HostAdapter->PCI_Address);
1022 } else
1023 BusLogic_Error("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", HostAdapter, HostAdapter->IO_Address);
1024 BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
1025 if (BusLogic_CommandFailureReason != NULL)
1026 BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, BusLogic_CommandFailureReason);
1027 return false;
1028}
1029
1030
1031/*
1032 BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
1033*/
1034
Richard Knutsson2065e312007-02-05 16:39:01 -08001035static bool __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036{
1037 union BusLogic_StatusRegister StatusRegister;
1038 union BusLogic_InterruptRegister InterruptRegister;
1039 union BusLogic_GeometryRegister GeometryRegister;
1040 /*
1041 FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
1042 */
1043 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
1044 struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
1045 FlashPointInfo->BaseAddress = (u32) HostAdapter->IO_Address;
1046 FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
1047 FlashPointInfo->Present = false;
1048 if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && FlashPointInfo->Present)) {
1049 BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
1050 BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", HostAdapter, HostAdapter->IO_Address, HostAdapter->PCI_Address);
1051 BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", HostAdapter);
1052 return false;
1053 }
1054 if (BusLogic_GlobalOptions.TraceProbe)
1055 BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", HostAdapter, HostAdapter->IO_Address);
1056 /*
1057 Indicate the Host Adapter Probe completed successfully.
1058 */
1059 return true;
1060 }
1061 /*
1062 Read the Status, Interrupt, and Geometry Registers to test if there are I/O
1063 ports that respond, and to check the values to determine if they are from a
1064 BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which
1065 case there is definitely no BusLogic Host Adapter at this base I/O Address.
1066 The test here is a subset of that used by the BusLogic Host Adapter BIOS.
1067 */
1068 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1069 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
1070 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1071 if (BusLogic_GlobalOptions.TraceProbe)
1072 BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All);
1073 if (StatusRegister.All == 0 || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.CommandParameterRegisterBusy || StatusRegister.sr.Reserved || StatusRegister.sr.CommandInvalid || InterruptRegister.ir.Reserved != 0)
1074 return false;
1075 /*
1076 Check the undocumented Geometry Register to test if there is an I/O port
1077 that responded. Adaptec Host Adapters do not implement the Geometry
1078 Register, so this test helps serve to avoid incorrectly recognizing an
1079 Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C
1080 series does respond to the Geometry Register I/O port, but it will be
1081 rejected later when the Inquire Extended Setup Information command is
1082 issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a
1083 BusLogic clone that implements the same interface as earlier BusLogic
1084 Host Adapters, including the undocumented commands, and is therefore
1085 supported by this driver. However, the AMI FastDisk always returns 0x00
1086 upon reading the Geometry Register, so the extended translation option
1087 should always be left disabled on the AMI FastDisk.
1088 */
1089 if (GeometryRegister.All == 0xFF)
1090 return false;
1091 /*
1092 Indicate the Host Adapter Probe completed successfully.
1093 */
1094 return true;
1095}
1096
1097
1098/*
1099 BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter
1100 and waits for Host Adapter Diagnostics to complete. If HardReset is true, a
1101 Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
1102 Soft Reset is performed which only resets the Host Adapter without forcing a
1103 SCSI Bus Reset.
1104*/
1105
Richard Knutsson2065e312007-02-05 16:39:01 -08001106static bool BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
1107 *HostAdapter, bool HardReset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108{
1109 union BusLogic_StatusRegister StatusRegister;
1110 int TimeoutCounter;
1111 /*
1112 FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
1113 */
1114 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
1115 struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
1116 FlashPointInfo->HostSoftReset = !HardReset;
1117 FlashPointInfo->ReportDataUnderrun = true;
1118 HostAdapter->CardHandle = FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
1119 if (HostAdapter->CardHandle == FlashPoint_BadCardHandle)
1120 return false;
1121 /*
1122 Indicate the Host Adapter Hard Reset completed successfully.
1123 */
1124 return true;
1125 }
1126 /*
1127 Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host
1128 Adapter should respond by setting Diagnostic Active in the Status Register.
1129 */
1130 if (HardReset)
1131 BusLogic_HardReset(HostAdapter);
1132 else
1133 BusLogic_SoftReset(HostAdapter);
1134 /*
1135 Wait until Diagnostic Active is set in the Status Register.
1136 */
1137 TimeoutCounter = 5 * 10000;
1138 while (--TimeoutCounter >= 0) {
1139 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1140 if (StatusRegister.sr.DiagnosticActive)
1141 break;
1142 udelay(100);
1143 }
1144 if (BusLogic_GlobalOptions.TraceHardwareReset)
1145 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
1146 if (TimeoutCounter < 0)
1147 return false;
1148 /*
1149 Wait 100 microseconds to allow completion of any initial diagnostic
1150 activity which might leave the contents of the Status Register
1151 unpredictable.
1152 */
1153 udelay(100);
1154 /*
1155 Wait until Diagnostic Active is reset in the Status Register.
1156 */
1157 TimeoutCounter = 10 * 10000;
1158 while (--TimeoutCounter >= 0) {
1159 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1160 if (!StatusRegister.sr.DiagnosticActive)
1161 break;
1162 udelay(100);
1163 }
1164 if (BusLogic_GlobalOptions.TraceHardwareReset)
1165 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
1166 if (TimeoutCounter < 0)
1167 return false;
1168 /*
1169 Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
1170 or Data In Register Ready bits is set in the Status Register.
1171 */
1172 TimeoutCounter = 10000;
1173 while (--TimeoutCounter >= 0) {
1174 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1175 if (StatusRegister.sr.DiagnosticFailure || StatusRegister.sr.HostAdapterReady || StatusRegister.sr.DataInRegisterReady)
1176 break;
1177 udelay(100);
1178 }
1179 if (BusLogic_GlobalOptions.TraceHardwareReset)
1180 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
1181 if (TimeoutCounter < 0)
1182 return false;
1183 /*
1184 If Diagnostic Failure is set or Host Adapter Ready is reset, then an
1185 error occurred during the Host Adapter diagnostics. If Data In Register
1186 Ready is set, then there is an Error Code available.
1187 */
1188 if (StatusRegister.sr.DiagnosticFailure || !StatusRegister.sr.HostAdapterReady) {
1189 BusLogic_CommandFailureReason = NULL;
1190 BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
1191 BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All);
1192 if (StatusRegister.sr.DataInRegisterReady) {
1193 unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
1194 BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", HostAdapter, ErrorCode);
1195 }
1196 return false;
1197 }
1198 /*
1199 Indicate the Host Adapter Hard Reset completed successfully.
1200 */
1201 return true;
1202}
1203
1204
1205/*
1206 BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
1207 Host Adapter.
1208*/
1209
Richard Knutsson2065e312007-02-05 16:39:01 -08001210static bool __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211{
1212 struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
1213 unsigned char RequestedReplyLength;
Richard Knutsson2065e312007-02-05 16:39:01 -08001214 bool Result = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 /*
1216 FlashPoint Host Adapters do not require this protection.
1217 */
1218 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1219 return true;
1220 /*
1221 Issue the Inquire Extended Setup Information command. Only genuine
1222 BusLogic Host Adapters and true clones support this command. Adaptec 1542C
1223 series Host Adapters that respond to the Geometry Register I/O port will
1224 fail this command.
1225 */
1226 RequestedReplyLength = sizeof(ExtendedSetupInformation);
1227 if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
1228 != sizeof(ExtendedSetupInformation))
1229 Result = false;
1230 /*
1231 Provide tracing information if requested and return.
1232 */
1233 if (BusLogic_GlobalOptions.TraceProbe)
1234 BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
1235 return Result;
1236}
1237
1238
1239/*
1240 BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
1241 from Host Adapter and initializes the Host Adapter structure.
1242*/
1243
Richard Knutsson2065e312007-02-05 16:39:01 -08001244static bool __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 *HostAdapter)
1246{
1247 struct BusLogic_BoardID BoardID;
1248 struct BusLogic_Configuration Configuration;
1249 struct BusLogic_SetupInformation SetupInformation;
1250 struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
1251 unsigned char HostAdapterModelNumber[5];
1252 unsigned char FirmwareVersion3rdDigit;
1253 unsigned char FirmwareVersionLetter;
1254 struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
1255 struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
1256 struct BusLogic_AutoSCSIData AutoSCSIData;
1257 union BusLogic_GeometryRegister GeometryRegister;
1258 unsigned char RequestedReplyLength;
1259 unsigned char *TargetPointer, Character;
1260 int TargetID, i;
1261 /*
1262 Configuration Information for FlashPoint Host Adapters is provided in the
1263 FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
1264 Initialize fields in the Host Adapter structure from the FlashPoint_Info
1265 structure.
1266 */
1267 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
1268 struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
1269 TargetPointer = HostAdapter->ModelName;
1270 *TargetPointer++ = 'B';
1271 *TargetPointer++ = 'T';
1272 *TargetPointer++ = '-';
1273 for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
1274 *TargetPointer++ = FlashPointInfo->ModelNumber[i];
1275 *TargetPointer++ = '\0';
1276 strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
1277 HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
1278 HostAdapter->ExtendedTranslationEnabled = FlashPointInfo->ExtendedTranslationEnabled;
1279 HostAdapter->ParityCheckingEnabled = FlashPointInfo->ParityCheckingEnabled;
1280 HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
1281 HostAdapter->LevelSensitiveInterrupt = true;
1282 HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
1283 HostAdapter->HostDifferentialSCSI = false;
1284 HostAdapter->HostSupportsSCAM = true;
1285 HostAdapter->HostUltraSCSI = true;
1286 HostAdapter->ExtendedLUNSupport = true;
1287 HostAdapter->TerminationInfoValid = true;
1288 HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
1289 HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
1290 HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
1291 HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
1292 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1293 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1294 HostAdapter->MaxLogicalUnits = 32;
1295 HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1296 HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1297 HostAdapter->DriverQueueDepth = 255;
1298 HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
1299 HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
1300 HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
1301 HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
1302 HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
1303 HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
1304 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1305 goto Common;
1306 }
1307 /*
1308 Issue the Inquire Board ID command.
1309 */
1310 if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)) != sizeof(BoardID))
1311 return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
1312 /*
1313 Issue the Inquire Configuration command.
1314 */
1315 if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, &Configuration, sizeof(Configuration))
1316 != sizeof(Configuration))
1317 return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
1318 /*
1319 Issue the Inquire Setup Information command.
1320 */
1321 RequestedReplyLength = sizeof(SetupInformation);
1322 if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
1323 != sizeof(SetupInformation))
1324 return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
1325 /*
1326 Issue the Inquire Extended Setup Information command.
1327 */
1328 RequestedReplyLength = sizeof(ExtendedSetupInformation);
1329 if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
1330 != sizeof(ExtendedSetupInformation))
1331 return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
1332 /*
1333 Issue the Inquire Firmware Version 3rd Digit command.
1334 */
1335 FirmwareVersion3rdDigit = '\0';
1336 if (BoardID.FirmwareVersion1stDigit > '0')
1337 if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, NULL, 0, &FirmwareVersion3rdDigit, sizeof(FirmwareVersion3rdDigit))
1338 != sizeof(FirmwareVersion3rdDigit))
1339 return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
1340 /*
1341 Issue the Inquire Host Adapter Model Number command.
1342 */
1343 if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2')
1344 /* BusLogic BT-542B ISA 2.xx */
1345 strcpy(HostAdapterModelNumber, "542B");
1346 else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '2' && (BoardID.FirmwareVersion2ndDigit <= '1' || (BoardID.FirmwareVersion2ndDigit == '2' && FirmwareVersion3rdDigit == '0')))
1347 /* BusLogic BT-742A EISA 2.1x or 2.20 */
1348 strcpy(HostAdapterModelNumber, "742A");
1349 else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0')
1350 /* AMI FastDisk EISA Series 441 0.x */
1351 strcpy(HostAdapterModelNumber, "747A");
1352 else {
1353 RequestedReplyLength = sizeof(HostAdapterModelNumber);
1354 if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), &HostAdapterModelNumber, sizeof(HostAdapterModelNumber))
1355 != sizeof(HostAdapterModelNumber))
1356 return BusLogic_Failure(HostAdapter, "INQUIRE HOST ADAPTER MODEL NUMBER");
1357 }
1358 /*
1359 BusLogic MultiMaster Host Adapters can be identified by their model number
1360 and the major version number of their firmware as follows:
1361
1362 5.xx BusLogic "W" Series Host Adapters:
1363 BT-948/958/958D
1364 4.xx BusLogic "C" Series Host Adapters:
1365 BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1366 3.xx BusLogic "S" Series Host Adapters:
1367 BT-747S/747D/757S/757D/445S/545S/542D
1368 BT-542B/742A (revision H)
1369 2.xx BusLogic "A" Series Host Adapters:
1370 BT-542B/742A (revision G and below)
1371 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1372 */
1373 /*
1374 Save the Model Name and Host Adapter Name in the Host Adapter structure.
1375 */
1376 TargetPointer = HostAdapter->ModelName;
1377 *TargetPointer++ = 'B';
1378 *TargetPointer++ = 'T';
1379 *TargetPointer++ = '-';
1380 for (i = 0; i < sizeof(HostAdapterModelNumber); i++) {
1381 Character = HostAdapterModelNumber[i];
1382 if (Character == ' ' || Character == '\0')
1383 break;
1384 *TargetPointer++ = Character;
1385 }
1386 *TargetPointer++ = '\0';
1387 /*
1388 Save the Firmware Version in the Host Adapter structure.
1389 */
1390 TargetPointer = HostAdapter->FirmwareVersion;
1391 *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
1392 *TargetPointer++ = '.';
1393 *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
1394 if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
1395 *TargetPointer++ = FirmwareVersion3rdDigit;
1396 *TargetPointer = '\0';
1397 /*
1398 Issue the Inquire Firmware Version Letter command.
1399 */
1400 if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) {
1401 if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter))
1402 != sizeof(FirmwareVersionLetter))
1403 return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER");
1404 if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
1405 *TargetPointer++ = FirmwareVersionLetter;
1406 *TargetPointer = '\0';
1407 }
1408 /*
1409 Save the Host Adapter SCSI ID in the Host Adapter structure.
1410 */
1411 HostAdapter->SCSI_ID = Configuration.HostAdapterID;
1412 /*
1413 Determine the Bus Type and save it in the Host Adapter structure, determine
1414 and save the IRQ Channel if necessary, and determine and save the DMA
1415 Channel for ISA Host Adapters.
1416 */
1417 HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
1418 if (HostAdapter->IRQ_Channel == 0) {
1419 if (Configuration.IRQ_Channel9)
1420 HostAdapter->IRQ_Channel = 9;
1421 else if (Configuration.IRQ_Channel10)
1422 HostAdapter->IRQ_Channel = 10;
1423 else if (Configuration.IRQ_Channel11)
1424 HostAdapter->IRQ_Channel = 11;
1425 else if (Configuration.IRQ_Channel12)
1426 HostAdapter->IRQ_Channel = 12;
1427 else if (Configuration.IRQ_Channel14)
1428 HostAdapter->IRQ_Channel = 14;
1429 else if (Configuration.IRQ_Channel15)
1430 HostAdapter->IRQ_Channel = 15;
1431 }
1432 if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) {
1433 if (Configuration.DMA_Channel5)
1434 HostAdapter->DMA_Channel = 5;
1435 else if (Configuration.DMA_Channel6)
1436 HostAdapter->DMA_Channel = 6;
1437 else if (Configuration.DMA_Channel7)
1438 HostAdapter->DMA_Channel = 7;
1439 }
1440 /*
1441 Determine whether Extended Translation is enabled and save it in
1442 the Host Adapter structure.
1443 */
1444 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1445 HostAdapter->ExtendedTranslationEnabled = GeometryRegister.gr.ExtendedTranslationEnabled;
1446 /*
1447 Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1448 SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1449 Ultra SCSI flag in the Host Adapter structure.
1450 */
1451 HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit;
1452 HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit;
1453 if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
1454 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1455 if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
1456 HostAdapter->LevelSensitiveInterrupt = true;
1457 HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
1458 HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI;
1459 HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
1460 HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
1461 /*
1462 Determine whether Extended LUN Format CCBs are supported and save the
1463 information in the Host Adapter structure.
1464 */
1465 if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
1466 HostAdapter->ExtendedLUNSupport = true;
1467 /*
1468 Issue the Inquire PCI Host Adapter Information command to read the
1469 Termination Information from "W" series MultiMaster Host Adapters.
1470 */
1471 if (HostAdapter->FirmwareVersion[0] == '5') {
1472 if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
1473 != sizeof(PCIHostAdapterInformation))
1474 return BusLogic_Failure(HostAdapter, "INQUIRE PCI HOST ADAPTER INFORMATION");
1475 /*
1476 Save the Termination Information in the Host Adapter structure.
1477 */
1478 if (PCIHostAdapterInformation.GenericInfoValid) {
1479 HostAdapter->TerminationInfoValid = true;
1480 HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated;
1481 HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
1482 }
1483 }
1484 /*
1485 Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
1486 from "W" and "C" series MultiMaster Host Adapters.
1487 */
1488 if (HostAdapter->FirmwareVersion[0] >= '4') {
1489 FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset;
1490 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
1491 if (BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIData, sizeof(AutoSCSIData))
1492 != sizeof(AutoSCSIData))
1493 return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
1494 /*
1495 Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
1496 Information in the Host Adapter structure.
1497 */
1498 HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
1499 HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
1500 if (HostAdapter->FirmwareVersion[0] == '4') {
1501 HostAdapter->TerminationInfoValid = true;
1502 HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
1503 HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
1504 }
1505 /*
1506 Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
1507 Disconnect Permitted, Ultra Permitted, and SCAM Information in the
1508 Host Adapter structure.
1509 */
1510 HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
1511 HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
1512 HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted;
1513 HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted;
1514 if (HostAdapter->HostUltraSCSI)
1515 HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
1516 if (HostAdapter->HostSupportsSCAM) {
1517 HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
1518 HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
1519 }
1520 }
1521 /*
1522 Initialize fields in the Host Adapter structure for "S" and "A" series
1523 MultiMaster Host Adapters.
1524 */
1525 if (HostAdapter->FirmwareVersion[0] < '4') {
1526 if (SetupInformation.SynchronousInitiationEnabled) {
1527 HostAdapter->SynchronousPermitted = 0xFF;
1528 if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) {
1529 if (ExtendedSetupInformation.Misc.FastOnEISA)
1530 HostAdapter->FastPermitted = 0xFF;
1531 if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
1532 HostAdapter->WidePermitted = 0xFF;
1533 }
1534 }
1535 HostAdapter->DisconnectPermitted = 0xFF;
1536 HostAdapter->ParityCheckingEnabled = SetupInformation.ParityCheckingEnabled;
1537 HostAdapter->BusResetEnabled = true;
1538 }
1539 /*
1540 Determine the maximum number of Target IDs and Logical Units supported by
1541 this driver for Wide and Narrow Host Adapters.
1542 */
1543 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1544 HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
1545 /*
1546 Select appropriate values for the Mailbox Count, Driver Queue Depth,
1547 Initial CCBs, and Incremental CCBs variables based on whether or not Strict
1548 Round Robin Mode is supported. If Strict Round Robin Mode is supported,
1549 then there is no performance degradation in using the maximum possible
1550 number of Outgoing and Incoming Mailboxes and allowing the Tagged and
1551 Untagged Queue Depths to determine the actual utilization. If Strict Round
1552 Robin Mode is not supported, then the Host Adapter must scan all the
1553 Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
1554 cause a substantial performance penalty. The host adapters actually have
1555 room to store the following number of CCBs internally; that is, they can
1556 internally queue and manage this many active commands on the SCSI bus
1557 simultaneously. Performance measurements demonstrate that the Driver Queue
1558 Depth should be set to the Mailbox Count, rather than the Host Adapter
1559 Queue Depth (internal CCB capacity), as it is more efficient to have the
1560 queued commands waiting in Outgoing Mailboxes if necessary than to block
1561 the process in the higher levels of the SCSI Subsystem.
1562
1563 192 BT-948/958/958D
1564 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1565 50 BT-545C/540CF
1566 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1567 */
1568 if (HostAdapter->FirmwareVersion[0] == '5')
1569 HostAdapter->HostAdapterQueueDepth = 192;
1570 else if (HostAdapter->FirmwareVersion[0] == '4')
1571 HostAdapter->HostAdapterQueueDepth = (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
1572 else
1573 HostAdapter->HostAdapterQueueDepth = 30;
1574 if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) {
1575 HostAdapter->StrictRoundRobinModeSupport = true;
1576 HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
1577 } else {
1578 HostAdapter->StrictRoundRobinModeSupport = false;
1579 HostAdapter->MailboxCount = 32;
1580 }
1581 HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
1582 HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1583 HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1584 /*
1585 Tagged Queuing support is available and operates properly on all "W" series
1586 MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
1587 firmware version 4.22 and above, and on "S" series MultiMaster Host
1588 Adapters with firmware version 3.35 and above.
1589 */
1590 HostAdapter->TaggedQueuingPermitted = 0;
1591 switch (HostAdapter->FirmwareVersion[0]) {
1592 case '5':
1593 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1594 break;
1595 case '4':
1596 if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
1597 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1598 break;
1599 case '3':
1600 if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
1601 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1602 break;
1603 }
1604 /*
1605 Determine the Host Adapter BIOS Address if the BIOS is enabled and
1606 save it in the Host Adapter structure. The BIOS is disabled if the
1607 BIOS_Address is 0.
1608 */
1609 HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
1610 /*
1611 ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
1612 */
1613 if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1614 HostAdapter->BounceBuffersRequired = true;
1615 /*
1616 BusLogic BT-445S Host Adapters prior to board revision E have a hardware
1617 bug whereby when the BIOS is enabled, transfers to/from the same address
1618 range the BIOS occupies modulo 16MB are handled incorrectly. Only properly
1619 functioning BT-445S Host Adapters have firmware version 3.37, so require
1620 that ISA Bounce Buffers be used for the buggy BT-445S models if there is
1621 more than 16MB memory.
1622 */
1623 if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1624 HostAdapter->BounceBuffersRequired = true;
1625 /*
1626 Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
1627 */
1628 Common:
1629 /*
1630 Initialize the Host Adapter Full Model Name from the Model Name.
1631 */
1632 strcpy(HostAdapter->FullModelName, "BusLogic ");
1633 strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
1634 /*
1635 Select an appropriate value for the Tagged Queue Depth either from a
1636 BusLogic Driver Options specification, or based on whether this Host
1637 Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth
1638 is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
1639 Initialize the Untagged Queue Depth.
1640 */
1641 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
1642 unsigned char QueueDepth = 0;
1643 if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
1644 QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
1645 else if (HostAdapter->BounceBuffersRequired)
1646 QueueDepth = BusLogic_TaggedQueueDepthBB;
1647 HostAdapter->QueueDepth[TargetID] = QueueDepth;
1648 }
1649 if (HostAdapter->BounceBuffersRequired)
1650 HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
1651 else
1652 HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
1653 if (HostAdapter->DriverOptions != NULL)
1654 HostAdapter->CommonQueueDepth = HostAdapter->DriverOptions->CommonQueueDepth;
1655 if (HostAdapter->CommonQueueDepth > 0 && HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
1656 HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
1657 /*
1658 Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1659 Therefore, mask the Tagged Queuing Permitted Default bits with the
1660 Disconnect/Reconnect Permitted bits.
1661 */
1662 HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
1663 /*
1664 Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
1665 Options Tagged Queuing specification.
1666 */
1667 if (HostAdapter->DriverOptions != NULL)
1668 HostAdapter->TaggedQueuingPermitted =
1669 (HostAdapter->DriverOptions->TaggedQueuingPermitted & HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
1670
1671 /*
1672 Select an appropriate value for Bus Settle Time either from a BusLogic
1673 Driver Options specification, or from BusLogic_DefaultBusSettleTime.
1674 */
1675 if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->BusSettleTime > 0)
1676 HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
1677 else
1678 HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
1679 /*
1680 Indicate reading the Host Adapter Configuration completed successfully.
1681 */
1682 return true;
1683}
1684
1685
1686/*
1687 BusLogic_ReportHostAdapterConfiguration reports the configuration of
1688 Host Adapter.
1689*/
1690
Richard Knutsson2065e312007-02-05 16:39:01 -08001691static bool __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 *HostAdapter)
1693{
1694 unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
1695 unsigned short SynchronousPermitted, FastPermitted;
1696 unsigned short UltraPermitted, WidePermitted;
1697 unsigned short DisconnectPermitted, TaggedQueuingPermitted;
Richard Knutsson2065e312007-02-05 16:39:01 -08001698 bool CommonSynchronousNegotiation, CommonTaggedQueueDepth;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 char SynchronousString[BusLogic_MaxTargetDevices + 1];
1700 char WideString[BusLogic_MaxTargetDevices + 1];
1701 char DisconnectString[BusLogic_MaxTargetDevices + 1];
1702 char TaggedQueuingString[BusLogic_MaxTargetDevices + 1];
1703 char *SynchronousMessage = SynchronousString;
1704 char *WideMessage = WideString;
1705 char *DisconnectMessage = DisconnectString;
1706 char *TaggedQueuingMessage = TaggedQueuingString;
1707 int TargetID;
1708 BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
1709 HostAdapter, HostAdapter->ModelName,
1710 BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], (HostAdapter->HostWideSCSI ? " Wide" : ""), (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
1711 BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", HostAdapter, HostAdapter->FirmwareVersion, HostAdapter->IO_Address, HostAdapter->IRQ_Channel, (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
1712 if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) {
1713 BusLogic_Info(" DMA Channel: ", HostAdapter);
1714 if (HostAdapter->DMA_Channel > 0)
1715 BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
1716 else
1717 BusLogic_Info("None, ", HostAdapter);
1718 if (HostAdapter->BIOS_Address > 0)
1719 BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, HostAdapter->BIOS_Address);
1720 else
1721 BusLogic_Info("BIOS Address: None, ", HostAdapter);
1722 } else {
1723 BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
1724 if (HostAdapter->PCI_Address > 0)
1725 BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
1726 else
1727 BusLogic_Info("Unassigned, ", HostAdapter);
1728 }
1729 BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, HostAdapter->SCSI_ID);
1730 BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n", HostAdapter, (HostAdapter->ParityCheckingEnabled ? "Enabled" : "Disabled"), (HostAdapter->ExtendedTranslationEnabled ? "Enabled" : "Disabled"));
1731 AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
1732 SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
1733 FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
1734 UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
1735 if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && (HostAdapter->FirmwareVersion[0] >= '4' || HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || BusLogic_FlashPointHostAdapterP(HostAdapter)) {
1736 CommonSynchronousNegotiation = false;
1737 if (SynchronousPermitted == 0) {
1738 SynchronousMessage = "Disabled";
1739 CommonSynchronousNegotiation = true;
1740 } else if (SynchronousPermitted == AllTargetsMask) {
1741 if (FastPermitted == 0) {
1742 SynchronousMessage = "Slow";
1743 CommonSynchronousNegotiation = true;
1744 } else if (FastPermitted == AllTargetsMask) {
1745 if (UltraPermitted == 0) {
1746 SynchronousMessage = "Fast";
1747 CommonSynchronousNegotiation = true;
1748 } else if (UltraPermitted == AllTargetsMask) {
1749 SynchronousMessage = "Ultra";
1750 CommonSynchronousNegotiation = true;
1751 }
1752 }
1753 }
1754 if (!CommonSynchronousNegotiation) {
1755 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1756 SynchronousString[TargetID] = ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : (!(FastPermitted & (1 << TargetID)) ? 'S' : (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
1757 SynchronousString[HostAdapter->SCSI_ID] = '#';
1758 SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
1759 }
1760 } else
1761 SynchronousMessage = (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
1762 WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
1763 if (WidePermitted == 0)
1764 WideMessage = "Disabled";
1765 else if (WidePermitted == AllTargetsMask)
1766 WideMessage = "Enabled";
1767 else {
1768 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1769 WideString[TargetID] = ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
1770 WideString[HostAdapter->SCSI_ID] = '#';
1771 WideString[HostAdapter->MaxTargetDevices] = '\0';
1772 }
1773 DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
1774 if (DisconnectPermitted == 0)
1775 DisconnectMessage = "Disabled";
1776 else if (DisconnectPermitted == AllTargetsMask)
1777 DisconnectMessage = "Enabled";
1778 else {
1779 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1780 DisconnectString[TargetID] = ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
1781 DisconnectString[HostAdapter->SCSI_ID] = '#';
1782 DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
1783 }
1784 TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
1785 if (TaggedQueuingPermitted == 0)
1786 TaggedQueuingMessage = "Disabled";
1787 else if (TaggedQueuingPermitted == AllTargetsMask)
1788 TaggedQueuingMessage = "Enabled";
1789 else {
1790 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1791 TaggedQueuingString[TargetID] = ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
1792 TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
1793 TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
1794 }
1795 BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n", HostAdapter, SynchronousMessage, WideMessage);
1796 BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", HostAdapter, DisconnectMessage, TaggedQueuingMessage);
1797 if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
1798 BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", HostAdapter, HostAdapter->DriverScatterGatherLimit, HostAdapter->HostAdapterScatterGatherLimit, HostAdapter->MailboxCount);
1799 BusLogic_Info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->HostAdapterQueueDepth);
1800 } else
1801 BusLogic_Info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->DriverScatterGatherLimit);
1802 BusLogic_Info(" Tagged Queue Depth: ", HostAdapter);
1803 CommonTaggedQueueDepth = true;
1804 for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1805 if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) {
1806 CommonTaggedQueueDepth = false;
1807 break;
1808 }
1809 if (CommonTaggedQueueDepth) {
1810 if (HostAdapter->QueueDepth[0] > 0)
1811 BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
1812 else
1813 BusLogic_Info("Automatic", HostAdapter);
1814 } else
1815 BusLogic_Info("Individual", HostAdapter);
1816 BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, HostAdapter->UntaggedQueueDepth);
1817 if (HostAdapter->TerminationInfoValid) {
1818 if (HostAdapter->HostWideSCSI)
1819 BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? (HostAdapter->HighByteTerminated ? "Both Enabled" : "Low Enabled")
1820 : (HostAdapter->HighByteTerminated ? "High Enabled" : "Both Disabled")));
1821 else
1822 BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled"));
1823 if (HostAdapter->HostSupportsSCAM)
1824 BusLogic_Info(", SCAM: %s", HostAdapter, (HostAdapter->SCAM_Enabled ? (HostAdapter->SCAM_Level2 ? "Enabled, Level 2" : "Enabled, Level 1")
1825 : "Disabled"));
1826 BusLogic_Info("\n", HostAdapter);
1827 }
1828 /*
1829 Indicate reporting the Host Adapter configuration completed successfully.
1830 */
1831 return true;
1832}
1833
1834
1835/*
1836 BusLogic_AcquireResources acquires the system resources necessary to use
1837 Host Adapter.
1838*/
1839
Richard Knutsson2065e312007-02-05 16:39:01 -08001840static bool __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
1842 if (HostAdapter->IRQ_Channel == 0) {
1843 BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
1844 return false;
1845 }
1846 /*
1847 Acquire shared access to the IRQ Channel.
1848 */
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07001849 if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, IRQF_SHARED, HostAdapter->FullModelName, HostAdapter) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->IRQ_Channel);
1851 return false;
1852 }
1853 HostAdapter->IRQ_ChannelAcquired = true;
1854 /*
1855 Acquire exclusive access to the DMA Channel.
1856 */
1857 if (HostAdapter->DMA_Channel > 0) {
1858 if (request_dma(HostAdapter->DMA_Channel, HostAdapter->FullModelName) < 0) {
1859 BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->DMA_Channel);
1860 return false;
1861 }
1862 set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
1863 enable_dma(HostAdapter->DMA_Channel);
1864 HostAdapter->DMA_ChannelAcquired = true;
1865 }
1866 /*
1867 Indicate the System Resource Acquisition completed successfully,
1868 */
1869 return true;
1870}
1871
1872
1873/*
1874 BusLogic_ReleaseResources releases any system resources previously acquired
1875 by BusLogic_AcquireResources.
1876*/
1877
1878static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
1879{
1880 /*
1881 Release shared access to the IRQ Channel.
1882 */
1883 if (HostAdapter->IRQ_ChannelAcquired)
1884 free_irq(HostAdapter->IRQ_Channel, HostAdapter);
1885 /*
1886 Release exclusive access to the DMA Channel.
1887 */
1888 if (HostAdapter->DMA_ChannelAcquired)
1889 free_dma(HostAdapter->DMA_Channel);
1890 /*
1891 Release any allocated memory structs not released elsewhere
1892 */
1893 if (HostAdapter->MailboxSpace)
1894 pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, HostAdapter->MailboxSpace, HostAdapter->MailboxSpaceHandle);
Alan Coxa07f3532006-09-15 15:34:32 +01001895 pci_dev_put(HostAdapter->PCI_Device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 HostAdapter->MailboxSpace = NULL;
1897 HostAdapter->MailboxSpaceHandle = 0;
1898 HostAdapter->MailboxSize = 0;
1899}
1900
1901
1902/*
1903 BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only
1904 function called during SCSI Host Adapter detection which modifies the state
1905 of the Host Adapter from its initial power on or hard reset state.
1906*/
1907
Richard Knutsson2065e312007-02-05 16:39:01 -08001908static bool BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 *HostAdapter)
1910{
1911 struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
1912 enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
1913 enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
1914 int TargetID;
1915 /*
1916 Initialize the pointers to the first and last CCBs that are queued for
1917 completion processing.
1918 */
1919 HostAdapter->FirstCompletedCCB = NULL;
1920 HostAdapter->LastCompletedCCB = NULL;
1921 /*
1922 Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
1923 Command Successful Flag, Active Commands, and Commands Since Reset
1924 for each Target Device.
1925 */
1926 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
1927 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
1928 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
1929 HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
1930 HostAdapter->ActiveCommands[TargetID] = 0;
1931 HostAdapter->CommandsSinceReset[TargetID] = 0;
1932 }
1933 /*
1934 FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
1935 */
1936 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1937 goto Done;
1938 /*
1939 Initialize the Outgoing and Incoming Mailbox pointers.
1940 */
1941 HostAdapter->MailboxSize = HostAdapter->MailboxCount * (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
1942 HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
1943 if (HostAdapter->MailboxSpace == NULL)
1944 return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
1945 HostAdapter->FirstOutgoingMailbox = (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
1946 HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
1947 HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
1948 HostAdapter->FirstIncomingMailbox = (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
1949 HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
1950 HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
1951
1952 /*
1953 Initialize the Outgoing and Incoming Mailbox structures.
1954 */
1955 memset(HostAdapter->FirstOutgoingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
1956 memset(HostAdapter->FirstIncomingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
1957 /*
1958 Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
1959 */
1960 ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
1961 ExtendedMailboxRequest.BaseMailboxAddress = (u32) HostAdapter->MailboxSpaceHandle;
1962 if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, &ExtendedMailboxRequest, sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
1963 return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
1964 /*
1965 Enable Strict Round Robin Mode if supported by the Host Adapter. In
1966 Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
1967 Mailbox for each new command, rather than scanning through all the
1968 Outgoing Mailboxes to find any that have new commands in them. Strict
1969 Round Robin Mode is significantly more efficient.
1970 */
1971 if (HostAdapter->StrictRoundRobinModeSupport) {
1972 RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
1973 if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, &RoundRobinModeRequest, sizeof(RoundRobinModeRequest), NULL, 0) < 0)
1974 return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
1975 }
1976 /*
1977 For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
1978 Format command to allow 32 Logical Units per Target Device.
1979 */
1980 if (HostAdapter->ExtendedLUNSupport) {
1981 SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
1982 if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0)
1983 return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
1984 }
1985 /*
1986 Announce Successful Initialization.
1987 */
1988 Done:
1989 if (!HostAdapter->HostAdapterInitialized) {
1990 BusLogic_Info("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
1991 BusLogic_Info("\n", HostAdapter);
1992 } else
1993 BusLogic_Warning("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
1994 HostAdapter->HostAdapterInitialized = true;
1995 /*
1996 Indicate the Host Adapter Initialization completed successfully.
1997 */
1998 return true;
1999}
2000
2001
2002/*
2003 BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
2004 through Host Adapter.
2005*/
2006
Richard Knutsson2065e312007-02-05 16:39:01 -08002007static bool __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 *HostAdapter)
2009{
2010 u16 InstalledDevices;
2011 u8 InstalledDevicesID0to7[8];
2012 struct BusLogic_SetupInformation SetupInformation;
2013 u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
2014 unsigned char RequestedReplyLength;
2015 int TargetID;
2016 /*
2017 Wait a few seconds between the Host Adapter Hard Reset which initiates
2018 a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
2019 confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
2020 */
2021 BusLogic_Delay(HostAdapter->BusSettleTime);
2022 /*
2023 FlashPoint Host Adapters do not provide for Target Device Inquiry.
2024 */
2025 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2026 return true;
2027 /*
2028 Inhibit the Target Device Inquiry if requested.
2029 */
2030 if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
2031 return true;
2032 /*
2033 Issue the Inquire Target Devices command for host adapters with firmware
2034 version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
2035 for older host adapters. This is necessary to force Synchronous Transfer
2036 Negotiation so that the Inquire Setup Information and Inquire Synchronous
2037 Period commands will return valid data. The Inquire Target Devices command
2038 is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
2039 Logical Unit 0 of each Target Device.
2040 */
2041 if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) {
2042
2043 /*
2044 * Issue a Inquire Target Devices command. Inquire Target Devices only
2045 * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
2046 * Devices commands which test Logical Units 0 - 7. Two bytes are
2047 * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
2048 * and so on.
2049 */
2050
2051 if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, &InstalledDevices, sizeof(InstalledDevices))
2052 != sizeof(InstalledDevices))
2053 return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
2054 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2055 HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? true : false);
2056 } else {
2057
2058 /*
2059 * Issue an Inquire Installed Devices command. For each Target Device,
2060 * a byte is returned where bit 0 set indicates that Logical Unit 0
2061 * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
2062 */
2063
2064 if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, NULL, 0, &InstalledDevicesID0to7, sizeof(InstalledDevicesID0to7))
2065 != sizeof(InstalledDevicesID0to7))
2066 return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2067 for (TargetID = 0; TargetID < 8; TargetID++)
2068 HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
2069 }
2070 /*
2071 Issue the Inquire Setup Information command.
2072 */
2073 RequestedReplyLength = sizeof(SetupInformation);
2074 if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
2075 != sizeof(SetupInformation))
2076 return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
2077 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2078 HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset : SetupInformation.SynchronousValuesID8to15[TargetID - 8].Offset);
2079 if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
2080 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2081 HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
2082 ? true : false)
2083 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID - 8))
2084 ? true : false));
2085 /*
2086 Issue the Inquire Synchronous Period command.
2087 */
2088 if (HostAdapter->FirmwareVersion[0] >= '3') {
2089
2090 /* Issue a Inquire Synchronous Period command. For each Target Device,
2091 * a byte is returned which represents the Synchronous Transfer Period
2092 * in units of 10 nanoseconds.
2093 */
2094
2095 RequestedReplyLength = sizeof(SynchronousPeriod);
2096 if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, &RequestedReplyLength, sizeof(RequestedReplyLength), &SynchronousPeriod, sizeof(SynchronousPeriod))
2097 != sizeof(SynchronousPeriod))
2098 return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
2099 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2100 HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
2101 } else
2102 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2103 if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
2104 HostAdapter->SynchronousPeriod[TargetID] = 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
2105 .TransferPeriod;
2106 /*
2107 Indicate the Target Device Inquiry completed successfully.
2108 */
2109 return true;
2110}
2111
2112/*
2113 BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
2114 structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
2115 SCSI Host structure are intentionally left uninitialized, as this driver
2116 handles acquisition and release of these resources explicitly, as well as
2117 ensuring exclusive access to the Host Adapter hardware and data structures
2118 through explicit acquisition and release of the Host Adapter's Lock.
2119*/
2120
2121static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter
2122 *HostAdapter, struct Scsi_Host *Host)
2123{
2124 Host->max_id = HostAdapter->MaxTargetDevices;
2125 Host->max_lun = HostAdapter->MaxLogicalUnits;
2126 Host->max_channel = 0;
2127 Host->unique_id = HostAdapter->IO_Address;
2128 Host->this_id = HostAdapter->SCSI_ID;
2129 Host->can_queue = HostAdapter->DriverQueueDepth;
2130 Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
2131 Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
2132 Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
2133}
2134
2135/*
2136 BusLogic_SlaveConfigure will actually set the queue depth on individual
2137 scsi devices as they are permanently added to the device chain. We
2138 shamelessly rip off the SelectQueueDepths code to make this work mostly
2139 like it used to. Since we don't get called once at the end of the scan
2140 but instead get called for each device, we have to do things a bit
2141 differently.
2142*/
2143static int BusLogic_SlaveConfigure(struct scsi_device *Device)
2144{
2145 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Device->host->hostdata;
2146 int TargetID = Device->id;
2147 int QueueDepth = HostAdapter->QueueDepth[TargetID];
2148
2149 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
2150 if (QueueDepth == 0)
2151 QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
2152 HostAdapter->QueueDepth[TargetID] = QueueDepth;
2153 scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
2154 } else {
2155 HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
2156 QueueDepth = HostAdapter->UntaggedQueueDepth;
2157 HostAdapter->QueueDepth[TargetID] = QueueDepth;
2158 scsi_adjust_queue_depth(Device, 0, QueueDepth);
2159 }
2160 QueueDepth = 0;
2161 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2162 if (HostAdapter->TargetFlags[TargetID].TargetExists) {
2163 QueueDepth += HostAdapter->QueueDepth[TargetID];
2164 }
2165 if (QueueDepth > HostAdapter->AllocatedCCBs)
2166 BusLogic_CreateAdditionalCCBs(HostAdapter, QueueDepth - HostAdapter->AllocatedCCBs, false);
2167 return 0;
2168}
2169
2170/*
2171 BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
2172 I/O Addresses where they may be located, initializing, registering, and
2173 reporting the configuration of each BusLogic Host Adapter it finds. It
2174 returns the number of BusLogic Host Adapters successfully initialized and
2175 registered.
2176*/
2177
2178static int __init BusLogic_init(void)
2179{
2180 int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
2181 struct BusLogic_HostAdapter *PrototypeHostAdapter;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002182 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
2184#ifdef MODULE
2185 if (BusLogic)
2186 BusLogic_Setup(BusLogic);
2187#endif
2188
2189 if (BusLogic_ProbeOptions.NoProbe)
2190 return -ENODEV;
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002191 BusLogic_ProbeInfoList =
2192 kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 if (BusLogic_ProbeInfoList == NULL) {
2194 BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
2195 return -ENOMEM;
2196 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002197
2198 PrototypeHostAdapter =
2199 kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 if (PrototypeHostAdapter == NULL) {
2201 kfree(BusLogic_ProbeInfoList);
2202 BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
2203 return -ENOMEM;
2204 }
Jeff Garzikdb3a8812006-11-08 19:56:20 -08002205
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206#ifdef MODULE
2207 if (BusLogic != NULL)
2208 BusLogic_Setup(BusLogic);
2209#endif
2210 BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
2211 for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) {
2212 struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
2213 struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
2214 struct Scsi_Host *Host;
2215 if (ProbeInfo->IO_Address == 0)
2216 continue;
2217 memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
2218 HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
2219 HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
2220 HostAdapter->IO_Address = ProbeInfo->IO_Address;
2221 HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
2222 HostAdapter->Bus = ProbeInfo->Bus;
2223 HostAdapter->Device = ProbeInfo->Device;
Petr Vandrovec745caf72006-01-11 11:31:07 -08002224 HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
2226 HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002227
2228 /*
2229 Make sure region is free prior to probing.
2230 */
2231 if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
2232 "BusLogic"))
2233 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 /*
2235 Probe the Host Adapter. If unsuccessful, abort further initialization.
2236 */
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002237 if (!BusLogic_ProbeHostAdapter(HostAdapter)) {
2238 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 /*
2242 Hard Reset the Host Adapter. If unsuccessful, abort further
2243 initialization.
2244 */
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002245 if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) {
2246 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 /*
2250 Check the Host Adapter. If unsuccessful, abort further initialization.
2251 */
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002252 if (!BusLogic_CheckHostAdapter(HostAdapter)) {
2253 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 continue;
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002255 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 /*
2257 Initialize the Driver Options field if provided.
2258 */
2259 if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
2260 HostAdapter->DriverOptions = &BusLogic_DriverOptions[DriverOptionsIndex++];
2261 /*
2262 Announce the Driver Version and Date, Author's Name, Copyright Notice,
2263 and Electronic Mail Address.
2264 */
2265 BusLogic_AnnounceDriver(HostAdapter);
2266 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 Register the SCSI Host structure.
2268 */
2269
2270 Host = scsi_host_alloc(&Bus_Logic_template, sizeof(struct BusLogic_HostAdapter));
2271 if (Host == NULL) {
2272 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
2273 continue;
2274 }
2275 HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
2276 memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
2277 HostAdapter->SCSI_Host = Host;
2278 HostAdapter->HostNumber = Host->host_no;
2279 /*
2280 Add Host Adapter to the end of the list of registered BusLogic
2281 Host Adapters.
2282 */
2283 list_add_tail(&HostAdapter->host_list, &BusLogic_host_list);
2284
2285 /*
2286 Read the Host Adapter Configuration, Configure the Host Adapter,
2287 Acquire the System Resources necessary to use the Host Adapter, then
2288 Create the Initial CCBs, Initialize the Host Adapter, and finally
2289 perform Target Device Inquiry.
Zachary Amsden1079a2d2007-04-10 08:53:08 -05002290
2291 From this point onward, any failure will be assumed to be due to a
2292 problem with the Host Adapter, rather than due to having mistakenly
2293 identified this port as belonging to a BusLogic Host Adapter. The
2294 I/O Address range will not be released, thereby preventing it from
2295 being incorrectly identified as any other type of Host Adapter.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 */
2297 if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002298 BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
2299 BusLogic_AcquireResources(HostAdapter) &&
2300 BusLogic_CreateInitialCCBs(HostAdapter) &&
2301 BusLogic_InitializeHostAdapter(HostAdapter) &&
2302 BusLogic_TargetDeviceInquiry(HostAdapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 /*
2304 Initialization has been completed successfully. Release and
2305 re-register usage of the I/O Address range so that the Model
2306 Name of the Host Adapter will appear, and initialize the SCSI
2307 Host structure.
2308 */
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002309 release_region(HostAdapter->IO_Address,
2310 HostAdapter->AddressCount);
2311 if (!request_region(HostAdapter->IO_Address,
2312 HostAdapter->AddressCount,
2313 HostAdapter->FullModelName)) {
2314 printk(KERN_WARNING
2315 "BusLogic: Release and re-register of "
2316 "port 0x%04lx failed \n",
2317 (unsigned long)HostAdapter->IO_Address);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 BusLogic_DestroyCCBs(HostAdapter);
2319 BusLogic_ReleaseResources(HostAdapter);
2320 list_del(&HostAdapter->host_list);
2321 scsi_host_put(Host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002322 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 } else {
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002324 BusLogic_InitializeHostStructure(HostAdapter,
2325 Host);
2326 if (scsi_add_host(Host, HostAdapter->PCI_Device
2327 ? &HostAdapter->PCI_Device->dev
2328 : NULL)) {
2329 printk(KERN_WARNING
2330 "BusLogic: scsi_add_host()"
2331 "failed!\n");
2332 BusLogic_DestroyCCBs(HostAdapter);
2333 BusLogic_ReleaseResources(HostAdapter);
2334 list_del(&HostAdapter->host_list);
2335 scsi_host_put(Host);
2336 ret = -ENODEV;
2337 } else {
2338 scsi_scan_host(Host);
2339 BusLogicHostAdapterCount++;
2340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 }
2342 } else {
2343 /*
2344 An error occurred during Host Adapter Configuration Querying, Host
2345 Adapter Configuration, Resource Acquisition, CCB Creation, Host
2346 Adapter Initialization, or Target Device Inquiry, so remove Host
2347 Adapter from the list of registered BusLogic Host Adapters, destroy
2348 the CCBs, Release the System Resources, and Unregister the SCSI
2349 Host.
2350 */
2351 BusLogic_DestroyCCBs(HostAdapter);
2352 BusLogic_ReleaseResources(HostAdapter);
2353 list_del(&HostAdapter->host_list);
2354 scsi_host_put(Host);
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002355 ret = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 }
2357 }
2358 kfree(PrototypeHostAdapter);
2359 kfree(BusLogic_ProbeInfoList);
2360 BusLogic_ProbeInfoList = NULL;
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002361 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362}
2363
2364
2365/*
2366 BusLogic_ReleaseHostAdapter releases all resources previously acquired to
2367 support a specific Host Adapter, including the I/O Address range, and
2368 unregisters the BusLogic Host Adapter.
2369*/
2370
2371static int __exit BusLogic_ReleaseHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
2372{
2373 struct Scsi_Host *Host = HostAdapter->SCSI_Host;
2374
2375 scsi_remove_host(Host);
2376
2377 /*
2378 FlashPoint Host Adapters must first be released by the FlashPoint
2379 SCCB Manager.
2380 */
2381 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2382 FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
2383 /*
2384 Destroy the CCBs and release any system resources acquired to
2385 support Host Adapter.
2386 */
2387 BusLogic_DestroyCCBs(HostAdapter);
2388 BusLogic_ReleaseResources(HostAdapter);
2389 /*
2390 Release usage of the I/O Address range.
2391 */
2392 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
2393 /*
2394 Remove Host Adapter from the list of registered BusLogic Host Adapters.
2395 */
2396 list_del(&HostAdapter->host_list);
2397
2398 scsi_host_put(Host);
2399 return 0;
2400}
2401
2402
2403/*
2404 BusLogic_QueueCompletedCCB queues CCB for completion processing.
2405*/
2406
2407static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB)
2408{
2409 struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
2410 CCB->Status = BusLogic_CCB_Completed;
2411 CCB->Next = NULL;
2412 if (HostAdapter->FirstCompletedCCB == NULL) {
2413 HostAdapter->FirstCompletedCCB = CCB;
2414 HostAdapter->LastCompletedCCB = CCB;
2415 } else {
2416 HostAdapter->LastCompletedCCB->Next = CCB;
2417 HostAdapter->LastCompletedCCB = CCB;
2418 }
2419 HostAdapter->ActiveCommands[CCB->TargetID]--;
2420}
2421
2422
2423/*
2424 BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
2425 the Host Adapter Status and Target Device Status.
2426*/
2427
2428static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_HostAdapterStatus HostAdapterStatus, enum BusLogic_TargetDeviceStatus TargetDeviceStatus)
2429{
2430 int HostStatus;
2431 switch (HostAdapterStatus) {
2432 case BusLogic_CommandCompletedNormally:
2433 case BusLogic_LinkedCommandCompleted:
2434 case BusLogic_LinkedCommandCompletedWithFlag:
2435 HostStatus = DID_OK;
2436 break;
2437 case BusLogic_SCSISelectionTimeout:
2438 HostStatus = DID_TIME_OUT;
2439 break;
2440 case BusLogic_InvalidOutgoingMailboxActionCode:
2441 case BusLogic_InvalidCommandOperationCode:
2442 case BusLogic_InvalidCommandParameter:
2443 BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", HostAdapter, HostAdapterStatus);
2444 case BusLogic_DataUnderRun:
2445 case BusLogic_DataOverRun:
2446 case BusLogic_UnexpectedBusFree:
2447 case BusLogic_LinkedCCBhasInvalidLUN:
2448 case BusLogic_AutoRequestSenseFailed:
2449 case BusLogic_TaggedQueuingMessageRejected:
2450 case BusLogic_UnsupportedMessageReceived:
2451 case BusLogic_HostAdapterHardwareFailed:
2452 case BusLogic_TargetDeviceReconnectedImproperly:
2453 case BusLogic_AbortQueueGenerated:
2454 case BusLogic_HostAdapterSoftwareError:
2455 case BusLogic_HostAdapterHardwareTimeoutError:
2456 case BusLogic_SCSIParityErrorDetected:
2457 HostStatus = DID_ERROR;
2458 break;
2459 case BusLogic_InvalidBusPhaseRequested:
2460 case BusLogic_TargetFailedResponseToATN:
2461 case BusLogic_HostAdapterAssertedRST:
2462 case BusLogic_OtherDeviceAssertedRST:
2463 case BusLogic_HostAdapterAssertedBusDeviceReset:
2464 HostStatus = DID_RESET;
2465 break;
2466 default:
2467 BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", HostAdapter, HostAdapterStatus);
2468 HostStatus = DID_ERROR;
2469 break;
2470 }
2471 return (HostStatus << 16) | TargetDeviceStatus;
2472}
2473
2474
2475/*
2476 BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
2477 Incoming Mailbox entries for completion processing.
2478*/
2479
2480static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdapter)
2481{
2482 /*
2483 Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
2484 any completed CCBs for further processing. It is essential that for each
2485 CCB and SCSI Command issued, command completion processing is performed
2486 exactly once. Therefore, only Incoming Mailboxes with completion code
2487 Command Completed Without Error, Command Completed With Error, or Command
2488 Aborted At Host Request are saved for completion processing. When an
2489 Incoming Mailbox has a completion code of Aborted Command Not Found, the
2490 CCB had already completed or been aborted before the current Abort request
2491 was processed, and so completion processing has already occurred and no
2492 further action should be taken.
2493 */
2494 struct BusLogic_IncomingMailbox *NextIncomingMailbox = HostAdapter->NextIncomingMailbox;
2495 enum BusLogic_CompletionCode CompletionCode;
2496 while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) {
2497 /*
2498 We are only allowed to do this because we limit our architectures we
2499 run on to machines where bus_to_virt() actually works. There *needs*
2500 to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
2501 replace bus_to_virt() or else this code is going to become very
2502 innefficient.
2503 */
2504 struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) Bus_to_Virtual(NextIncomingMailbox->CCB);
2505 if (CompletionCode != BusLogic_AbortedCommandNotFound) {
2506 if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) {
2507 /*
2508 Save the Completion Code for this CCB and queue the CCB
2509 for completion processing.
2510 */
2511 CCB->CompletionCode = CompletionCode;
2512 BusLogic_QueueCompletedCCB(CCB);
2513 } else {
2514 /*
2515 If a CCB ever appears in an Incoming Mailbox and is not marked
2516 as status Active or Reset, then there is most likely a bug in
2517 the Host Adapter firmware.
2518 */
2519 BusLogic_Warning("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", HostAdapter, CCB->SerialNumber, CCB->Status);
2520 }
2521 }
2522 NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
2523 if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
2524 NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
2525 }
2526 HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
2527}
2528
2529
2530/*
2531 BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
2532 Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
2533 calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
2534 should already have been acquired by the caller.
2535*/
2536
2537static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapter)
2538{
2539 if (HostAdapter->ProcessCompletedCCBsActive)
2540 return;
2541 HostAdapter->ProcessCompletedCCBsActive = true;
2542 while (HostAdapter->FirstCompletedCCB != NULL) {
2543 struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
2544 struct scsi_cmnd *Command = CCB->Command;
2545 HostAdapter->FirstCompletedCCB = CCB->Next;
2546 if (HostAdapter->FirstCompletedCCB == NULL)
2547 HostAdapter->LastCompletedCCB = NULL;
2548 /*
2549 Process the Completed CCB.
2550 */
2551 if (CCB->Opcode == BusLogic_BusDeviceReset) {
2552 int TargetID = CCB->TargetID;
2553 BusLogic_Warning("Bus Device Reset CCB #%ld to Target " "%d Completed\n", HostAdapter, CCB->SerialNumber, TargetID);
2554 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
2555 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
2556 HostAdapter->CommandsSinceReset[TargetID] = 0;
2557 HostAdapter->LastResetCompleted[TargetID] = jiffies;
2558 /*
2559 Place CCB back on the Host Adapter's free list.
2560 */
2561 BusLogic_DeallocateCCB(CCB);
2562#if 0 /* this needs to be redone different for new EH */
2563 /*
2564 Bus Device Reset CCBs have the Command field non-NULL only when a
2565 Bus Device Reset was requested for a Command that did not have a
2566 currently active CCB in the Host Adapter (i.e., a Synchronous
2567 Bus Device Reset), and hence would not have its Completion Routine
2568 called otherwise.
2569 */
2570 while (Command != NULL) {
2571 struct scsi_cmnd *NextCommand = Command->reset_chain;
2572 Command->reset_chain = NULL;
2573 Command->result = DID_RESET << 16;
2574 Command->scsi_done(Command);
2575 Command = NextCommand;
2576 }
2577#endif
2578 /*
2579 Iterate over the CCBs for this Host Adapter performing completion
2580 processing for any CCBs marked as Reset for this Target.
2581 */
2582 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
2583 if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) {
2584 Command = CCB->Command;
2585 BusLogic_DeallocateCCB(CCB);
2586 HostAdapter->ActiveCommands[TargetID]--;
2587 Command->result = DID_RESET << 16;
2588 Command->scsi_done(Command);
2589 }
2590 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
2591 } else {
2592 /*
2593 Translate the Completion Code, Host Adapter Status, and Target
2594 Device Status into a SCSI Subsystem Result Code.
2595 */
2596 switch (CCB->CompletionCode) {
2597 case BusLogic_IncomingMailboxFree:
2598 case BusLogic_AbortedCommandNotFound:
2599 case BusLogic_InvalidCCB:
2600 BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
2601 break;
2602 case BusLogic_CommandCompletedWithoutError:
2603 HostAdapter->TargetStatistics[CCB->TargetID]
2604 .CommandsCompleted++;
2605 HostAdapter->TargetFlags[CCB->TargetID]
2606 .CommandSuccessfulFlag = true;
2607 Command->result = DID_OK << 16;
2608 break;
2609 case BusLogic_CommandAbortedAtHostRequest:
2610 BusLogic_Warning("CCB #%ld to Target %d Aborted\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
2611 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID]
2612 .CommandAbortsCompleted);
2613 Command->result = DID_ABORT << 16;
2614 break;
2615 case BusLogic_CommandCompletedWithError:
2616 Command->result = BusLogic_ComputeResultCode(HostAdapter, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
2617 if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) {
2618 HostAdapter->TargetStatistics[CCB->TargetID]
2619 .CommandsCompleted++;
2620 if (BusLogic_GlobalOptions.TraceErrors) {
2621 int i;
2622 BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
2623 "Adapter Status %02X " "Target Status %02X\n", HostAdapter, CCB->SerialNumber, CCB->TargetID, Command->result, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
2624 BusLogic_Notice("CDB ", HostAdapter);
2625 for (i = 0; i < CCB->CDB_Length; i++)
2626 BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
2627 BusLogic_Notice("\n", HostAdapter);
2628 BusLogic_Notice("Sense ", HostAdapter);
2629 for (i = 0; i < CCB->SenseDataLength; i++)
2630 BusLogic_Notice(" %02X", HostAdapter, Command->sense_buffer[i]);
2631 BusLogic_Notice("\n", HostAdapter);
2632 }
2633 }
2634 break;
2635 }
2636 /*
2637 When an INQUIRY command completes normally, save the
2638 CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
2639 Wide Data Transfers Supported) bits.
2640 */
2641 if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 && CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) {
2642 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[CCB->TargetID];
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002643 struct SCSI_Inquiry *InquiryResult =
2644 (struct SCSI_Inquiry *) scsi_sglist(Command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 TargetFlags->TargetExists = true;
2646 TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
2647 TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
2648 }
2649 /*
2650 Place CCB back on the Host Adapter's free list.
2651 */
2652 BusLogic_DeallocateCCB(CCB);
2653 /*
2654 Call the SCSI Command Completion Routine.
2655 */
2656 Command->scsi_done(Command);
2657 }
2658 }
2659 HostAdapter->ProcessCompletedCCBsActive = false;
2660}
2661
2662
2663/*
2664 BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
2665 Adapters.
2666*/
2667
David Howells7d12e782006-10-05 14:55:46 +01002668static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669{
2670 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier;
2671 unsigned long ProcessorFlags;
2672 /*
2673 Acquire exclusive access to Host Adapter.
2674 */
2675 spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
2676 /*
2677 Handle Interrupts appropriately for each Host Adapter type.
2678 */
2679 if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
2680 union BusLogic_InterruptRegister InterruptRegister;
2681 /*
2682 Read the Host Adapter Interrupt Register.
2683 */
2684 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
2685 if (InterruptRegister.ir.InterruptValid) {
2686 /*
2687 Acknowledge the interrupt and reset the Host Adapter
2688 Interrupt Register.
2689 */
2690 BusLogic_InterruptReset(HostAdapter);
2691 /*
2692 Process valid External SCSI Bus Reset and Incoming Mailbox
2693 Loaded Interrupts. Command Complete Interrupts are noted,
2694 and Outgoing Mailbox Available Interrupts are ignored, as
2695 they are never enabled.
2696 */
2697 if (InterruptRegister.ir.ExternalBusReset)
2698 HostAdapter->HostAdapterExternalReset = true;
2699 else if (InterruptRegister.ir.IncomingMailboxLoaded)
2700 BusLogic_ScanIncomingMailboxes(HostAdapter);
2701 else if (InterruptRegister.ir.CommandComplete)
2702 HostAdapter->HostAdapterCommandCompleted = true;
2703 }
2704 } else {
2705 /*
2706 Check if there is a pending interrupt for this Host Adapter.
2707 */
2708 if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
2709 switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) {
2710 case FlashPoint_NormalInterrupt:
2711 break;
2712 case FlashPoint_ExternalBusReset:
2713 HostAdapter->HostAdapterExternalReset = true;
2714 break;
2715 case FlashPoint_InternalError:
2716 BusLogic_Warning("Internal FlashPoint Error detected" " - Resetting Host Adapter\n", HostAdapter);
2717 HostAdapter->HostAdapterInternalError = true;
2718 break;
2719 }
2720 }
2721 /*
2722 Process any completed CCBs.
2723 */
2724 if (HostAdapter->FirstCompletedCCB != NULL)
2725 BusLogic_ProcessCompletedCCBs(HostAdapter);
2726 /*
2727 Reset the Host Adapter if requested.
2728 */
2729 if (HostAdapter->HostAdapterExternalReset) {
2730 BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", HostAdapter, HostAdapter->FullModelName);
2731 BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
2732 BusLogic_ResetHostAdapter(HostAdapter, false);
2733 HostAdapter->HostAdapterExternalReset = false;
2734 } else if (HostAdapter->HostAdapterInternalError) {
2735 BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", HostAdapter, HostAdapter->FullModelName);
2736 BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
2737 BusLogic_ResetHostAdapter(HostAdapter, true);
2738 HostAdapter->HostAdapterInternalError = false;
2739 }
2740 /*
2741 Release exclusive access to Host Adapter.
2742 */
2743 spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, ProcessorFlags);
2744 return IRQ_HANDLED;
2745}
2746
2747
2748/*
2749 BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
2750 Mailbox for execution by Host Adapter. The Host Adapter's Lock should
2751 already have been acquired by the caller.
2752*/
2753
Richard Knutsson2065e312007-02-05 16:39:01 -08002754static bool BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
2756{
2757 struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
2758 NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
2759 if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) {
2760 CCB->Status = BusLogic_CCB_Active;
2761 /*
2762 The CCB field must be written before the Action Code field since
2763 the Host Adapter is operating asynchronously and the locking code
2764 does not protect against simultaneous access by the Host Adapter.
2765 */
2766 NextOutgoingMailbox->CCB = CCB->DMA_Handle;
2767 NextOutgoingMailbox->ActionCode = ActionCode;
2768 BusLogic_StartMailboxCommand(HostAdapter);
2769 if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
2770 NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
2771 HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
2772 if (ActionCode == BusLogic_MailboxStartCommand) {
2773 HostAdapter->ActiveCommands[CCB->TargetID]++;
2774 if (CCB->Opcode != BusLogic_BusDeviceReset)
2775 HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
2776 }
2777 return true;
2778 }
2779 return false;
2780}
2781
2782/* Error Handling (EH) support */
2783
2784static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
2785{
2786 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
2787
2788 unsigned int id = SCpnt->device->id;
2789 struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
Jeff Garzik df0ae242005-05-28 07:57:14 -04002790 int rc;
2791
2792 spin_lock_irq(SCpnt->device->host->host_lock);
2793
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
2795
Jeff Garzik df0ae242005-05-28 07:57:14 -04002796 rc = BusLogic_ResetHostAdapter(HostAdapter, false);
2797 spin_unlock_irq(SCpnt->device->host->host_lock);
2798 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799}
2800
2801/*
2802 BusLogic_QueueCommand creates a CCB for Command and places it into an
2803 Outgoing Mailbox for execution by the associated Host Adapter.
2804*/
2805
2806static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRoutine) (struct scsi_cmnd *))
2807{
2808 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
2809 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[Command->device->id];
2810 struct BusLogic_TargetStatistics *TargetStatistics = HostAdapter->TargetStatistics;
2811 unsigned char *CDB = Command->cmnd;
2812 int CDB_Length = Command->cmd_len;
2813 int TargetID = Command->device->id;
2814 int LogicalUnit = Command->device->lun;
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002815 int BufferLength = scsi_bufflen(Command);
2816 int Count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 struct BusLogic_CCB *CCB;
2818 /*
2819 SCSI REQUEST_SENSE commands will be executed automatically by the Host
2820 Adapter for any errors, so they should not be executed explicitly unless
2821 the Sense Data is zero indicating that no error occurred.
2822 */
2823 if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
2824 Command->result = DID_OK << 16;
2825 CompletionRoutine(Command);
2826 return 0;
2827 }
2828 /*
2829 Allocate a CCB from the Host Adapter's free list. In the unlikely event
2830 that there are none available and memory allocation fails, wait 1 second
2831 and try again. If that fails, the Host Adapter is probably hung so signal
2832 an error as a Host Adapter Hard Reset should be initiated soon.
2833 */
2834 CCB = BusLogic_AllocateCCB(HostAdapter);
2835 if (CCB == NULL) {
2836 spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
2837 BusLogic_Delay(1);
2838 spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
2839 CCB = BusLogic_AllocateCCB(HostAdapter);
2840 if (CCB == NULL) {
2841 Command->result = DID_ERROR << 16;
2842 CompletionRoutine(Command);
2843 return 0;
2844 }
2845 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002846
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 /*
2848 Initialize the fields in the BusLogic Command Control Block (CCB).
2849 */
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002850 Count = scsi_dma_map(Command);
2851 BUG_ON(Count < 0);
2852 if (Count) {
2853 struct scatterlist *sg;
2854 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
2857 CCB->DataLength = Count * sizeof(struct BusLogic_ScatterGatherSegment);
2858 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
2859 CCB->DataPointer = (unsigned int) CCB->DMA_Handle + ((unsigned long) &CCB->ScatterGatherList - (unsigned long) CCB);
2860 else
2861 CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002862
2863 scsi_for_each_sg(Command, sg, Count, i) {
2864 CCB->ScatterGatherList[i].SegmentByteCount =
2865 sg_dma_len(sg);
2866 CCB->ScatterGatherList[i].SegmentDataPointer =
2867 sg_dma_address(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002869 } else if (!Count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 CCB->Opcode = BusLogic_InitiatorCCB;
2871 CCB->DataLength = BufferLength;
2872 CCB->DataPointer = 0;
2873 }
FUJITA Tomonoriddc914c72007-05-14 15:43:56 +09002874
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 switch (CDB[0]) {
2876 case READ_6:
2877 case READ_10:
2878 CCB->DataDirection = BusLogic_DataInLengthChecked;
2879 TargetStatistics[TargetID].ReadCommands++;
2880 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
2881 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
2882 break;
2883 case WRITE_6:
2884 case WRITE_10:
2885 CCB->DataDirection = BusLogic_DataOutLengthChecked;
2886 TargetStatistics[TargetID].WriteCommands++;
2887 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
2888 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
2889 break;
2890 default:
2891 CCB->DataDirection = BusLogic_UncheckedDataTransfer;
2892 break;
2893 }
2894 CCB->CDB_Length = CDB_Length;
2895 CCB->HostAdapterStatus = 0;
2896 CCB->TargetDeviceStatus = 0;
2897 CCB->TargetID = TargetID;
2898 CCB->LogicalUnit = LogicalUnit;
2899 CCB->TagEnable = false;
2900 CCB->LegacyTagEnable = false;
2901 /*
2902 BusLogic recommends that after a Reset the first couple of commands that
2903 are sent to a Target Device be sent in a non Tagged Queue fashion so that
2904 the Host Adapter and Target Device can establish Synchronous and Wide
2905 Transfer before Queue Tag messages can interfere with the Synchronous and
2906 Wide Negotiation messages. By waiting to enable Tagged Queuing until after
2907 the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
2908 assured that after a Reset any pending commands are requeued before Tagged
2909 Queuing is enabled and that the Tagged Queuing message will not occur while
2910 the partition table is being printed. In addition, some devices do not
2911 properly handle the transition from non-tagged to tagged commands, so it is
2912 necessary to wait until there are no pending commands for a target device
2913 before queuing tagged commands.
2914 */
2915 if (HostAdapter->CommandsSinceReset[TargetID]++ >=
2916 BusLogic_MaxTaggedQueueDepth && !TargetFlags->TaggedQueuingActive && HostAdapter->ActiveCommands[TargetID] == 0 && TargetFlags->TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
2917 TargetFlags->TaggedQueuingActive = true;
2918 BusLogic_Notice("Tagged Queuing now active for Target %d\n", HostAdapter, TargetID);
2919 }
2920 if (TargetFlags->TaggedQueuingActive) {
2921 enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
2922 /*
2923 When using Tagged Queuing with Simple Queue Tags, it appears that disk
2924 drive controllers do not guarantee that a queued command will not
2925 remain in a disconnected state indefinitely if commands that read or
2926 write nearer the head position continue to arrive without interruption.
2927 Therefore, for each Target Device this driver keeps track of the last
2928 time either the queue was empty or an Ordered Queue Tag was issued. If
2929 more than 4 seconds (one fifth of the 20 second disk timeout) have
2930 elapsed since this last sequence point, this command will be issued
2931 with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
2932 the Target Device to complete all previously queued commands before
2933 this command may be executed.
2934 */
2935 if (HostAdapter->ActiveCommands[TargetID] == 0)
2936 HostAdapter->LastSequencePoint[TargetID] = jiffies;
Marcelo Feitoza Parisi60c904a2006-03-28 01:56:47 -08002937 else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 HostAdapter->LastSequencePoint[TargetID] = jiffies;
2939 QueueTag = BusLogic_OrderedQueueTag;
2940 }
2941 if (HostAdapter->ExtendedLUNSupport) {
2942 CCB->TagEnable = true;
2943 CCB->QueueTag = QueueTag;
2944 } else {
2945 CCB->LegacyTagEnable = true;
2946 CCB->LegacyQueueTag = QueueTag;
2947 }
2948 }
2949 memcpy(CCB->CDB, CDB, CDB_Length);
FUJITA Tomonorib80ca4f2008-01-13 15:46:13 +09002950 CCB->SenseDataLength = SCSI_SENSE_BUFFERSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, Command->sense_buffer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
2952 CCB->Command = Command;
2953 Command->scsi_done = CompletionRoutine;
2954 if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
2955 /*
2956 Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI
2957 Subsystem should not attempt to queue more commands than can be placed
2958 in Outgoing Mailboxes, so there should always be one free. In the
2959 unlikely event that there are none available, wait 1 second and try
2960 again. If that fails, the Host Adapter is probably hung so signal an
2961 error as a Host Adapter Hard Reset should be initiated soon.
2962 */
2963 if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
2964 spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
2965 BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
2966 BusLogic_Delay(1);
2967 spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
2968 if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
2969 BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
2970 BusLogic_DeallocateCCB(CCB);
2971 Command->result = DID_ERROR << 16;
2972 Command->scsi_done(Command);
2973 }
2974 }
2975 } else {
2976 /*
2977 Call the FlashPoint SCCB Manager to start execution of the CCB.
2978 */
2979 CCB->Status = BusLogic_CCB_Active;
2980 HostAdapter->ActiveCommands[TargetID]++;
2981 TargetStatistics[TargetID].CommandsAttempted++;
2982 FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
2983 /*
2984 The Command may have already completed and BusLogic_QueueCompletedCCB
2985 been called, or it may still be pending.
2986 */
2987 if (CCB->Status == BusLogic_CCB_Completed)
2988 BusLogic_ProcessCompletedCCBs(HostAdapter);
2989 }
2990 return 0;
2991}
2992
2993
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07002994#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995/*
2996 BusLogic_AbortCommand aborts Command if possible.
2997*/
2998
2999static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
3000{
3001 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
3002
3003 int TargetID = Command->device->id;
3004 struct BusLogic_CCB *CCB;
3005 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
3006 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 Attempt to find an Active CCB for this Command. If no Active CCB for this
3008 Command is found, then no Abort is necessary.
3009 */
3010 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3011 if (CCB->Command == Command)
3012 break;
3013 if (CCB == NULL) {
3014 BusLogic_Warning("Unable to Abort Command to Target %d - " "No CCB Found\n", HostAdapter, TargetID);
3015 return SUCCESS;
3016 } else if (CCB->Status == BusLogic_CCB_Completed) {
3017 BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Completed\n", HostAdapter, TargetID);
3018 return SUCCESS;
3019 } else if (CCB->Status == BusLogic_CCB_Reset) {
3020 BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Reset\n", HostAdapter, TargetID);
3021 return SUCCESS;
3022 }
3023 if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
3024 /*
3025 Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx
3026 do not generate Abort Tag messages, but only generate the non-tagged
3027 Abort message. Since non-tagged commands are not sent by the Host
3028 Adapter until the queue of outstanding tagged commands has completed,
3029 and the Abort message is treated as a non-tagged command, it is
3030 effectively impossible to abort commands when Tagged Queuing is active.
3031 Firmware version 5.xx does generate Abort Tag messages, so it is
3032 possible to abort commands when Tagged Queuing is active.
3033 */
3034 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && HostAdapter->FirmwareVersion[0] < '5') {
3035 BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "Abort Tag Not Supported\n", HostAdapter, CCB->SerialNumber, TargetID);
3036 return FAILURE;
3037 } else if (BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxAbortCommand, CCB)) {
3038 BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
3039 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3040 return SUCCESS;
3041 } else {
3042 BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "No Outgoing Mailboxes\n", HostAdapter, CCB->SerialNumber, TargetID);
3043 return FAILURE;
3044 }
3045 } else {
3046 /*
3047 Call the FlashPoint SCCB Manager to abort execution of the CCB.
3048 */
3049 BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
3050 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3051 FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
3052 /*
3053 The Abort may have already been completed and
3054 BusLogic_QueueCompletedCCB been called, or it
3055 may still be pending.
3056 */
3057 if (CCB->Status == BusLogic_CCB_Completed) {
3058 BusLogic_ProcessCompletedCCBs(HostAdapter);
3059 }
3060 return SUCCESS;
3061 }
3062 return SUCCESS;
3063}
3064
Daniel Walkerd2afb3a2006-08-14 23:09:23 -07003065#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066/*
3067 BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
3068 currently executing SCSI Commands as having been Reset.
3069*/
3070
Richard Knutsson2065e312007-02-05 16:39:01 -08003071static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, bool HardReset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072{
3073 struct BusLogic_CCB *CCB;
3074 int TargetID;
3075
3076 /*
3077 * Attempt to Reset and Reinitialize the Host Adapter.
3078 */
3079
3080 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(HostAdapter))) {
3081 BusLogic_Error("Resetting %s Failed\n", HostAdapter, HostAdapter->FullModelName);
3082 return FAILURE;
3083 }
3084
3085 /*
3086 * Deallocate all currently executing CCBs.
3087 */
3088
3089 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3090 if (CCB->Status == BusLogic_CCB_Active)
3091 BusLogic_DeallocateCCB(CCB);
3092 /*
3093 * Wait a few seconds between the Host Adapter Hard Reset which
3094 * initiates a SCSI Bus Reset and issuing any SCSI Commands. Some
3095 * SCSI devices get confused if they receive SCSI Commands too soon
3096 * after a SCSI Bus Reset.
3097 */
3098
3099 if (HardReset) {
3100 spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
3101 BusLogic_Delay(HostAdapter->BusSettleTime);
3102 spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
3103 }
3104
3105 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3106 HostAdapter->LastResetAttempted[TargetID] = jiffies;
3107 HostAdapter->LastResetCompleted[TargetID] = jiffies;
3108 }
3109 return SUCCESS;
3110}
3111
3112/*
3113 BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
3114 Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
3115 the appropriate number of cylinders so as not to exceed drive capacity. In
3116 order for disks equal to or larger than 1 GB to be addressable by the BIOS
3117 without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
3118 may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
3119 series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
3120 series MultiMaster Host Adapters. With Extended Translation enabled, drives
3121 between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
3122 heads and 32 sectors, and drives above 2 GB inclusive are given a disk
3123 geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
3124 Extended Translation setting does not match the geometry in the partition
3125 table, then the translation inferred from the partition table will be used by
3126 the BIOS, and a warning may be displayed.
3127*/
3128
3129static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, sector_t capacity, int *Parameters)
3130{
3131 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
3132 struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
3133 unsigned char *buf;
3134 if (HostAdapter->ExtendedTranslationEnabled && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */ ) {
3135 if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */ ) {
3136 DiskParameters->Heads = 255;
3137 DiskParameters->Sectors = 63;
3138 } else {
3139 DiskParameters->Heads = 128;
3140 DiskParameters->Sectors = 32;
3141 }
3142 } else {
3143 DiskParameters->Heads = 64;
3144 DiskParameters->Sectors = 32;
3145 }
3146 DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
3147 buf = scsi_bios_ptable(Device);
3148 if (buf == NULL)
3149 return 0;
3150 /*
3151 If the boot sector partition table flag is valid, search for a partition
3152 table entry whose end_head matches one of the standard BusLogic geometry
3153 translations (64/32, 128/32, or 255/63).
3154 */
3155 if (*(unsigned short *) (buf + 64) == 0xAA55) {
3156 struct partition *FirstPartitionEntry = (struct partition *) buf;
3157 struct partition *PartitionEntry = FirstPartitionEntry;
3158 int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
3159 unsigned char PartitionEntryEndHead = 0, PartitionEntryEndSector = 0;
3160 for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) {
3161 PartitionEntryEndHead = PartitionEntry->end_head;
3162 PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
3163 if (PartitionEntryEndHead == 64 - 1) {
3164 DiskParameters->Heads = 64;
3165 DiskParameters->Sectors = 32;
3166 break;
3167 } else if (PartitionEntryEndHead == 128 - 1) {
3168 DiskParameters->Heads = 128;
3169 DiskParameters->Sectors = 32;
3170 break;
3171 } else if (PartitionEntryEndHead == 255 - 1) {
3172 DiskParameters->Heads = 255;
3173 DiskParameters->Sectors = 63;
3174 break;
3175 }
3176 PartitionEntry++;
3177 }
3178 if (PartitionNumber == 4) {
3179 PartitionEntryEndHead = FirstPartitionEntry->end_head;
3180 PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
3181 }
3182 DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
3183 if (PartitionNumber < 4 && PartitionEntryEndSector == DiskParameters->Sectors) {
3184 if (DiskParameters->Cylinders != SavedCylinders)
3185 BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
3186 } else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) {
3187 BusLogic_Warning("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", HostAdapter, PartitionEntryEndHead + 1, PartitionEntryEndSector);
3188 BusLogic_Warning("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
3189 }
3190 }
3191 kfree(buf);
3192 return 0;
3193}
3194
3195
3196/*
3197 BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
3198*/
3199
3200static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
3201{
3202 struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) shost->hostdata;
3203 struct BusLogic_TargetStatistics *TargetStatistics;
3204 int TargetID, Length;
3205 char *Buffer;
3206
3207 TargetStatistics = HostAdapter->TargetStatistics;
3208 if (WriteFlag) {
3209 HostAdapter->ExternalHostAdapterResets = 0;
3210 HostAdapter->HostAdapterInternalErrors = 0;
3211 memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
3212 return 0;
3213 }
3214 Buffer = HostAdapter->MessageBuffer;
3215 Length = HostAdapter->MessageBufferLength;
3216 Length += sprintf(&Buffer[Length], "\n\
3217Current Driver Queue Depth: %d\n\
3218Currently Allocated CCBs: %d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
3219 Length += sprintf(&Buffer[Length], "\n\n\
3220 DATA TRANSFER STATISTICS\n\
3221\n\
3222Target Tagged Queuing Queue Depth Active Attempted Completed\n\
3223====== ============== =========== ====== ========= =========\n");
3224 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3225 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
3226 if (!TargetFlags->TargetExists)
3227 continue;
3228 Length += sprintf(&Buffer[Length], " %2d %s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? " Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
3229 ? " Permitted" : " Disabled"))
3230 : "Not Supported"));
3231 Length += sprintf(&Buffer[Length],
3232 " %3d %3u %9u %9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
3233 }
3234 Length += sprintf(&Buffer[Length], "\n\
3235Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
3236====== ============= ============== =================== ===================\n");
3237 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3238 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
3239 if (!TargetFlags->TargetExists)
3240 continue;
3241 Length += sprintf(&Buffer[Length], " %2d %9u %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
3242 if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
3243 Length += sprintf(&Buffer[Length], " %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
3244 else
3245 Length += sprintf(&Buffer[Length], " %9u", TargetStatistics[TargetID].TotalBytesRead.Units);
3246 if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
3247 Length += sprintf(&Buffer[Length], " %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
3248 else
3249 Length += sprintf(&Buffer[Length], " %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
3250 }
3251 Length += sprintf(&Buffer[Length], "\n\
3252Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
3253====== ======= ========= ========= ========= ========= =========\n");
3254 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3255 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
3256 if (!TargetFlags->TargetExists)
3257 continue;
3258 Length +=
3259 sprintf(&Buffer[Length],
3260 " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
3261 TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
3262 TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
3263 Length +=
3264 sprintf(&Buffer[Length],
3265 " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
3266 TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
3267 TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
3268 }
3269 Length += sprintf(&Buffer[Length], "\n\
3270Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
3271====== ======= ========= ========= ========= ========= =========\n");
3272 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3273 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
3274 if (!TargetFlags->TargetExists)
3275 continue;
3276 Length +=
3277 sprintf(&Buffer[Length],
3278 " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
3279 TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
3280 TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
3281 Length +=
3282 sprintf(&Buffer[Length],
3283 " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
3284 TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
3285 TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
3286 }
3287 Length += sprintf(&Buffer[Length], "\n\n\
3288 ERROR RECOVERY STATISTICS\n\
3289\n\
3290 Command Aborts Bus Device Resets Host Adapter Resets\n\
3291Target Requested Completed Requested Completed Requested Completed\n\
3292 ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
3293====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
3294 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
3295 struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
3296 if (!TargetFlags->TargetExists)
3297 continue;
3298 Length += sprintf(&Buffer[Length], "\
3299 %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
3300 }
3301 Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
3302 Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
3303 if (Length >= BusLogic_MessageBufferSize)
3304 BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
3305 if ((Length -= Offset) <= 0)
3306 return 0;
3307 if (Length >= BytesAvailable)
3308 Length = BytesAvailable;
3309 memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
3310 *StartPointer = ProcBuffer;
3311 return Length;
3312}
3313
3314
3315/*
3316 BusLogic_Message prints Driver Messages.
3317*/
3318
3319static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
3320{
3321 static char Buffer[BusLogic_LineBufferSize];
Richard Knutsson2065e312007-02-05 16:39:01 -08003322 static bool BeginningOfLine = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323 va_list Arguments;
3324 int Length = 0;
3325 va_start(Arguments, HostAdapter);
3326 Length = vsprintf(Buffer, Format, Arguments);
3327 va_end(Arguments);
3328 if (MessageLevel == BusLogic_AnnounceLevel) {
3329 static int AnnouncementLines = 0;
3330 strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
3331 HostAdapter->MessageBufferLength += Length;
3332 if (++AnnouncementLines <= 2)
3333 printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
3334 } else if (MessageLevel == BusLogic_InfoLevel) {
3335 strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
3336 HostAdapter->MessageBufferLength += Length;
3337 if (BeginningOfLine) {
3338 if (Buffer[0] != '\n' || Length > 1)
3339 printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
3340 } else
3341 printk("%s", Buffer);
3342 } else {
3343 if (BeginningOfLine) {
3344 if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
3345 printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
3346 else
3347 printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
3348 } else
3349 printk("%s", Buffer);
3350 }
3351 BeginningOfLine = (Buffer[Length - 1] == '\n');
3352}
3353
3354
3355/*
3356 BusLogic_ParseKeyword parses an individual option keyword. It returns true
3357 and updates the pointer if the keyword is recognized and false otherwise.
3358*/
3359
Richard Knutsson2065e312007-02-05 16:39:01 -08003360static bool __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361{
3362 char *Pointer = *StringPointer;
3363 while (*Keyword != '\0') {
3364 char StringChar = *Pointer++;
3365 char KeywordChar = *Keyword++;
3366 if (StringChar >= 'A' && StringChar <= 'Z')
3367 StringChar += 'a' - 'Z';
3368 if (KeywordChar >= 'A' && KeywordChar <= 'Z')
3369 KeywordChar += 'a' - 'Z';
3370 if (StringChar != KeywordChar)
3371 return false;
3372 }
3373 *StringPointer = Pointer;
3374 return true;
3375}
3376
3377
3378/*
3379 BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
3380 specifications.
3381
3382 BusLogic Driver Options may be specified either via the Linux Kernel Command
3383 Line or via the Loadable Kernel Module Installation Facility. Driver Options
3384 for multiple host adapters may be specified either by separating the option
3385 strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
3386 command line. Individual option specifications for a single host adapter are
3387 separated by commas. The Probing and Debugging Options apply to all host
3388 adapters whereas the remaining options apply individually only to the
3389 selected host adapter.
3390
3391 The BusLogic Driver Probing Options are described in
3392 <file:Documentation/scsi/BusLogic.txt>.
3393*/
3394
3395static int __init BusLogic_ParseDriverOptions(char *OptionsString)
3396{
3397 while (true) {
3398 struct BusLogic_DriverOptions *DriverOptions = &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
3399 int TargetID;
3400 memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
3401 while (*OptionsString != '\0' && *OptionsString != ';') {
3402 /* Probing Options. */
3403 if (BusLogic_ParseKeyword(&OptionsString, "IO:")) {
3404 unsigned long IO_Address = simple_strtoul(OptionsString, &OptionsString, 0);
3405 BusLogic_ProbeOptions.LimitedProbeISA = true;
3406 switch (IO_Address) {
3407 case 0x330:
3408 BusLogic_ProbeOptions.Probe330 = true;
3409 break;
3410 case 0x334:
3411 BusLogic_ProbeOptions.Probe334 = true;
3412 break;
3413 case 0x230:
3414 BusLogic_ProbeOptions.Probe230 = true;
3415 break;
3416 case 0x234:
3417 BusLogic_ProbeOptions.Probe234 = true;
3418 break;
3419 case 0x130:
3420 BusLogic_ProbeOptions.Probe130 = true;
3421 break;
3422 case 0x134:
3423 BusLogic_ProbeOptions.Probe134 = true;
3424 break;
3425 default:
3426 BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, IO_Address);
3427 return 0;
3428 }
3429 } else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
3430 BusLogic_ProbeOptions.NoProbeISA = true;
3431 else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
3432 BusLogic_ProbeOptions.NoProbePCI = true;
3433 else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
3434 BusLogic_ProbeOptions.NoProbe = true;
3435 else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
3436 BusLogic_ProbeOptions.NoSortPCI = true;
3437 else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
3438 BusLogic_ProbeOptions.MultiMasterFirst = true;
3439 else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
3440 BusLogic_ProbeOptions.FlashPointFirst = true;
3441 /* Tagged Queuing Options. */
3442 else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || BusLogic_ParseKeyword(&OptionsString, "QD:[")) {
3443 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
3444 unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
3445 if (QueueDepth > BusLogic_MaxTaggedQueueDepth) {
3446 BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
3447 return 0;
3448 }
3449 DriverOptions->QueueDepth[TargetID] = QueueDepth;
3450 if (*OptionsString == ',')
3451 OptionsString++;
3452 else if (*OptionsString == ']')
3453 break;
3454 else {
3455 BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString);
3456 return 0;
3457 }
3458 }
3459 if (*OptionsString != ']') {
3460 BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString);
3461 return 0;
3462 } else
3463 OptionsString++;
3464 } else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || BusLogic_ParseKeyword(&OptionsString, "QD:")) {
3465 unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
3466 if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) {
3467 BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
3468 return 0;
3469 }
3470 DriverOptions->CommonQueueDepth = QueueDepth;
3471 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
3472 DriverOptions->QueueDepth[TargetID] = QueueDepth;
3473 } else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || BusLogic_ParseKeyword(&OptionsString, "TQ:")) {
3474 if (BusLogic_ParseKeyword(&OptionsString, "Default")) {
3475 DriverOptions->TaggedQueuingPermitted = 0x0000;
3476 DriverOptions->TaggedQueuingPermittedMask = 0x0000;
3477 } else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) {
3478 DriverOptions->TaggedQueuingPermitted = 0xFFFF;
3479 DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
3480 } else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) {
3481 DriverOptions->TaggedQueuingPermitted = 0x0000;
3482 DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
3483 } else {
3484 unsigned short TargetBit;
3485 for (TargetID = 0, TargetBit = 1; TargetID < BusLogic_MaxTargetDevices; TargetID++, TargetBit <<= 1)
3486 switch (*OptionsString++) {
3487 case 'Y':
3488 DriverOptions->TaggedQueuingPermitted |= TargetBit;
3489 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
3490 break;
3491 case 'N':
3492 DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
3493 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
3494 break;
3495 case 'X':
3496 break;
3497 default:
3498 OptionsString--;
3499 TargetID = BusLogic_MaxTargetDevices;
3500 break;
3501 }
3502 }
3503 }
3504 /* Miscellaneous Options. */
3505 else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || BusLogic_ParseKeyword(&OptionsString, "BST:")) {
3506 unsigned short BusSettleTime = simple_strtoul(OptionsString, &OptionsString, 0);
3507 if (BusSettleTime > 5 * 60) {
3508 BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, BusSettleTime);
3509 return 0;
3510 }
3511 DriverOptions->BusSettleTime = BusSettleTime;
3512 } else if (BusLogic_ParseKeyword(&OptionsString, "InhibitTargetInquiry"))
3513 DriverOptions->LocalOptions.InhibitTargetInquiry = true;
3514 /* Debugging Options. */
3515 else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
3516 BusLogic_GlobalOptions.TraceProbe = true;
3517 else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
3518 BusLogic_GlobalOptions.TraceHardwareReset = true;
3519 else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
3520 BusLogic_GlobalOptions.TraceConfiguration = true;
3521 else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
3522 BusLogic_GlobalOptions.TraceErrors = true;
3523 else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) {
3524 BusLogic_GlobalOptions.TraceProbe = true;
3525 BusLogic_GlobalOptions.TraceHardwareReset = true;
3526 BusLogic_GlobalOptions.TraceConfiguration = true;
3527 BusLogic_GlobalOptions.TraceErrors = true;
3528 }
3529 if (*OptionsString == ',')
3530 OptionsString++;
3531 else if (*OptionsString != ';' && *OptionsString != '\0') {
3532 BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, OptionsString);
3533 *OptionsString = '\0';
3534 }
3535 }
3536 if (!(BusLogic_DriverOptionsCount == 0 || BusLogic_ProbeInfoCount == 0 || BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) {
3537 BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
3538 return 0;
3539 }
3540 /*
3541 Tagged Queuing is disabled when the Queue Depth is 1 since queuing
3542 multiple commands is not possible.
3543 */
3544 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
3545 if (DriverOptions->QueueDepth[TargetID] == 1) {
3546 unsigned short TargetBit = 1 << TargetID;
3547 DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
3548 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
3549 }
3550 if (*OptionsString == ';')
3551 OptionsString++;
3552 if (*OptionsString == '\0')
3553 return 0;
3554 }
3555 return 1;
3556}
3557
3558/*
3559 Get it all started
3560*/
3561
3562static struct scsi_host_template Bus_Logic_template = {
3563 .module = THIS_MODULE,
3564 .proc_name = "BusLogic",
3565 .proc_info = BusLogic_ProcDirectoryInfo,
3566 .name = "BusLogic",
3567 .info = BusLogic_DriverInfo,
3568 .queuecommand = BusLogic_QueueCommand,
3569 .slave_configure = BusLogic_SlaveConfigure,
3570 .bios_param = BusLogic_BIOSDiskParameters,
3571 .eh_host_reset_handler = BusLogic_host_reset,
3572#if 0
3573 .eh_abort_handler = BusLogic_AbortCommand,
3574#endif
3575 .unchecked_isa_dma = 1,
3576 .max_sectors = 128,
3577 .use_clustering = ENABLE_CLUSTERING,
3578};
3579
3580/*
3581 BusLogic_Setup handles processing of Kernel Command Line Arguments.
3582*/
3583
3584static int __init BusLogic_Setup(char *str)
3585{
3586 int ints[3];
3587
3588 (void) get_options(str, ARRAY_SIZE(ints), ints);
3589
3590 if (ints[0] != 0) {
3591 BusLogic_Error("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
3592 return 0;
3593 }
3594 if (str == NULL || *str == '\0')
3595 return 0;
3596 return BusLogic_ParseDriverOptions(str);
3597}
3598
3599/*
3600 * Exit function. Deletes all hosts associated with this driver.
3601 */
3602
3603static void __exit BusLogic_exit(void)
3604{
3605 struct BusLogic_HostAdapter *ha, *next;
3606
3607 list_for_each_entry_safe(ha, next, &BusLogic_host_list, host_list)
3608 BusLogic_ReleaseHostAdapter(ha);
3609}
3610
3611__setup("BusLogic=", BusLogic_Setup);
3612
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003613#ifdef MODULE
Ben Collins745b5712006-10-18 08:36:57 -04003614static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
3615 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
3616 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3617 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
3618 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3619 { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
3620 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
3621 { }
3622};
Zachary Amsden1079a2d2007-04-10 08:53:08 -05003623#endif
Ben Collins745b5712006-10-18 08:36:57 -04003624MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
3625
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626module_init(BusLogic_init);
3627module_exit(BusLogic_exit);