Import 2.3.18pre1
[davej-history.git] / drivers / scsi / BusLogic.c
blobaa19438912128a514dfaecea52dbb49e4e54be72
1 /*
3 Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
5 Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>
7 This program is free software; you may redistribute and/or modify it under
8 the terms of the GNU General Public License Version 2 as published by the
9 Free Software Foundation.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for complete details.
16 The author respectfully requests that any modifications to this software be
17 sent directly to him for evaluation and testing.
19 Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
20 advice has been invaluable, to David Gentzel, for writing the original Linux
21 BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
23 Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
24 Manager available as freely redistributable source code.
29 #define BusLogic_DriverVersion "2.1.15"
30 #define BusLogic_DriverDate "17 August 1998"
33 #include <linux/version.h>
34 #include <linux/module.h>
35 #include <linux/config.h>
36 #include <linux/init.h>
37 #include <linux/types.h>
38 #include <linux/blk.h>
39 #include <linux/blkdev.h>
40 #include <linux/delay.h>
41 #include <linux/ioport.h>
42 #include <linux/mm.h>
43 #include <linux/sched.h>
44 #include <linux/stat.h>
45 #include <linux/pci.h>
46 #include <linux/spinlock.h>
47 #include <asm/dma.h>
48 #include <asm/io.h>
49 #include <asm/system.h>
50 #include "scsi.h"
51 #include "hosts.h"
52 #include "sd.h"
53 #include "BusLogic.h"
54 #include "FlashPoint.c"
58 BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
59 Options specifications provided via the Linux Kernel Command Line or via
60 the Loadable Kernel Module Installation Facility.
63 static int
64 BusLogic_DriverOptionsCount = 0;
68 BusLogic_DriverOptions is an array of Driver Options structures representing
69 BusLogic Driver Options specifications provided via the Linux Kernel Command
70 Line or via the Loadable Kernel Module Installation Facility.
73 static BusLogic_DriverOptions_T
74 BusLogic_DriverOptions[BusLogic_MaxHostAdapters];
78 BusLogic_Options can be assigned a string by the Loadable Kernel Module
79 Installation Facility to be parsed for BusLogic Driver Options
80 specifications.
83 static char
84 *BusLogic_Options = NULL;
88 BusLogic_ProbeOptions is a set of Probe Options to be applied across
89 all BusLogic Host Adapters.
92 static BusLogic_ProbeOptions_T
93 BusLogic_ProbeOptions = { 0 };
97 BusLogic_GlobalOptions is a set of Global Options to be applied across
98 all BusLogic Host Adapters.
101 static BusLogic_GlobalOptions_T
102 BusLogic_GlobalOptions = { 0 };
106 BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter
107 are pointers to the first and last registered BusLogic Host Adapters.
110 static BusLogic_HostAdapter_T
111 *BusLogic_FirstRegisteredHostAdapter = NULL,
112 *BusLogic_LastRegisteredHostAdapter = NULL;
116 BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
119 static int
120 BusLogic_ProbeInfoCount = 0;
124 BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information
125 to be checked for potential BusLogic Host Adapters. It is initialized by
126 interrogating the PCI Configuration Space on PCI machines as well as from the
127 list of standard BusLogic I/O Addresses.
130 static BusLogic_ProbeInfo_T
131 *BusLogic_ProbeInfoList = NULL;
135 BusLogic_CommandFailureReason holds a string identifying the reason why a
136 call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command
137 returns a failure code.
140 static char
141 *BusLogic_CommandFailureReason;
145 BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
148 PROC_DirectoryEntry_T
149 BusLogic_ProcDirectoryEntry =
150 { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
154 BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
155 Name, Copyright Notice, and Electronic Mail Address.
158 static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter)
160 BusLogic_Announce("***** BusLogic SCSI Driver Version "
161 BusLogic_DriverVersion " of "
162 BusLogic_DriverDate " *****\n", HostAdapter);
163 BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
164 "<lnz@dandelion.com>\n", HostAdapter);
169 BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI
170 Driver and Host Adapter.
173 const char *BusLogic_DriverInfo(SCSI_Host_T *Host)
175 BusLogic_HostAdapter_T *HostAdapter =
176 (BusLogic_HostAdapter_T *) Host->hostdata;
177 return HostAdapter->FullModelName;
182 BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
183 BusLogic Host Adapters.
186 static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
188 HostAdapter->Next = NULL;
189 if (BusLogic_FirstRegisteredHostAdapter == NULL)
191 BusLogic_FirstRegisteredHostAdapter = HostAdapter;
192 BusLogic_LastRegisteredHostAdapter = HostAdapter;
194 else
196 BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
197 BusLogic_LastRegisteredHostAdapter = HostAdapter;
203 BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
204 registered BusLogic Host Adapters.
207 static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
209 if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
211 BusLogic_FirstRegisteredHostAdapter =
212 BusLogic_FirstRegisteredHostAdapter->Next;
213 if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
214 BusLogic_LastRegisteredHostAdapter = NULL;
216 else
218 BusLogic_HostAdapter_T *PreviousHostAdapter =
219 BusLogic_FirstRegisteredHostAdapter;
220 while (PreviousHostAdapter != NULL &&
221 PreviousHostAdapter->Next != HostAdapter)
222 PreviousHostAdapter = PreviousHostAdapter->Next;
223 if (PreviousHostAdapter != NULL)
224 PreviousHostAdapter->Next = HostAdapter->Next;
226 HostAdapter->Next = NULL;
231 BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
232 for Host Adapter from the BlockSize bytes located at BlockPointer. The newly
233 created CCBs are added to Host Adapter's free list.
236 static void BusLogic_InitializeCCBs(BusLogic_HostAdapter_T *HostAdapter,
237 void *BlockPointer, int BlockSize)
239 BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) BlockPointer;
240 memset(BlockPointer, 0, BlockSize);
241 CCB->AllocationGroupHead = true;
242 while ((BlockSize -= sizeof(BusLogic_CCB_T)) >= 0)
244 CCB->Status = BusLogic_CCB_Free;
245 CCB->HostAdapter = HostAdapter;
246 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
248 CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
249 CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
251 CCB->Next = HostAdapter->Free_CCBs;
252 CCB->NextAll = HostAdapter->All_CCBs;
253 HostAdapter->Free_CCBs = CCB;
254 HostAdapter->All_CCBs = CCB;
255 HostAdapter->AllocatedCCBs++;
256 CCB++;
262 BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
265 static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter)
267 int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
268 while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs)
270 void *BlockPointer = kmalloc(BlockSize,
271 (HostAdapter->BounceBuffersRequired
272 ? GFP_ATOMIC | GFP_DMA
273 : GFP_ATOMIC));
274 if (BlockPointer == NULL)
276 BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
277 HostAdapter);
278 return false;
280 BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
282 return true;
287 BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
290 static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter)
292 BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB;
293 HostAdapter->All_CCBs = NULL;
294 HostAdapter->Free_CCBs = NULL;
295 while ((CCB = NextCCB) != NULL)
297 NextCCB = CCB->NextAll;
298 if (CCB->AllocationGroupHead)
299 kfree(CCB);
305 BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If
306 allocation fails and there are no remaining CCBs available, the Driver Queue
307 Depth is decreased to a known safe value to avoid potential deadlocks when
308 multiple host adapters share the same IRQ Channel.
311 static void BusLogic_CreateAdditionalCCBs(BusLogic_HostAdapter_T *HostAdapter,
312 int AdditionalCCBs,
313 boolean SuccessMessageP)
315 int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
316 int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
317 if (AdditionalCCBs <= 0) return;
318 while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs)
320 void *BlockPointer = kmalloc(BlockSize,
321 (HostAdapter->BounceBuffersRequired
322 ? GFP_ATOMIC | GFP_DMA
323 : GFP_ATOMIC));
324 if (BlockPointer == NULL) break;
325 BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
327 if (HostAdapter->AllocatedCCBs > PreviouslyAllocated)
329 if (SuccessMessageP)
330 BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n",
331 HostAdapter,
332 HostAdapter->AllocatedCCBs - PreviouslyAllocated,
333 HostAdapter->AllocatedCCBs);
334 return;
336 BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
337 if (HostAdapter->DriverQueueDepth >
338 HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount)
340 HostAdapter->DriverQueueDepth =
341 HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
342 HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
348 BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,
349 allocating more memory from the Kernel if necessary. The Host Adapter's
350 Lock should already have been acquired by the caller.
353 static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T
354 *HostAdapter)
356 static unsigned long SerialNumber = 0;
357 BusLogic_CCB_T *CCB;
358 CCB = HostAdapter->Free_CCBs;
359 if (CCB != NULL)
361 CCB->SerialNumber = ++SerialNumber;
362 HostAdapter->Free_CCBs = CCB->Next;
363 CCB->Next = NULL;
364 if (HostAdapter->Free_CCBs == NULL)
365 BusLogic_CreateAdditionalCCBs(HostAdapter,
366 HostAdapter->IncrementalCCBs,
367 true);
368 return CCB;
370 BusLogic_CreateAdditionalCCBs(HostAdapter,
371 HostAdapter->IncrementalCCBs,
372 true);
373 CCB = HostAdapter->Free_CCBs;
374 if (CCB == NULL) return NULL;
375 CCB->SerialNumber = ++SerialNumber;
376 HostAdapter->Free_CCBs = CCB->Next;
377 CCB->Next = NULL;
378 return CCB;
383 BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
384 free list. The Host Adapter's Lock should already have been acquired by the
385 caller.
388 static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB)
390 BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
391 CCB->Command = NULL;
392 CCB->Status = BusLogic_CCB_Free;
393 CCB->Next = HostAdapter->Free_CCBs;
394 HostAdapter->Free_CCBs = CCB;
399 BusLogic_Command sends the command OperationCode to HostAdapter, optionally
400 providing ParameterLength bytes of ParameterData and receiving at most
401 ReplyLength bytes of ReplyData; any excess reply data is received but
402 discarded.
404 On success, this function returns the number of reply bytes read from
405 the Host Adapter (including any discarded data); on failure, it returns
406 -1 if the command was invalid, or -2 if a timeout occurred.
408 BusLogic_Command is called exclusively during host adapter detection and
409 initialization, so performance and latency are not critical, and exclusive
410 access to the Host Adapter hardware is assumed. Once the host adapter and
411 driver are initialized, the only Host Adapter command that is issued is the
412 single byte Execute Mailbox Command operation code, which does not require
413 waiting for the Host Adapter Ready bit to be set in the Status Register.
416 static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
417 BusLogic_OperationCode_T OperationCode,
418 void *ParameterData,
419 int ParameterLength,
420 void *ReplyData,
421 int ReplyLength)
423 unsigned char *ParameterPointer = (unsigned char *) ParameterData;
424 unsigned char *ReplyPointer = (unsigned char *) ReplyData;
425 BusLogic_StatusRegister_T StatusRegister;
426 BusLogic_InterruptRegister_T InterruptRegister;
427 ProcessorFlags_T ProcessorFlags = 0;
428 int ReplyBytes = 0, Result;
429 long TimeoutCounter;
431 Clear out the Reply Data if provided.
433 if (ReplyLength > 0)
434 memset(ReplyData, 0, ReplyLength);
436 If the IRQ Channel has not yet been acquired, then interrupts must be
437 disabled while issuing host adapter commands since a Command Complete
438 interrupt could occur if the IRQ Channel was previously enabled by another
439 BusLogic Host Adapter or another driver sharing the same IRQ Channel.
441 if (!HostAdapter->IRQ_ChannelAcquired)
443 save_flags(ProcessorFlags);
444 cli();
447 Wait for the Host Adapter Ready bit to be set and the Command/Parameter
448 Register Busy bit to be reset in the Status Register.
450 TimeoutCounter = 10000;
451 while (--TimeoutCounter >= 0)
453 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
454 if (StatusRegister.Bits.HostAdapterReady &&
455 !StatusRegister.Bits.CommandParameterRegisterBusy)
456 break;
457 udelay(100);
459 if (TimeoutCounter < 0)
461 BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
462 Result = -2;
463 goto Done;
466 Write the OperationCode to the Command/Parameter Register.
468 HostAdapter->HostAdapterCommandCompleted = false;
469 BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
471 Write any additional Parameter Bytes.
473 TimeoutCounter = 10000;
474 while (ParameterLength > 0 && --TimeoutCounter >= 0)
477 Wait 100 microseconds to give the Host Adapter enough time to determine
478 whether the last value written to the Command/Parameter Register was
479 valid or not. If the Command Complete bit is set in the Interrupt
480 Register, then the Command Invalid bit in the Status Register will be
481 reset if the Operation Code or Parameter was valid and the command
482 has completed, or set if the Operation Code or Parameter was invalid.
483 If the Data In Register Ready bit is set in the Status Register, then
484 the Operation Code was valid, and data is waiting to be read back
485 from the Host Adapter. Otherwise, wait for the Command/Parameter
486 Register Busy bit in the Status Register to be reset.
488 udelay(100);
489 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
490 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
491 if (InterruptRegister.Bits.CommandComplete) break;
492 if (HostAdapter->HostAdapterCommandCompleted) break;
493 if (StatusRegister.Bits.DataInRegisterReady) break;
494 if (StatusRegister.Bits.CommandParameterRegisterBusy) continue;
495 BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
496 ParameterLength--;
498 if (TimeoutCounter < 0)
500 BusLogic_CommandFailureReason =
501 "Timeout waiting for Parameter Acceptance";
502 Result = -2;
503 goto Done;
506 The Modify I/O Address command does not cause a Command Complete Interrupt.
508 if (OperationCode == BusLogic_ModifyIOAddress)
510 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
511 if (StatusRegister.Bits.CommandInvalid)
513 BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
514 Result = -1;
515 goto Done;
517 if (BusLogic_GlobalOptions.TraceConfiguration)
518 BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
519 "(Modify I/O Address)\n", HostAdapter,
520 OperationCode, StatusRegister.All);
521 Result = 0;
522 goto Done;
525 Select an appropriate timeout value for awaiting command completion.
527 switch (OperationCode)
529 case BusLogic_InquireInstalledDevicesID0to7:
530 case BusLogic_InquireInstalledDevicesID8to15:
531 case BusLogic_InquireTargetDevices:
532 /* Approximately 60 seconds. */
533 TimeoutCounter = 60*10000;
534 break;
535 default:
536 /* Approximately 1 second. */
537 TimeoutCounter = 10000;
538 break;
541 Receive any Reply Bytes, waiting for either the Command Complete bit to
542 be set in the Interrupt Register, or for the Interrupt Handler to set the
543 Host Adapter Command Completed bit in the Host Adapter structure.
545 while (--TimeoutCounter >= 0)
547 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
548 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
549 if (InterruptRegister.Bits.CommandComplete) break;
550 if (HostAdapter->HostAdapterCommandCompleted) break;
551 if (StatusRegister.Bits.DataInRegisterReady)
553 if (++ReplyBytes <= ReplyLength)
554 *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
555 else BusLogic_ReadDataInRegister(HostAdapter);
557 if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
558 StatusRegister.Bits.HostAdapterReady) break;
559 udelay(100);
561 if (TimeoutCounter < 0)
563 BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
564 Result = -2;
565 goto Done;
568 Clear any pending Command Complete Interrupt.
570 BusLogic_InterruptReset(HostAdapter);
572 Provide tracing information if requested.
574 if (BusLogic_GlobalOptions.TraceConfiguration)
576 int i;
577 BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
578 HostAdapter, OperationCode,
579 StatusRegister.All, ReplyLength, ReplyBytes);
580 if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes;
581 for (i = 0; i < ReplyLength; i++)
582 BusLogic_Notice(" %02X", HostAdapter,
583 ((unsigned char *) ReplyData)[i]);
584 BusLogic_Notice("\n", HostAdapter);
587 Process Command Invalid conditions.
589 if (StatusRegister.Bits.CommandInvalid)
592 Some early BusLogic Host Adapters may not recover properly from
593 a Command Invalid condition, so if this appears to be the case,
594 a Soft Reset is issued to the Host Adapter. Potentially invalid
595 commands are never attempted after Mailbox Initialization is
596 performed, so there should be no Host Adapter state lost by a
597 Soft Reset in response to a Command Invalid condition.
599 udelay(1000);
600 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
601 if (StatusRegister.Bits.CommandInvalid ||
602 StatusRegister.Bits.Reserved ||
603 StatusRegister.Bits.DataInRegisterReady ||
604 StatusRegister.Bits.CommandParameterRegisterBusy ||
605 !StatusRegister.Bits.HostAdapterReady ||
606 !StatusRegister.Bits.InitializationRequired ||
607 StatusRegister.Bits.DiagnosticActive ||
608 StatusRegister.Bits.DiagnosticFailure)
610 BusLogic_SoftReset(HostAdapter);
611 udelay(1000);
613 BusLogic_CommandFailureReason = "Command Invalid";
614 Result = -1;
615 goto Done;
618 Handle Excess Parameters Supplied conditions.
620 if (ParameterLength > 0)
622 BusLogic_CommandFailureReason = "Excess Parameters Supplied";
623 Result = -1;
624 goto Done;
627 Indicate the command completed successfully.
629 BusLogic_CommandFailureReason = NULL;
630 Result = ReplyBytes;
632 Restore the interrupt status if necessary and return.
634 Done:
635 if (!HostAdapter->IRQ_ChannelAcquired)
636 restore_flags(ProcessorFlags);
637 return Result;
642 BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list
643 of I/O Address and Bus Probe Information to be checked for potential BusLogic
644 Host Adapters.
647 static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address)
649 BusLogic_ProbeInfo_T *ProbeInfo;
650 if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return;
651 ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
652 ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
653 ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
654 ProbeInfo->IO_Address = IO_Address;
659 BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and
660 Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
661 only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
664 static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T
665 *PrototypeHostAdapter)
668 If BusLogic Driver Options specifications requested that ISA Bus Probes
669 be inhibited, do not proceed further.
671 if (BusLogic_ProbeOptions.NoProbeISA) return;
673 Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
675 if (BusLogic_ProbeOptions.LimitedProbeISA
676 ? BusLogic_ProbeOptions.Probe330
677 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
678 BusLogic_AppendProbeAddressISA(0x330);
679 if (BusLogic_ProbeOptions.LimitedProbeISA
680 ? BusLogic_ProbeOptions.Probe334
681 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
682 BusLogic_AppendProbeAddressISA(0x334);
683 if (BusLogic_ProbeOptions.LimitedProbeISA
684 ? BusLogic_ProbeOptions.Probe230
685 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
686 BusLogic_AppendProbeAddressISA(0x230);
687 if (BusLogic_ProbeOptions.LimitedProbeISA
688 ? BusLogic_ProbeOptions.Probe234
689 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
690 BusLogic_AppendProbeAddressISA(0x234);
691 if (BusLogic_ProbeOptions.LimitedProbeISA
692 ? BusLogic_ProbeOptions.Probe130
693 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
694 BusLogic_AppendProbeAddressISA(0x130);
695 if (BusLogic_ProbeOptions.LimitedProbeISA
696 ? BusLogic_ProbeOptions.Probe134
697 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
698 BusLogic_AppendProbeAddressISA(0x134);
702 #ifdef CONFIG_PCI
706 BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order
707 of increasing PCI Bus and Device Number.
710 static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList,
711 int ProbeInfoCount)
713 int LastInterchange = ProbeInfoCount-1, Bound, j;
714 while (LastInterchange > 0)
716 Bound = LastInterchange;
717 LastInterchange = 0;
718 for (j = 0; j < Bound; j++)
720 BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j];
721 BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1];
722 if (ProbeInfo1->Bus > ProbeInfo2->Bus ||
723 (ProbeInfo1->Bus == ProbeInfo2->Bus &&
724 (ProbeInfo1->Device > ProbeInfo2->Device)))
726 BusLogic_ProbeInfo_T TempProbeInfo;
727 memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T));
728 memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T));
729 memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T));
730 LastInterchange = j;
738 BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address
739 and Bus Probe Information to be checked for potential BusLogic MultiMaster
740 SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
741 machines as well as from the list of standard BusLogic MultiMaster ISA
742 I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
745 static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T
746 *PrototypeHostAdapter)
748 BusLogic_ProbeInfo_T *PrimaryProbeInfo =
749 &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
750 int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
751 int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
752 boolean ForceBusDeviceScanningOrder = false;
753 boolean ForceBusDeviceScanningOrderChecked = false;
754 boolean StandardAddressSeen[6];
755 PCI_Device_T *PCI_Device = NULL;
756 int i;
757 if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0;
758 BusLogic_ProbeInfoCount++;
759 for (i = 0; i < 6; i++)
760 StandardAddressSeen[i] = false;
762 Iterate over the MultiMaster PCI Host Adapters. For each enumerated host
763 adapter, determine whether its ISA Compatible I/O Port is enabled and if
764 so, whether it is assigned the Primary I/O Address. A host adapter that is
765 assigned the Primary I/O Address will always be the preferred boot device.
766 The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
767 Address, then any other PCI host adapters, and finally any host adapters
768 located at the remaining standard ISA I/O Addresses. When a PCI host
769 adapter is found with its ISA Compatible I/O Port enabled, a command is
770 issued to disable the ISA Compatible I/O Port, and it is noted that the
771 particular standard ISA I/O Address need not be probed.
773 PrimaryProbeInfo->IO_Address = 0;
774 while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
775 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
776 PCI_Device)) != NULL)
778 BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
779 BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
780 BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest;
781 unsigned char Bus = PCI_Device->bus->number;
782 unsigned char Device = PCI_Device->devfn >> 3;
783 unsigned int IRQ_Channel = PCI_Device->irq;
784 unsigned long BaseAddress0 = PCI_Device->resource[0].start;
785 unsigned long BaseAddress1 = PCI_Device->resource[1].start;
786 BusLogic_IO_Address_T IO_Address = BaseAddress0;
787 BusLogic_PCI_Address_T PCI_Address = BaseAddress1;
789 if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO))
791 BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
792 "MultiMaster Host Adapter\n", NULL, BaseAddress0);
793 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
794 NULL, Bus, Device, IO_Address);
795 continue;
797 if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO)
799 BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
800 "MultiMaster Host Adapter\n", NULL, BaseAddress1);
801 BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
802 NULL, Bus, Device, PCI_Address);
803 continue;
805 if (IRQ_Channel == 0)
807 BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
808 "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
809 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
810 NULL, Bus, Device, IO_Address);
811 continue;
813 if (BusLogic_GlobalOptions.TraceProbe)
815 BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter "
816 "detected at\n", NULL);
817 BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
818 "0x%X PCI Address 0x%X\n", NULL,
819 Bus, Device, IO_Address, PCI_Address);
822 Issue the Inquire PCI Host Adapter Information command to determine
823 the ISA Compatible I/O Port. If the ISA Compatible I/O Port is
824 known and enabled, note that the particular Standard ISA I/O
825 Address should not be probed.
827 HostAdapter->IO_Address = IO_Address;
828 BusLogic_InterruptReset(HostAdapter);
829 if (BusLogic_Command(HostAdapter,
830 BusLogic_InquirePCIHostAdapterInformation,
831 NULL, 0, &PCIHostAdapterInformation,
832 sizeof(PCIHostAdapterInformation))
833 == sizeof(PCIHostAdapterInformation))
835 if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
836 StandardAddressSeen[PCIHostAdapterInformation
837 .ISACompatibleIOPort] = true;
839 else PCIHostAdapterInformation.ISACompatibleIOPort =
840 BusLogic_IO_Disable;
842 Issue the Modify I/O Address command to disable the ISA Compatible
843 I/O Port.
845 ModifyIOAddressRequest = BusLogic_IO_Disable;
846 BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
847 &ModifyIOAddressRequest,
848 sizeof(ModifyIOAddressRequest), NULL, 0);
850 For the first MultiMaster Host Adapter enumerated, issue the Fetch
851 Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
852 for the setting of the "Use Bus And Device # For PCI Scanning Seq."
853 option. Issue the Inquire Board ID command since this option is
854 only valid for the BT-948/958/958D.
856 if (!ForceBusDeviceScanningOrderChecked)
858 BusLogic_FetchHostAdapterLocalRAMRequest_T
859 FetchHostAdapterLocalRAMRequest;
860 BusLogic_AutoSCSIByte45_T AutoSCSIByte45;
861 BusLogic_BoardID_T BoardID;
862 FetchHostAdapterLocalRAMRequest.ByteOffset =
863 BusLogic_AutoSCSI_BaseOffset + 45;
864 FetchHostAdapterLocalRAMRequest.ByteCount =
865 sizeof(AutoSCSIByte45);
866 BusLogic_Command(HostAdapter,
867 BusLogic_FetchHostAdapterLocalRAM,
868 &FetchHostAdapterLocalRAMRequest,
869 sizeof(FetchHostAdapterLocalRAMRequest),
870 &AutoSCSIByte45, sizeof(AutoSCSIByte45));
871 BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
872 NULL, 0, &BoardID, sizeof(BoardID));
873 if (BoardID.FirmwareVersion1stDigit == '5')
874 ForceBusDeviceScanningOrder =
875 AutoSCSIByte45.ForceBusDeviceScanningOrder;
876 ForceBusDeviceScanningOrderChecked = true;
879 Determine whether this MultiMaster Host Adapter has its ISA
880 Compatible I/O Port enabled and is assigned the Primary I/O Address.
881 If it does, then it is the Primary MultiMaster Host Adapter and must
882 be recognized first. If it does not, then it is added to the list
883 for probing after any Primary MultiMaster Host Adapter is probed.
885 if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330)
887 PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
888 PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
889 PrimaryProbeInfo->IO_Address = IO_Address;
890 PrimaryProbeInfo->PCI_Address = PCI_Address;
891 PrimaryProbeInfo->Bus = Bus;
892 PrimaryProbeInfo->Device = Device;
893 PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
894 PCIMultiMasterCount++;
896 else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
898 BusLogic_ProbeInfo_T *ProbeInfo =
899 &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
900 ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
901 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
902 ProbeInfo->IO_Address = IO_Address;
903 ProbeInfo->PCI_Address = PCI_Address;
904 ProbeInfo->Bus = Bus;
905 ProbeInfo->Device = Device;
906 ProbeInfo->IRQ_Channel = IRQ_Channel;
907 NonPrimaryPCIMultiMasterCount++;
908 PCIMultiMasterCount++;
910 else BusLogic_Warning("BusLogic: Too many Host Adapters "
911 "detected\n", NULL);
914 If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
915 for the first enumerated MultiMaster Host Adapter, and if that host adapter
916 is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
917 Host Adapters in the order of increasing PCI Bus and Device Number. In
918 that case, sort the probe information into the same order the BIOS uses.
919 If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
920 Host Adapters in the order they are enumerated by the PCI BIOS, and hence
921 no sorting is necessary.
923 if (ForceBusDeviceScanningOrder)
924 BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[
925 NonPrimaryPCIMultiMasterIndex],
926 NonPrimaryPCIMultiMasterCount);
928 If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
929 then the Primary I/O Address must be probed explicitly before any PCI
930 host adapters are probed.
932 if (!BusLogic_ProbeOptions.NoProbeISA)
933 if (PrimaryProbeInfo->IO_Address == 0 &&
934 (BusLogic_ProbeOptions.LimitedProbeISA
935 ? BusLogic_ProbeOptions.Probe330
936 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0))
938 PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
939 PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
940 PrimaryProbeInfo->IO_Address = 0x330;
943 Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
944 omitting the Primary I/O Address which has already been handled.
946 if (!BusLogic_ProbeOptions.NoProbeISA)
948 if (!StandardAddressSeen[1] &&
949 (BusLogic_ProbeOptions.LimitedProbeISA
950 ? BusLogic_ProbeOptions.Probe334
951 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
952 BusLogic_AppendProbeAddressISA(0x334);
953 if (!StandardAddressSeen[2] &&
954 (BusLogic_ProbeOptions.LimitedProbeISA
955 ? BusLogic_ProbeOptions.Probe230
956 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
957 BusLogic_AppendProbeAddressISA(0x230);
958 if (!StandardAddressSeen[3] &&
959 (BusLogic_ProbeOptions.LimitedProbeISA
960 ? BusLogic_ProbeOptions.Probe234
961 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
962 BusLogic_AppendProbeAddressISA(0x234);
963 if (!StandardAddressSeen[4] &&
964 (BusLogic_ProbeOptions.LimitedProbeISA
965 ? BusLogic_ProbeOptions.Probe130
966 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
967 BusLogic_AppendProbeAddressISA(0x130);
968 if (!StandardAddressSeen[5] &&
969 (BusLogic_ProbeOptions.LimitedProbeISA
970 ? BusLogic_ProbeOptions.Probe134
971 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
972 BusLogic_AppendProbeAddressISA(0x134);
975 Iterate over the older non-compliant MultiMaster PCI Host Adapters,
976 noting the PCI bus location and assigned IRQ Channel.
978 PCI_Device = NULL;
979 while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
980 PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
981 PCI_Device)) != NULL)
983 unsigned char Bus = PCI_Device->bus->number;
984 unsigned char Device = PCI_Device->devfn >> 3;
985 unsigned int IRQ_Channel = PCI_Device->irq;
986 BusLogic_IO_Address_T IO_Address = PCI_Device->resource[0].start;
988 if (IO_Address == 0 || IRQ_Channel == 0) continue;
989 for (i = 0; i < BusLogic_ProbeInfoCount; i++)
991 BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[i];
992 if (ProbeInfo->IO_Address == IO_Address &&
993 ProbeInfo->HostAdapterType == BusLogic_MultiMaster)
995 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
996 ProbeInfo->PCI_Address = 0;
997 ProbeInfo->Bus = Bus;
998 ProbeInfo->Device = Device;
999 ProbeInfo->IRQ_Channel = IRQ_Channel;
1000 break;
1004 return PCIMultiMasterCount;
1009 BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address
1010 and Bus Probe Information to be checked for potential BusLogic FlashPoint
1011 Host Adapters by interrogating the PCI Configuration Space. It returns the
1012 number of FlashPoint Host Adapters found.
1015 static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T
1016 *PrototypeHostAdapter)
1018 int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
1019 PCI_Device_T *PCI_Device = NULL;
1021 Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
1023 while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
1024 PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
1025 PCI_Device)) != NULL)
1027 unsigned char Bus = PCI_Device->bus->number;
1028 unsigned char Device = PCI_Device->devfn >> 3;
1029 unsigned int IRQ_Channel = PCI_Device->irq;
1030 unsigned long BaseAddress0 = PCI_Device->resource[0].start;
1031 unsigned long BaseAddress1 = PCI_Device->resource[1].start;
1032 BusLogic_IO_Address_T IO_Address = BaseAddress0;
1033 BusLogic_PCI_Address_T PCI_Address = BaseAddress1;
1034 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
1035 if (!(PCI_Device->resource[0].flags & PCI_BASE_ADDRESS_SPACE_IO))
1037 BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
1038 "FlashPoint Host Adapter\n", NULL, BaseAddress0);
1039 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
1040 NULL, Bus, Device, IO_Address);
1041 continue;
1043 if (PCI_Device->resource[1].flags & PCI_BASE_ADDRESS_SPACE_IO)
1045 BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
1046 "FlashPoint Host Adapter\n", NULL, BaseAddress1);
1047 BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
1048 NULL, Bus, Device, PCI_Address);
1049 continue;
1051 if (IRQ_Channel == 0)
1053 BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
1054 "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
1055 BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
1056 NULL, Bus, Device, IO_Address);
1057 continue;
1059 if (BusLogic_GlobalOptions.TraceProbe)
1061 BusLogic_Notice("BusLogic: FlashPoint Host Adapter "
1062 "detected at\n", NULL);
1063 BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
1064 "0x%X PCI Address 0x%X\n", NULL,
1065 Bus, Device, IO_Address, PCI_Address);
1067 if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
1069 BusLogic_ProbeInfo_T *ProbeInfo =
1070 &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
1071 ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
1072 ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
1073 ProbeInfo->IO_Address = IO_Address;
1074 ProbeInfo->PCI_Address = PCI_Address;
1075 ProbeInfo->Bus = Bus;
1076 ProbeInfo->Device = Device;
1077 ProbeInfo->IRQ_Channel = IRQ_Channel;
1078 FlashPointCount++;
1080 else BusLogic_Warning("BusLogic: Too many Host Adapters "
1081 "detected\n", NULL);
1082 #else
1083 BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
1084 "PCI Bus %d Device %d\n", NULL, Bus, Device);
1085 BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
1086 "but FlashPoint\n", NULL, IO_Address, PCI_Address);
1087 BusLogic_Error("BusLogic: support was omitted in this kernel "
1088 "configuration.\n", NULL);
1089 #endif
1092 The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
1093 increasing PCI Bus and Device Number, so sort the probe information into
1094 the same order the BIOS uses.
1096 BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex],
1097 FlashPointCount);
1098 return FlashPointCount;
1103 BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus
1104 Probe Information to be checked for potential BusLogic SCSI Host Adapters by
1105 interrogating the PCI Configuration Space on PCI machines as well as from the
1106 list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
1107 FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
1108 probe for FlashPoint Host Adapters first unless the BIOS primary disk is
1109 controlled by the first PCI MultiMaster Host Adapter, in which case
1110 MultiMaster Host Adapters will be probed first. The BusLogic Driver Options
1111 specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
1112 a particular probe order.
1115 static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T
1116 *PrototypeHostAdapter)
1119 If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
1120 Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
1122 if (!BusLogic_ProbeOptions.NoProbePCI && pci_present())
1124 if (BusLogic_ProbeOptions.MultiMasterFirst)
1126 BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1127 BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1129 else if (BusLogic_ProbeOptions.FlashPointFirst)
1131 BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1132 BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1134 else
1136 int FlashPointCount =
1137 BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1138 int PCIMultiMasterCount =
1139 BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1140 if (FlashPointCount > 0 && PCIMultiMasterCount > 0)
1142 BusLogic_ProbeInfo_T *ProbeInfo =
1143 &BusLogic_ProbeInfoList[FlashPointCount];
1144 BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
1145 BusLogic_FetchHostAdapterLocalRAMRequest_T
1146 FetchHostAdapterLocalRAMRequest;
1147 BusLogic_BIOSDriveMapByte_T Drive0MapByte;
1148 while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
1149 ProbeInfo++;
1150 HostAdapter->IO_Address = ProbeInfo->IO_Address;
1151 FetchHostAdapterLocalRAMRequest.ByteOffset =
1152 BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
1153 FetchHostAdapterLocalRAMRequest.ByteCount =
1154 sizeof(Drive0MapByte);
1155 BusLogic_Command(HostAdapter,
1156 BusLogic_FetchHostAdapterLocalRAM,
1157 &FetchHostAdapterLocalRAMRequest,
1158 sizeof(FetchHostAdapterLocalRAMRequest),
1159 &Drive0MapByte, sizeof(Drive0MapByte));
1161 If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
1162 is controlled by this PCI MultiMaster Host Adapter, then
1163 reverse the probe order so that MultiMaster Host Adapters are
1164 probed before FlashPoint Host Adapters.
1166 if (Drive0MapByte.DiskGeometry !=
1167 BusLogic_BIOS_Disk_Not_Installed)
1169 BusLogic_ProbeInfo_T
1170 SavedProbeInfo[BusLogic_MaxHostAdapters];
1171 int MultiMasterCount =
1172 BusLogic_ProbeInfoCount - FlashPointCount;
1173 memcpy(SavedProbeInfo,
1174 BusLogic_ProbeInfoList,
1175 BusLogic_ProbeInfoCount
1176 * sizeof(BusLogic_ProbeInfo_T));
1177 memcpy(&BusLogic_ProbeInfoList[0],
1178 &SavedProbeInfo[FlashPointCount],
1179 MultiMasterCount * sizeof(BusLogic_ProbeInfo_T));
1180 memcpy(&BusLogic_ProbeInfoList[MultiMasterCount],
1181 &SavedProbeInfo[0],
1182 FlashPointCount * sizeof(BusLogic_ProbeInfo_T));
1187 else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
1191 #endif /* CONFIG_PCI */
1195 BusLogic_Failure prints a standardized error message, and then returns false.
1198 static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter,
1199 char *ErrorMessage)
1201 BusLogic_AnnounceDriver(HostAdapter);
1202 if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus)
1204 BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n",
1205 HostAdapter);
1206 BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n",
1207 HostAdapter, HostAdapter->Bus, HostAdapter->Device,
1208 HostAdapter->IO_Address, HostAdapter->PCI_Address);
1210 else BusLogic_Error("While configuring BusLogic Host Adapter at "
1211 "I/O Address 0x%X:\n", HostAdapter,
1212 HostAdapter->IO_Address);
1213 BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
1214 if (BusLogic_CommandFailureReason != NULL)
1215 BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter,
1216 BusLogic_CommandFailureReason);
1217 return false;
1222 BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
1225 static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
1227 BusLogic_StatusRegister_T StatusRegister;
1228 BusLogic_InterruptRegister_T InterruptRegister;
1229 BusLogic_GeometryRegister_T GeometryRegister;
1231 FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
1233 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1235 FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1236 FlashPointInfo->BaseAddress =
1237 (BusLogic_Base_Address_T) HostAdapter->IO_Address;
1238 FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
1239 FlashPointInfo->Present = false;
1240 if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 &&
1241 FlashPointInfo->Present))
1243 BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
1244 "PCI Bus %d Device %d\n", HostAdapter,
1245 HostAdapter->Bus, HostAdapter->Device);
1246 BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
1247 "but FlashPoint\n", HostAdapter,
1248 HostAdapter->IO_Address, HostAdapter->PCI_Address);
1249 BusLogic_Error("BusLogic: Probe Function failed to validate it.\n",
1250 HostAdapter);
1251 return false;
1253 if (BusLogic_GlobalOptions.TraceProbe)
1254 BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n",
1255 HostAdapter, HostAdapter->IO_Address);
1257 Indicate the Host Adapter Probe completed successfully.
1259 return true;
1262 Read the Status, Interrupt, and Geometry Registers to test if there are I/O
1263 ports that respond, and to check the values to determine if they are from a
1264 BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which
1265 case there is definitely no BusLogic Host Adapter at this base I/O Address.
1266 The test here is a subset of that used by the BusLogic Host Adapter BIOS.
1268 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1269 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
1270 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1271 if (BusLogic_GlobalOptions.TraceProbe)
1272 BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, "
1273 "Geometry 0x%02X\n", HostAdapter,
1274 HostAdapter->IO_Address, StatusRegister.All,
1275 InterruptRegister.All, GeometryRegister.All);
1276 if (StatusRegister.All == 0 ||
1277 StatusRegister.Bits.DiagnosticActive ||
1278 StatusRegister.Bits.CommandParameterRegisterBusy ||
1279 StatusRegister.Bits.Reserved ||
1280 StatusRegister.Bits.CommandInvalid ||
1281 InterruptRegister.Bits.Reserved != 0)
1282 return false;
1284 Check the undocumented Geometry Register to test if there is an I/O port
1285 that responded. Adaptec Host Adapters do not implement the Geometry
1286 Register, so this test helps serve to avoid incorrectly recognizing an
1287 Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C
1288 series does respond to the Geometry Register I/O port, but it will be
1289 rejected later when the Inquire Extended Setup Information command is
1290 issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a
1291 BusLogic clone that implements the same interface as earlier BusLogic
1292 Host Adapters, including the undocumented commands, and is therefore
1293 supported by this driver. However, the AMI FastDisk always returns 0x00
1294 upon reading the Geometry Register, so the extended translation option
1295 should always be left disabled on the AMI FastDisk.
1297 if (GeometryRegister.All == 0xFF) return false;
1299 Indicate the Host Adapter Probe completed successfully.
1301 return true;
1306 BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter
1307 and waits for Host Adapter Diagnostics to complete. If HardReset is true, a
1308 Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
1309 Soft Reset is performed which only resets the Host Adapter without forcing a
1310 SCSI Bus Reset.
1313 static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T
1314 *HostAdapter,
1315 boolean HardReset)
1317 BusLogic_StatusRegister_T StatusRegister;
1318 int TimeoutCounter;
1320 FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
1322 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1324 FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1325 FlashPointInfo->HostSoftReset = !HardReset;
1326 FlashPointInfo->ReportDataUnderrun = true;
1327 HostAdapter->CardHandle =
1328 FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
1329 if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false;
1331 Indicate the Host Adapter Hard Reset completed successfully.
1333 return true;
1336 Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host
1337 Adapter should respond by setting Diagnostic Active in the Status Register.
1339 if (HardReset)
1340 BusLogic_HardReset(HostAdapter);
1341 else BusLogic_SoftReset(HostAdapter);
1343 Wait until Diagnostic Active is set in the Status Register.
1345 TimeoutCounter = 5*10000;
1346 while (--TimeoutCounter >= 0)
1348 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1349 if (StatusRegister.Bits.DiagnosticActive) break;
1350 udelay(100);
1352 if (BusLogic_GlobalOptions.TraceHardwareReset)
1353 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, "
1354 "Status 0x%02X\n", HostAdapter,
1355 HostAdapter->IO_Address, StatusRegister.All);
1356 if (TimeoutCounter < 0) return false;
1358 Wait 100 microseconds to allow completion of any initial diagnostic
1359 activity which might leave the contents of the Status Register
1360 unpredictable.
1362 udelay(100);
1364 Wait until Diagnostic Active is reset in the Status Register.
1366 TimeoutCounter = 10*10000;
1367 while (--TimeoutCounter >= 0)
1369 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1370 if (!StatusRegister.Bits.DiagnosticActive) break;
1371 udelay(100);
1373 if (BusLogic_GlobalOptions.TraceHardwareReset)
1374 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, "
1375 "Status 0x%02X\n", HostAdapter,
1376 HostAdapter->IO_Address, StatusRegister.All);
1377 if (TimeoutCounter < 0) return false;
1379 Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
1380 or Data In Register Ready bits is set in the Status Register.
1382 TimeoutCounter = 10000;
1383 while (--TimeoutCounter >= 0)
1385 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1386 if (StatusRegister.Bits.DiagnosticFailure ||
1387 StatusRegister.Bits.HostAdapterReady ||
1388 StatusRegister.Bits.DataInRegisterReady)
1389 break;
1390 udelay(100);
1392 if (BusLogic_GlobalOptions.TraceHardwareReset)
1393 BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, "
1394 "Status 0x%02X\n", HostAdapter,
1395 HostAdapter->IO_Address, StatusRegister.All);
1396 if (TimeoutCounter < 0) return false;
1398 If Diagnostic Failure is set or Host Adapter Ready is reset, then an
1399 error occurred during the Host Adapter diagnostics. If Data In Register
1400 Ready is set, then there is an Error Code available.
1402 if (StatusRegister.Bits.DiagnosticFailure ||
1403 !StatusRegister.Bits.HostAdapterReady)
1405 BusLogic_CommandFailureReason = NULL;
1406 BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
1407 BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n",
1408 HostAdapter, StatusRegister.All);
1409 if (StatusRegister.Bits.DataInRegisterReady)
1411 unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
1412 BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n",
1413 HostAdapter, ErrorCode);
1415 return false;
1418 Indicate the Host Adapter Hard Reset completed successfully.
1420 return true;
1425 BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
1426 Host Adapter.
1429 static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
1431 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
1432 BusLogic_RequestedReplyLength_T RequestedReplyLength;
1433 boolean Result = true;
1435 FlashPoint Host Adapters do not require this protection.
1437 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
1439 Issue the Inquire Extended Setup Information command. Only genuine
1440 BusLogic Host Adapters and true clones support this command. Adaptec 1542C
1441 series Host Adapters that respond to the Geometry Register I/O port will
1442 fail this command.
1444 RequestedReplyLength = sizeof(ExtendedSetupInformation);
1445 if (BusLogic_Command(HostAdapter,
1446 BusLogic_InquireExtendedSetupInformation,
1447 &RequestedReplyLength,
1448 sizeof(RequestedReplyLength),
1449 &ExtendedSetupInformation,
1450 sizeof(ExtendedSetupInformation))
1451 != sizeof(ExtendedSetupInformation))
1452 Result = false;
1454 Provide tracing information if requested and return.
1456 if (BusLogic_GlobalOptions.TraceProbe)
1457 BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter,
1458 HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
1459 return Result;
1464 BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
1465 from Host Adapter and initializes the Host Adapter structure.
1468 static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
1469 *HostAdapter)
1471 BusLogic_BoardID_T BoardID;
1472 BusLogic_Configuration_T Configuration;
1473 BusLogic_SetupInformation_T SetupInformation;
1474 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
1475 BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber;
1476 BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
1477 BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
1478 BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
1479 BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest;
1480 BusLogic_AutoSCSIData_T AutoSCSIData;
1481 BusLogic_GeometryRegister_T GeometryRegister;
1482 BusLogic_RequestedReplyLength_T RequestedReplyLength;
1483 unsigned char *TargetPointer, Character;
1484 int TargetID, i;
1486 Configuration Information for FlashPoint Host Adapters is provided in the
1487 FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
1488 Initialize fields in the Host Adapter structure from the FlashPoint_Info
1489 structure.
1491 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1493 FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1494 TargetPointer = HostAdapter->ModelName;
1495 *TargetPointer++ = 'B';
1496 *TargetPointer++ = 'T';
1497 *TargetPointer++ = '-';
1498 for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
1499 *TargetPointer++ = FlashPointInfo->ModelNumber[i];
1500 *TargetPointer++ = '\0';
1501 strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
1502 HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
1503 HostAdapter->ExtendedTranslationEnabled =
1504 FlashPointInfo->ExtendedTranslationEnabled;
1505 HostAdapter->ParityCheckingEnabled =
1506 FlashPointInfo->ParityCheckingEnabled;
1507 HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
1508 HostAdapter->LevelSensitiveInterrupt = true;
1509 HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
1510 HostAdapter->HostDifferentialSCSI = false;
1511 HostAdapter->HostSupportsSCAM = true;
1512 HostAdapter->HostUltraSCSI = true;
1513 HostAdapter->ExtendedLUNSupport = true;
1514 HostAdapter->TerminationInfoValid = true;
1515 HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
1516 HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
1517 HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
1518 HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
1519 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1520 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1521 HostAdapter->MaxLogicalUnits = 32;
1522 HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1523 HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1524 HostAdapter->DriverQueueDepth = 255;
1525 HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
1526 HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
1527 HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
1528 HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
1529 HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
1530 HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
1531 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1532 goto Common;
1535 Issue the Inquire Board ID command.
1537 if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
1538 &BoardID, sizeof(BoardID)) != sizeof(BoardID))
1539 return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
1541 Issue the Inquire Configuration command.
1543 if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
1544 &Configuration, sizeof(Configuration))
1545 != sizeof(Configuration))
1546 return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
1548 Issue the Inquire Setup Information command.
1550 RequestedReplyLength = sizeof(SetupInformation);
1551 if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
1552 &RequestedReplyLength, sizeof(RequestedReplyLength),
1553 &SetupInformation, sizeof(SetupInformation))
1554 != sizeof(SetupInformation))
1555 return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
1557 Issue the Inquire Extended Setup Information command.
1559 RequestedReplyLength = sizeof(ExtendedSetupInformation);
1560 if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
1561 &RequestedReplyLength, sizeof(RequestedReplyLength),
1562 &ExtendedSetupInformation,
1563 sizeof(ExtendedSetupInformation))
1564 != sizeof(ExtendedSetupInformation))
1565 return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
1567 Issue the Inquire Firmware Version 3rd Digit command.
1569 FirmwareVersion3rdDigit = '\0';
1570 if (BoardID.FirmwareVersion1stDigit > '0')
1571 if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
1572 NULL, 0, &FirmwareVersion3rdDigit,
1573 sizeof(FirmwareVersion3rdDigit))
1574 != sizeof(FirmwareVersion3rdDigit))
1575 return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
1577 Issue the Inquire Host Adapter Model Number command.
1579 if (ExtendedSetupInformation.BusType == 'A' &&
1580 BoardID.FirmwareVersion1stDigit == '2')
1581 /* BusLogic BT-542B ISA 2.xx */
1582 strcpy(HostAdapterModelNumber, "542B");
1583 else if (ExtendedSetupInformation.BusType == 'E' &&
1584 BoardID.FirmwareVersion1stDigit == '2' &&
1585 (BoardID.FirmwareVersion2ndDigit <= '1' ||
1586 (BoardID.FirmwareVersion2ndDigit == '2' &&
1587 FirmwareVersion3rdDigit == '0')))
1588 /* BusLogic BT-742A EISA 2.1x or 2.20 */
1589 strcpy(HostAdapterModelNumber, "742A");
1590 else if (ExtendedSetupInformation.BusType == 'E' &&
1591 BoardID.FirmwareVersion1stDigit == '0')
1592 /* AMI FastDisk EISA Series 441 0.x */
1593 strcpy(HostAdapterModelNumber, "747A");
1594 else
1596 RequestedReplyLength = sizeof(HostAdapterModelNumber);
1597 if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber,
1598 &RequestedReplyLength, sizeof(RequestedReplyLength),
1599 &HostAdapterModelNumber,
1600 sizeof(HostAdapterModelNumber))
1601 != sizeof(HostAdapterModelNumber))
1602 return BusLogic_Failure(HostAdapter,
1603 "INQUIRE HOST ADAPTER MODEL NUMBER");
1606 BusLogic MultiMaster Host Adapters can be identified by their model number
1607 and the major version number of their firmware as follows:
1609 5.xx BusLogic "W" Series Host Adapters:
1610 BT-948/958/958D
1611 4.xx BusLogic "C" Series Host Adapters:
1612 BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1613 3.xx BusLogic "S" Series Host Adapters:
1614 BT-747S/747D/757S/757D/445S/545S/542D
1615 BT-542B/742A (revision H)
1616 2.xx BusLogic "A" Series Host Adapters:
1617 BT-542B/742A (revision G and below)
1618 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1621 Save the Model Name and Host Adapter Name in the Host Adapter structure.
1623 TargetPointer = HostAdapter->ModelName;
1624 *TargetPointer++ = 'B';
1625 *TargetPointer++ = 'T';
1626 *TargetPointer++ = '-';
1627 for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
1629 Character = HostAdapterModelNumber[i];
1630 if (Character == ' ' || Character == '\0') break;
1631 *TargetPointer++ = Character;
1633 *TargetPointer++ = '\0';
1635 Save the Firmware Version in the Host Adapter structure.
1637 TargetPointer = HostAdapter->FirmwareVersion;
1638 *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
1639 *TargetPointer++ = '.';
1640 *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
1641 if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
1642 *TargetPointer++ = FirmwareVersion3rdDigit;
1643 *TargetPointer = '\0';
1645 Issue the Inquire Firmware Version Letter command.
1647 if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0)
1649 if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
1650 NULL, 0, &FirmwareVersionLetter,
1651 sizeof(FirmwareVersionLetter))
1652 != sizeof(FirmwareVersionLetter))
1653 return BusLogic_Failure(HostAdapter,
1654 "INQUIRE FIRMWARE VERSION LETTER");
1655 if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
1656 *TargetPointer++ = FirmwareVersionLetter;
1657 *TargetPointer = '\0';
1660 Save the Host Adapter SCSI ID in the Host Adapter structure.
1662 HostAdapter->SCSI_ID = Configuration.HostAdapterID;
1664 Determine the Bus Type and save it in the Host Adapter structure, determine
1665 and save the IRQ Channel if necessary, and determine and save the DMA
1666 Channel for ISA Host Adapters.
1668 HostAdapter->HostAdapterBusType =
1669 BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
1670 if (HostAdapter->IRQ_Channel == 0)
1672 if (Configuration.IRQ_Channel9)
1673 HostAdapter->IRQ_Channel = 9;
1674 else if (Configuration.IRQ_Channel10)
1675 HostAdapter->IRQ_Channel = 10;
1676 else if (Configuration.IRQ_Channel11)
1677 HostAdapter->IRQ_Channel = 11;
1678 else if (Configuration.IRQ_Channel12)
1679 HostAdapter->IRQ_Channel = 12;
1680 else if (Configuration.IRQ_Channel14)
1681 HostAdapter->IRQ_Channel = 14;
1682 else if (Configuration.IRQ_Channel15)
1683 HostAdapter->IRQ_Channel = 15;
1685 if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
1687 if (Configuration.DMA_Channel5)
1688 HostAdapter->DMA_Channel = 5;
1689 else if (Configuration.DMA_Channel6)
1690 HostAdapter->DMA_Channel = 6;
1691 else if (Configuration.DMA_Channel7)
1692 HostAdapter->DMA_Channel = 7;
1695 Determine whether Extended Translation is enabled and save it in
1696 the Host Adapter structure.
1698 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1699 HostAdapter->ExtendedTranslationEnabled =
1700 GeometryRegister.Bits.ExtendedTranslationEnabled;
1702 Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1703 SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1704 Ultra SCSI flag in the Host Adapter structure.
1706 HostAdapter->HostAdapterScatterGatherLimit =
1707 ExtendedSetupInformation.ScatterGatherLimit;
1708 HostAdapter->DriverScatterGatherLimit =
1709 HostAdapter->HostAdapterScatterGatherLimit;
1710 if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
1711 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1712 if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
1713 HostAdapter->LevelSensitiveInterrupt = true;
1714 HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
1715 HostAdapter->HostDifferentialSCSI =
1716 ExtendedSetupInformation.HostDifferentialSCSI;
1717 HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
1718 HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
1720 Determine whether Extended LUN Format CCBs are supported and save the
1721 information in the Host Adapter structure.
1723 if (HostAdapter->FirmwareVersion[0] == '5' ||
1724 (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
1725 HostAdapter->ExtendedLUNSupport = true;
1727 Issue the Inquire PCI Host Adapter Information command to read the
1728 Termination Information from "W" series MultiMaster Host Adapters.
1730 if (HostAdapter->FirmwareVersion[0] == '5')
1732 if (BusLogic_Command(HostAdapter,
1733 BusLogic_InquirePCIHostAdapterInformation,
1734 NULL, 0, &PCIHostAdapterInformation,
1735 sizeof(PCIHostAdapterInformation))
1736 != sizeof(PCIHostAdapterInformation))
1737 return BusLogic_Failure(HostAdapter,
1738 "INQUIRE PCI HOST ADAPTER INFORMATION");
1740 Save the Termination Information in the Host Adapter structure.
1742 if (PCIHostAdapterInformation.GenericInfoValid)
1744 HostAdapter->TerminationInfoValid = true;
1745 HostAdapter->LowByteTerminated =
1746 PCIHostAdapterInformation.LowByteTerminated;
1747 HostAdapter->HighByteTerminated =
1748 PCIHostAdapterInformation.HighByteTerminated;
1752 Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
1753 from "W" and "C" series MultiMaster Host Adapters.
1755 if (HostAdapter->FirmwareVersion[0] >= '4')
1757 FetchHostAdapterLocalRAMRequest.ByteOffset =
1758 BusLogic_AutoSCSI_BaseOffset;
1759 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
1760 if (BusLogic_Command(HostAdapter,
1761 BusLogic_FetchHostAdapterLocalRAM,
1762 &FetchHostAdapterLocalRAMRequest,
1763 sizeof(FetchHostAdapterLocalRAMRequest),
1764 &AutoSCSIData, sizeof(AutoSCSIData))
1765 != sizeof(AutoSCSIData))
1766 return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
1768 Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
1769 Information in the Host Adapter structure.
1771 HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
1772 HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
1773 if (HostAdapter->FirmwareVersion[0] == '4')
1775 HostAdapter->TerminationInfoValid = true;
1776 HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
1777 HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
1780 Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
1781 Disconnect Permitted, Ultra Permitted, and SCAM Information in the
1782 Host Adapter structure.
1784 HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
1785 HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
1786 HostAdapter->SynchronousPermitted =
1787 AutoSCSIData.SynchronousPermitted;
1788 HostAdapter->DisconnectPermitted =
1789 AutoSCSIData.DisconnectPermitted;
1790 if (HostAdapter->HostUltraSCSI)
1791 HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
1792 if (HostAdapter->HostSupportsSCAM)
1794 HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
1795 HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
1799 Initialize fields in the Host Adapter structure for "S" and "A" series
1800 MultiMaster Host Adapters.
1802 if (HostAdapter->FirmwareVersion[0] < '4')
1804 if (SetupInformation.SynchronousInitiationEnabled)
1806 HostAdapter->SynchronousPermitted = 0xFF;
1807 if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)
1809 if (ExtendedSetupInformation.Misc.FastOnEISA)
1810 HostAdapter->FastPermitted = 0xFF;
1811 if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
1812 HostAdapter->WidePermitted = 0xFF;
1815 HostAdapter->DisconnectPermitted = 0xFF;
1816 HostAdapter->ParityCheckingEnabled =
1817 SetupInformation.ParityCheckingEnabled;
1818 HostAdapter->BusResetEnabled = true;
1821 Determine the maximum number of Target IDs and Logical Units supported by
1822 this driver for Wide and Narrow Host Adapters.
1824 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1825 HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
1827 Select appropriate values for the Mailbox Count, Driver Queue Depth,
1828 Initial CCBs, and Incremental CCBs variables based on whether or not Strict
1829 Round Robin Mode is supported. If Strict Round Robin Mode is supported,
1830 then there is no performance degradation in using the maximum possible
1831 number of Outgoing and Incoming Mailboxes and allowing the Tagged and
1832 Untagged Queue Depths to determine the actual utilization. If Strict Round
1833 Robin Mode is not supported, then the Host Adapter must scan all the
1834 Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
1835 cause a substantial performance penalty. The host adapters actually have
1836 room to store the following number of CCBs internally; that is, they can
1837 internally queue and manage this many active commands on the SCSI bus
1838 simultaneously. Performance measurements demonstrate that the Driver Queue
1839 Depth should be set to the Mailbox Count, rather than the Host Adapter
1840 Queue Depth (internal CCB capacity), as it is more efficient to have the
1841 queued commands waiting in Outgoing Mailboxes if necessary than to block
1842 the process in the higher levels of the SCSI Subsystem.
1844 192 BT-948/958/958D
1845 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1846 50 BT-545C/540CF
1847 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1849 if (HostAdapter->FirmwareVersion[0] == '5')
1850 HostAdapter->HostAdapterQueueDepth = 192;
1851 else if (HostAdapter->FirmwareVersion[0] == '4')
1852 HostAdapter->HostAdapterQueueDepth =
1853 (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
1854 else HostAdapter->HostAdapterQueueDepth = 30;
1855 if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0)
1857 HostAdapter->StrictRoundRobinModeSupport = true;
1858 HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
1860 else
1862 HostAdapter->StrictRoundRobinModeSupport = false;
1863 HostAdapter->MailboxCount = 32;
1865 HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
1866 HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1867 HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1869 Tagged Queuing support is available and operates properly on all "W" series
1870 MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
1871 firmware version 4.22 and above, and on "S" series MultiMaster Host
1872 Adapters with firmware version 3.35 and above.
1874 HostAdapter->TaggedQueuingPermitted = 0;
1875 switch (HostAdapter->FirmwareVersion[0])
1877 case '5':
1878 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1879 break;
1880 case '4':
1881 if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
1882 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1883 break;
1884 case '3':
1885 if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
1886 HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1887 break;
1890 Determine the Host Adapter BIOS Address if the BIOS is enabled and
1891 save it in the Host Adapter structure. The BIOS is disabled if the
1892 BIOS_Address is 0.
1894 HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
1896 ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
1898 if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus &&
1899 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1900 HostAdapter->BounceBuffersRequired = true;
1902 BusLogic BT-445S Host Adapters prior to board revision E have a hardware
1903 bug whereby when the BIOS is enabled, transfers to/from the same address
1904 range the BIOS occupies modulo 16MB are handled incorrectly. Only properly
1905 functioning BT-445S Host Adapters have firmware version 3.37, so require
1906 that ISA Bounce Buffers be used for the buggy BT-445S models if there is
1907 more than 16MB memory.
1909 if (HostAdapter->BIOS_Address > 0 &&
1910 strcmp(HostAdapter->ModelName, "BT-445S") == 0 &&
1911 strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 &&
1912 (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1913 HostAdapter->BounceBuffersRequired = true;
1915 Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
1917 Common:
1919 Initialize the Host Adapter Full Model Name from the Model Name.
1921 strcpy(HostAdapter->FullModelName, "BusLogic ");
1922 strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
1924 Select an appropriate value for the Tagged Queue Depth either from a
1925 BusLogic Driver Options specification, or based on whether this Host
1926 Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth
1927 is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
1928 Initialize the Untagged Queue Depth.
1930 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
1932 unsigned char QueueDepth = 0;
1933 if (HostAdapter->DriverOptions != NULL &&
1934 HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
1935 QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
1936 else if (HostAdapter->BounceBuffersRequired)
1937 QueueDepth = BusLogic_TaggedQueueDepthBB;
1938 HostAdapter->QueueDepth[TargetID] = QueueDepth;
1940 if (HostAdapter->BounceBuffersRequired)
1941 HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
1942 else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
1943 if (HostAdapter->DriverOptions != NULL)
1944 HostAdapter->CommonQueueDepth =
1945 HostAdapter->DriverOptions->CommonQueueDepth;
1946 if (HostAdapter->CommonQueueDepth > 0 &&
1947 HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
1948 HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
1950 Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1951 Therefore, mask the Tagged Queuing Permitted Default bits with the
1952 Disconnect/Reconnect Permitted bits.
1954 HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
1956 Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
1957 Options Tagged Queuing specification.
1959 if (HostAdapter->DriverOptions != NULL)
1960 HostAdapter->TaggedQueuingPermitted =
1961 (HostAdapter->DriverOptions->TaggedQueuingPermitted &
1962 HostAdapter->DriverOptions->TaggedQueuingPermittedMask) |
1963 (HostAdapter->TaggedQueuingPermitted &
1964 ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
1966 Select appropriate values for the Error Recovery Strategy array
1967 either from a BusLogic Driver Options specification, or using
1968 BusLogic_ErrorRecovery_Default.
1970 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
1971 if (HostAdapter->DriverOptions != NULL)
1972 HostAdapter->ErrorRecoveryStrategy[TargetID] =
1973 HostAdapter->DriverOptions->ErrorRecoveryStrategy[TargetID];
1974 else HostAdapter->ErrorRecoveryStrategy[TargetID] =
1975 BusLogic_ErrorRecovery_Default;
1977 Select an appropriate value for Bus Settle Time either from a BusLogic
1978 Driver Options specification, or from BusLogic_DefaultBusSettleTime.
1980 if (HostAdapter->DriverOptions != NULL &&
1981 HostAdapter->DriverOptions->BusSettleTime > 0)
1982 HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
1983 else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
1985 Indicate reading the Host Adapter Configuration completed successfully.
1987 return true;
1992 BusLogic_ReportHostAdapterConfiguration reports the configuration of
1993 Host Adapter.
1996 static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T
1997 *HostAdapter)
1999 unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
2000 unsigned short SynchronousPermitted, FastPermitted;
2001 unsigned short UltraPermitted, WidePermitted;
2002 unsigned short DisconnectPermitted, TaggedQueuingPermitted;
2003 boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
2004 boolean CommonErrorRecovery;
2005 char SynchronousString[BusLogic_MaxTargetDevices+1];
2006 char WideString[BusLogic_MaxTargetDevices+1];
2007 char DisconnectString[BusLogic_MaxTargetDevices+1];
2008 char TaggedQueuingString[BusLogic_MaxTargetDevices+1];
2009 char ErrorRecoveryString[BusLogic_MaxTargetDevices+1];
2010 char *SynchronousMessage = SynchronousString;
2011 char *WideMessage = WideString;
2012 char *DisconnectMessage = DisconnectString;
2013 char *TaggedQueuingMessage = TaggedQueuingString;
2014 char *ErrorRecoveryMessage = ErrorRecoveryString;
2015 int TargetID;
2016 BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
2017 HostAdapter, HostAdapter->ModelName,
2018 BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType],
2019 (HostAdapter->HostWideSCSI ? " Wide" : ""),
2020 (HostAdapter->HostDifferentialSCSI ? " Differential" : ""),
2021 (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
2022 BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, "
2023 "IRQ Channel: %d/%s\n", HostAdapter,
2024 HostAdapter->FirmwareVersion,
2025 HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
2026 (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
2027 if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus)
2029 BusLogic_Info(" DMA Channel: ", HostAdapter);
2030 if (HostAdapter->DMA_Channel > 0)
2031 BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
2032 else BusLogic_Info("None, ", HostAdapter);
2033 if (HostAdapter->BIOS_Address > 0)
2034 BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter,
2035 HostAdapter->BIOS_Address);
2036 else BusLogic_Info("BIOS Address: None, ", HostAdapter);
2038 else
2040 BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ",
2041 HostAdapter, HostAdapter->Bus, HostAdapter->Device);
2042 if (HostAdapter->PCI_Address > 0)
2043 BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
2044 else BusLogic_Info("Unassigned, ", HostAdapter);
2046 BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter,
2047 HostAdapter->SCSI_ID);
2048 BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n",
2049 HostAdapter,
2050 (HostAdapter->ParityCheckingEnabled
2051 ? "Enabled" : "Disabled"),
2052 (HostAdapter->ExtendedTranslationEnabled
2053 ? "Enabled" : "Disabled"));
2054 AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
2055 SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
2056 FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
2057 UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
2058 if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
2059 (HostAdapter->FirmwareVersion[0] >= '4' ||
2060 HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) ||
2061 BusLogic_FlashPointHostAdapterP(HostAdapter))
2063 CommonSynchronousNegotiation = false;
2064 if (SynchronousPermitted == 0)
2066 SynchronousMessage = "Disabled";
2067 CommonSynchronousNegotiation = true;
2069 else if (SynchronousPermitted == AllTargetsMask)
2071 if (FastPermitted == 0)
2073 SynchronousMessage = "Slow";
2074 CommonSynchronousNegotiation = true;
2076 else if (FastPermitted == AllTargetsMask)
2078 if (UltraPermitted == 0)
2080 SynchronousMessage = "Fast";
2081 CommonSynchronousNegotiation = true;
2083 else if (UltraPermitted == AllTargetsMask)
2085 SynchronousMessage = "Ultra";
2086 CommonSynchronousNegotiation = true;
2090 if (!CommonSynchronousNegotiation)
2092 for (TargetID = 0;
2093 TargetID < HostAdapter->MaxTargetDevices;
2094 TargetID++)
2095 SynchronousString[TargetID] =
2096 ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' :
2097 (!(FastPermitted & (1 << TargetID)) ? 'S' :
2098 (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
2099 SynchronousString[HostAdapter->SCSI_ID] = '#';
2100 SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
2103 else SynchronousMessage =
2104 (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
2105 WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
2106 if (WidePermitted == 0)
2107 WideMessage = "Disabled";
2108 else if (WidePermitted == AllTargetsMask)
2109 WideMessage = "Enabled";
2110 else
2112 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2113 WideString[TargetID] =
2114 ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
2115 WideString[HostAdapter->SCSI_ID] = '#';
2116 WideString[HostAdapter->MaxTargetDevices] = '\0';
2118 DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
2119 if (DisconnectPermitted == 0)
2120 DisconnectMessage = "Disabled";
2121 else if (DisconnectPermitted == AllTargetsMask)
2122 DisconnectMessage = "Enabled";
2123 else
2125 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2126 DisconnectString[TargetID] =
2127 ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
2128 DisconnectString[HostAdapter->SCSI_ID] = '#';
2129 DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
2131 TaggedQueuingPermitted =
2132 HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
2133 if (TaggedQueuingPermitted == 0)
2134 TaggedQueuingMessage = "Disabled";
2135 else if (TaggedQueuingPermitted == AllTargetsMask)
2136 TaggedQueuingMessage = "Enabled";
2137 else
2139 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2140 TaggedQueuingString[TargetID] =
2141 ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
2142 TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
2143 TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
2145 BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
2146 HostAdapter, SynchronousMessage, WideMessage);
2147 BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n",
2148 HostAdapter, DisconnectMessage, TaggedQueuingMessage);
2149 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
2151 BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, "
2152 "Mailboxes: %d\n", HostAdapter,
2153 HostAdapter->DriverScatterGatherLimit,
2154 HostAdapter->HostAdapterScatterGatherLimit,
2155 HostAdapter->MailboxCount);
2156 BusLogic_Info(" Driver Queue Depth: %d, "
2157 "Host Adapter Queue Depth: %d\n",
2158 HostAdapter, HostAdapter->DriverQueueDepth,
2159 HostAdapter->HostAdapterQueueDepth);
2161 else BusLogic_Info(" Driver Queue Depth: %d, "
2162 "Scatter/Gather Limit: %d segments\n",
2163 HostAdapter, HostAdapter->DriverQueueDepth,
2164 HostAdapter->DriverScatterGatherLimit);
2165 BusLogic_Info(" Tagged Queue Depth: ", HostAdapter);
2166 CommonTaggedQueueDepth = true;
2167 for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2168 if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0])
2170 CommonTaggedQueueDepth = false;
2171 break;
2173 if (CommonTaggedQueueDepth)
2175 if (HostAdapter->QueueDepth[0] > 0)
2176 BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
2177 else BusLogic_Info("Automatic", HostAdapter);
2179 else BusLogic_Info("Individual", HostAdapter);
2180 BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter,
2181 HostAdapter->UntaggedQueueDepth);
2182 CommonErrorRecovery = true;
2183 for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2184 if (HostAdapter->ErrorRecoveryStrategy[TargetID] !=
2185 HostAdapter->ErrorRecoveryStrategy[0])
2187 CommonErrorRecovery = false;
2188 break;
2190 if (CommonErrorRecovery)
2191 ErrorRecoveryMessage =
2192 BusLogic_ErrorRecoveryStrategyNames[
2193 HostAdapter->ErrorRecoveryStrategy[0]];
2194 else
2196 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2197 ErrorRecoveryString[TargetID] =
2198 BusLogic_ErrorRecoveryStrategyLetters[
2199 HostAdapter->ErrorRecoveryStrategy[TargetID]];
2200 ErrorRecoveryString[HostAdapter->SCSI_ID] = '#';
2201 ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0';
2203 BusLogic_Info(" Error Recovery Strategy: %s, SCSI Bus Reset: %s\n",
2204 HostAdapter, ErrorRecoveryMessage,
2205 (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled"));
2206 if (HostAdapter->TerminationInfoValid)
2208 if (HostAdapter->HostWideSCSI)
2209 BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter,
2210 (HostAdapter->LowByteTerminated
2211 ? (HostAdapter->HighByteTerminated
2212 ? "Both Enabled" : "Low Enabled")
2213 : (HostAdapter->HighByteTerminated
2214 ? "High Enabled" : "Both Disabled")));
2215 else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter,
2216 (HostAdapter->LowByteTerminated ?
2217 "Enabled" : "Disabled"));
2218 if (HostAdapter->HostSupportsSCAM)
2219 BusLogic_Info(", SCAM: %s", HostAdapter,
2220 (HostAdapter->SCAM_Enabled
2221 ? (HostAdapter->SCAM_Level2
2222 ? "Enabled, Level 2" : "Enabled, Level 1")
2223 : "Disabled"));
2224 BusLogic_Info("\n", HostAdapter);
2227 Indicate reporting the Host Adapter configuration completed successfully.
2229 return true;
2234 BusLogic_AcquireResources acquires the system resources necessary to use
2235 Host Adapter.
2238 static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
2240 if (HostAdapter->IRQ_Channel == 0)
2242 BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
2243 HostAdapter);
2244 return false;
2247 Acquire shared access to the IRQ Channel.
2249 if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
2250 SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0)
2252 BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
2253 HostAdapter, HostAdapter->IRQ_Channel);
2254 return false;
2256 HostAdapter->IRQ_ChannelAcquired = true;
2258 Acquire exclusive access to the DMA Channel.
2260 if (HostAdapter->DMA_Channel > 0)
2262 if (request_dma(HostAdapter->DMA_Channel,
2263 HostAdapter->FullModelName) < 0)
2265 BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
2266 HostAdapter, HostAdapter->DMA_Channel);
2267 return false;
2269 set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
2270 enable_dma(HostAdapter->DMA_Channel);
2271 HostAdapter->DMA_ChannelAcquired = true;
2274 Indicate the System Resource Acquisition completed successfully,
2276 return true;
2281 BusLogic_ReleaseResources releases any system resources previously acquired
2282 by BusLogic_AcquireResources.
2285 static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter)
2288 Release shared access to the IRQ Channel.
2290 if (HostAdapter->IRQ_ChannelAcquired)
2291 free_irq(HostAdapter->IRQ_Channel, HostAdapter);
2293 Release exclusive access to the DMA Channel.
2295 if (HostAdapter->DMA_ChannelAcquired)
2296 free_dma(HostAdapter->DMA_Channel);
2301 BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only
2302 function called during SCSI Host Adapter detection which modifies the state
2303 of the Host Adapter from its initial power on or hard reset state.
2306 static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T
2307 *HostAdapter)
2309 BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
2310 BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest;
2311 BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest;
2312 int TargetID;
2314 Initialize the pointers to the first and last CCBs that are queued for
2315 completion processing.
2317 HostAdapter->FirstCompletedCCB = NULL;
2318 HostAdapter->LastCompletedCCB = NULL;
2320 Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
2321 Command Successful Flag, Active Commands, and Commands Since Reset
2322 for each Target Device.
2324 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2326 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
2327 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
2328 HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
2329 HostAdapter->ActiveCommands[TargetID] = 0;
2330 HostAdapter->CommandsSinceReset[TargetID] = 0;
2333 FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
2335 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done;
2337 Initialize the Outgoing and Incoming Mailbox pointers.
2339 HostAdapter->FirstOutgoingMailbox =
2340 (BusLogic_OutgoingMailbox_T *) HostAdapter->MailboxSpace;
2341 HostAdapter->LastOutgoingMailbox =
2342 HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
2343 HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
2344 HostAdapter->FirstIncomingMailbox =
2345 (BusLogic_IncomingMailbox_T *) (HostAdapter->LastOutgoingMailbox + 1);
2346 HostAdapter->LastIncomingMailbox =
2347 HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
2348 HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
2350 Initialize the Outgoing and Incoming Mailbox structures.
2352 memset(HostAdapter->FirstOutgoingMailbox, 0,
2353 HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T));
2354 memset(HostAdapter->FirstIncomingMailbox, 0,
2355 HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T));
2357 Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
2359 ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
2360 ExtendedMailboxRequest.BaseMailboxAddress =
2361 Virtual_to_Bus(HostAdapter->FirstOutgoingMailbox);
2362 if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
2363 &ExtendedMailboxRequest,
2364 sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
2365 return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
2367 Enable Strict Round Robin Mode if supported by the Host Adapter. In
2368 Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
2369 Mailbox for each new command, rather than scanning through all the
2370 Outgoing Mailboxes to find any that have new commands in them. Strict
2371 Round Robin Mode is significantly more efficient.
2373 if (HostAdapter->StrictRoundRobinModeSupport)
2375 RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
2376 if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
2377 &RoundRobinModeRequest,
2378 sizeof(RoundRobinModeRequest), NULL, 0) < 0)
2379 return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
2382 For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
2383 Format command to allow 32 Logical Units per Target Device.
2385 if (HostAdapter->ExtendedLUNSupport)
2387 SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
2388 if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat,
2389 &SetCCBFormatRequest, sizeof(SetCCBFormatRequest),
2390 NULL, 0) < 0)
2391 return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
2394 Announce Successful Initialization.
2396 Done:
2397 if (!HostAdapter->HostAdapterInitialized)
2399 BusLogic_Info("*** %s Initialized Successfully ***\n",
2400 HostAdapter, HostAdapter->FullModelName);
2401 BusLogic_Info("\n", HostAdapter);
2403 else BusLogic_Warning("*** %s Initialized Successfully ***\n",
2404 HostAdapter, HostAdapter->FullModelName);
2405 HostAdapter->HostAdapterInitialized = true;
2407 Indicate the Host Adapter Initialization completed successfully.
2409 return true;
2414 BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
2415 through Host Adapter.
2418 static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T
2419 *HostAdapter)
2421 BusLogic_InstalledDevices_T InstalledDevices;
2422 BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
2423 BusLogic_SetupInformation_T SetupInformation;
2424 BusLogic_SynchronousPeriod_T SynchronousPeriod;
2425 BusLogic_RequestedReplyLength_T RequestedReplyLength;
2426 int TargetID;
2428 Wait a few seconds between the Host Adapter Hard Reset which initiates
2429 a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
2430 confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
2432 BusLogic_Delay(HostAdapter->BusSettleTime);
2434 FlashPoint Host Adapters do not provide for Target Device Inquiry.
2436 if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
2438 Inhibit the Target Device Inquiry if requested.
2440 if (HostAdapter->DriverOptions != NULL &&
2441 HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
2442 return true;
2444 Issue the Inquire Target Devices command for host adapters with firmware
2445 version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
2446 for older host adapters. This is necessary to force Synchronous Transfer
2447 Negotiation so that the Inquire Setup Information and Inquire Synchronous
2448 Period commands will return valid data. The Inquire Target Devices command
2449 is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
2450 Logical Unit 0 of each Target Device.
2452 if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
2454 if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0,
2455 &InstalledDevices, sizeof(InstalledDevices))
2456 != sizeof(InstalledDevices))
2457 return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
2458 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2459 HostAdapter->TargetFlags[TargetID].TargetExists =
2460 (InstalledDevices & (1 << TargetID) ? true : false);
2462 else
2464 if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
2465 NULL, 0, &InstalledDevicesID0to7,
2466 sizeof(InstalledDevicesID0to7))
2467 != sizeof(InstalledDevicesID0to7))
2468 return BusLogic_Failure(HostAdapter,
2469 "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2470 for (TargetID = 0; TargetID < 8; TargetID++)
2471 HostAdapter->TargetFlags[TargetID].TargetExists =
2472 (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
2475 Issue the Inquire Setup Information command.
2477 RequestedReplyLength = sizeof(SetupInformation);
2478 if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
2479 &RequestedReplyLength, sizeof(RequestedReplyLength),
2480 &SetupInformation, sizeof(SetupInformation))
2481 != sizeof(SetupInformation))
2482 return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
2483 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2484 HostAdapter->SynchronousOffset[TargetID] =
2485 (TargetID < 8
2486 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
2487 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
2488 if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
2489 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2490 HostAdapter->TargetFlags[TargetID].WideTransfersActive =
2491 (TargetID < 8
2492 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
2493 ? true : false)
2494 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
2495 ? true : false));
2497 Issue the Inquire Synchronous Period command.
2499 if (HostAdapter->FirmwareVersion[0] >= '3')
2501 RequestedReplyLength = sizeof(SynchronousPeriod);
2502 if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
2503 &RequestedReplyLength, sizeof(RequestedReplyLength),
2504 &SynchronousPeriod, sizeof(SynchronousPeriod))
2505 != sizeof(SynchronousPeriod))
2506 return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
2507 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2508 HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
2510 else
2511 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2512 if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
2513 HostAdapter->SynchronousPeriod[TargetID] =
2514 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
2515 .TransferPeriod;
2517 Indicate the Target Device Inquiry completed successfully.
2519 return true;
2524 BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible
2525 through Host Adapter.
2528 static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T
2529 *HostAdapter)
2531 int TargetID;
2533 Inhibit the Target Device Inquiry and Reporting if requested.
2535 if (BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
2536 HostAdapter->DriverOptions != NULL &&
2537 HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
2538 return;
2540 Report on the Target Devices found.
2542 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2544 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
2545 if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported)
2547 int SynchronousTransferRate = 0;
2548 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2550 boolean WideTransfersActive;
2551 FlashPoint_InquireTargetInfo(
2552 HostAdapter->CardHandle, TargetID,
2553 &HostAdapter->SynchronousPeriod[TargetID],
2554 &HostAdapter->SynchronousOffset[TargetID],
2555 &WideTransfersActive);
2556 TargetFlags->WideTransfersActive = WideTransfersActive;
2558 else if (TargetFlags->WideTransfersSupported &&
2559 (HostAdapter->WidePermitted & (1 << TargetID)) &&
2560 strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0)
2561 TargetFlags->WideTransfersActive = true;
2562 if (HostAdapter->SynchronousPeriod[TargetID] > 0)
2563 SynchronousTransferRate =
2564 100000 / HostAdapter->SynchronousPeriod[TargetID];
2565 if (TargetFlags->WideTransfersActive)
2566 SynchronousTransferRate <<= 1;
2567 if (SynchronousTransferRate >= 9950)
2569 SynchronousTransferRate = (SynchronousTransferRate + 50) / 100;
2570 BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
2571 "%d.%01d MB/sec, offset %d\n",
2572 HostAdapter, TargetID,
2573 HostAdapter->QueueDepth[TargetID],
2574 (TargetFlags->WideTransfersActive ? "Wide " : ""),
2575 SynchronousTransferRate / 10,
2576 SynchronousTransferRate % 10,
2577 HostAdapter->SynchronousOffset[TargetID]);
2579 else if (SynchronousTransferRate > 0)
2581 SynchronousTransferRate = (SynchronousTransferRate + 5) / 10;
2582 BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
2583 "%d.%02d MB/sec, offset %d\n",
2584 HostAdapter, TargetID,
2585 HostAdapter->QueueDepth[TargetID],
2586 (TargetFlags->WideTransfersActive ? "Wide " : ""),
2587 SynchronousTransferRate / 100,
2588 SynchronousTransferRate % 100,
2589 HostAdapter->SynchronousOffset[TargetID]);
2591 else BusLogic_Info("Target %d: Queue Depth %d, Asynchronous\n",
2592 HostAdapter, TargetID,
2593 HostAdapter->QueueDepth[TargetID]);
2594 TargetFlags->TargetInfoReported = true;
2601 BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
2602 structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
2603 SCSI Host structure are intentionally left uninitialized, as this driver
2604 handles acquisition and release of these resources explicitly, as well as
2605 ensuring exclusive access to the Host Adapter hardware and data structures
2606 through explicit acquisition and release of the Host Adapter's Lock.
2609 static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
2610 *HostAdapter,
2611 SCSI_Host_T *Host)
2613 Host->max_id = HostAdapter->MaxTargetDevices;
2614 Host->max_lun = HostAdapter->MaxLogicalUnits;
2615 Host->max_channel = 0;
2616 Host->unique_id = HostAdapter->IO_Address;
2617 Host->this_id = HostAdapter->SCSI_ID;
2618 Host->can_queue = HostAdapter->DriverQueueDepth;
2619 Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
2620 Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
2621 Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
2626 BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based
2627 on the Host Adapter's Total Queue Depth and the number, type, speed, and
2628 capabilities of the Target Devices. When called for the last Host Adapter,
2629 it reports on the Target Device Information for all BusLogic Host Adapters
2630 since all the Target Devices have now been probed.
2633 static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host,
2634 SCSI_Device_T *DeviceList)
2636 BusLogic_HostAdapter_T *HostAdapter =
2637 (BusLogic_HostAdapter_T *) Host->hostdata;
2638 int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0;
2639 int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0;
2640 int AllocatedQueueDepth = 0;
2641 SCSI_Device_T *Device;
2642 int TargetID;
2643 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2644 if (HostAdapter->TargetFlags[TargetID].TargetExists)
2646 int QueueDepth = HostAdapter->QueueDepth[TargetID];
2647 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
2648 (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
2650 TaggedDeviceCount++;
2651 if (QueueDepth == 0) AutomaticTaggedDeviceCount++;
2653 else
2655 UntaggedDeviceCount++;
2656 if (QueueDepth == 0 ||
2657 QueueDepth > HostAdapter->UntaggedQueueDepth)
2659 QueueDepth = HostAdapter->UntaggedQueueDepth;
2660 HostAdapter->QueueDepth[TargetID] = QueueDepth;
2663 AllocatedQueueDepth += QueueDepth;
2664 if (QueueDepth == 1)
2665 HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
2667 HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount;
2668 if (AutomaticTaggedDeviceCount > 0)
2670 AutomaticTaggedQueueDepth =
2671 (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth)
2672 / AutomaticTaggedDeviceCount;
2673 if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth)
2674 AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
2675 if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth)
2676 AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth;
2677 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2678 if (HostAdapter->TargetFlags[TargetID].TargetExists &&
2679 HostAdapter->QueueDepth[TargetID] == 0)
2681 AllocatedQueueDepth += AutomaticTaggedQueueDepth;
2682 HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth;
2685 for (Device = DeviceList; Device != NULL; Device = Device->next)
2686 if (Device->host == Host)
2687 Device->queue_depth = HostAdapter->QueueDepth[Device->id];
2688 /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */
2689 AllocatedQueueDepth += HostAdapter->TargetDeviceCount;
2690 if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth)
2691 AllocatedQueueDepth = HostAdapter->DriverQueueDepth;
2692 BusLogic_CreateAdditionalCCBs(HostAdapter,
2693 AllocatedQueueDepth
2694 - HostAdapter->AllocatedCCBs,
2695 false);
2696 if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
2697 for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
2698 HostAdapter != NULL;
2699 HostAdapter = HostAdapter->Next)
2700 BusLogic_ReportTargetDeviceInfo(HostAdapter);
2705 BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
2706 I/O Addresses where they may be located, initializing, registering, and
2707 reporting the configuration of each BusLogic Host Adapter it finds. It
2708 returns the number of BusLogic Host Adapters successfully initialized and
2709 registered.
2712 int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
2714 int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
2715 BusLogic_HostAdapter_T *PrototypeHostAdapter;
2716 if (BusLogic_ProbeOptions.NoProbe) return 0;
2717 BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *)
2718 kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T),
2719 GFP_ATOMIC);
2720 if (BusLogic_ProbeInfoList == NULL)
2722 BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
2723 return 0;
2725 memset(BusLogic_ProbeInfoList, 0,
2726 BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T));
2727 PrototypeHostAdapter = (BusLogic_HostAdapter_T *)
2728 kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC);
2729 if (PrototypeHostAdapter == NULL)
2731 kfree(BusLogic_ProbeInfoList);
2732 BusLogic_Error("BusLogic: Unable to allocate Prototype "
2733 "Host Adapter\n", NULL);
2734 return 0;
2736 memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
2737 if (BusLogic_Options != NULL)
2738 BusLogic_ParseDriverOptions(BusLogic_Options);
2739 BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
2740 for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
2742 BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
2743 BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
2744 SCSI_Host_T *Host;
2745 if (ProbeInfo->IO_Address == 0) continue;
2746 memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
2747 HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
2748 HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
2749 HostAdapter->IO_Address = ProbeInfo->IO_Address;
2750 HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
2751 HostAdapter->Bus = ProbeInfo->Bus;
2752 HostAdapter->Device = ProbeInfo->Device;
2753 HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
2754 HostAdapter->AddressCount =
2755 BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
2757 Probe the Host Adapter. If unsuccessful, abort further initialization.
2759 if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
2761 Hard Reset the Host Adapter. If unsuccessful, abort further
2762 initialization.
2764 if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
2766 Check the Host Adapter. If unsuccessful, abort further initialization.
2768 if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
2770 Initialize the Driver Options field if provided.
2772 if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
2773 HostAdapter->DriverOptions =
2774 &BusLogic_DriverOptions[DriverOptionsIndex++];
2776 Announce the Driver Version and Date, Author's Name, Copyright Notice,
2777 and Electronic Mail Address.
2779 BusLogic_AnnounceDriver(HostAdapter);
2781 Register usage of the I/O Address range. From this point onward, any
2782 failure will be assumed to be due to a problem with the Host Adapter,
2783 rather than due to having mistakenly identified this port as belonging
2784 to a BusLogic Host Adapter. The I/O Address range will not be
2785 released, thereby preventing it from being incorrectly identified as
2786 any other type of Host Adapter.
2788 request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
2789 "BusLogic");
2791 Register the SCSI Host structure.
2793 Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T));
2794 HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata;
2795 memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T));
2796 HostAdapter->SCSI_Host = Host;
2797 HostAdapter->HostNumber = Host->host_no;
2798 Host->select_queue_depths = BusLogic_SelectQueueDepths;
2800 Add Host Adapter to the end of the list of registered BusLogic
2801 Host Adapters.
2803 BusLogic_RegisterHostAdapter(HostAdapter);
2805 Read the Host Adapter Configuration, Configure the Host Adapter,
2806 Acquire the System Resources necessary to use the Host Adapter, then
2807 Create the Initial CCBs, Initialize the Host Adapter, and finally
2808 perform Target Device Inquiry.
2810 if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
2811 BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
2812 BusLogic_AcquireResources(HostAdapter) &&
2813 BusLogic_CreateInitialCCBs(HostAdapter) &&
2814 BusLogic_InitializeHostAdapter(HostAdapter) &&
2815 BusLogic_TargetDeviceInquiry(HostAdapter))
2818 Initialization has been completed successfully. Release and
2819 re-register usage of the I/O Address range so that the Model
2820 Name of the Host Adapter will appear, and initialize the SCSI
2821 Host structure.
2823 release_region(HostAdapter->IO_Address,
2824 HostAdapter->AddressCount);
2825 request_region(HostAdapter->IO_Address,
2826 HostAdapter->AddressCount,
2827 HostAdapter->FullModelName);
2828 BusLogic_InitializeHostStructure(HostAdapter, Host);
2829 BusLogicHostAdapterCount++;
2831 else
2834 An error occurred during Host Adapter Configuration Querying, Host
2835 Adapter Configuration, Resource Acquisition, CCB Creation, Host
2836 Adapter Initialization, or Target Device Inquiry, so remove Host
2837 Adapter from the list of registered BusLogic Host Adapters, destroy
2838 the CCBs, Release the System Resources, and Unregister the SCSI
2839 Host.
2841 BusLogic_DestroyCCBs(HostAdapter);
2842 BusLogic_ReleaseResources(HostAdapter);
2843 BusLogic_UnregisterHostAdapter(HostAdapter);
2844 scsi_unregister(Host);
2847 kfree(PrototypeHostAdapter);
2848 kfree(BusLogic_ProbeInfoList);
2849 BusLogic_ProbeInfoList = NULL;
2850 return BusLogicHostAdapterCount;
2855 BusLogic_ReleaseHostAdapter releases all resources previously acquired to
2856 support a specific Host Adapter, including the I/O Address range, and
2857 unregisters the BusLogic Host Adapter.
2860 int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
2862 BusLogic_HostAdapter_T *HostAdapter =
2863 (BusLogic_HostAdapter_T *) Host->hostdata;
2865 FlashPoint Host Adapters must first be released by the FlashPoint
2866 SCCB Manager.
2868 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2869 FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
2871 Destroy the CCBs and release any system resources acquired to
2872 support Host Adapter.
2874 BusLogic_DestroyCCBs(HostAdapter);
2875 BusLogic_ReleaseResources(HostAdapter);
2877 Release usage of the I/O Address range.
2879 release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
2881 Remove Host Adapter from the list of registered BusLogic Host Adapters.
2883 BusLogic_UnregisterHostAdapter(HostAdapter);
2884 return 0;
2889 BusLogic_QueueCompletedCCB queues CCB for completion processing.
2892 static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB)
2894 BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
2895 CCB->Status = BusLogic_CCB_Completed;
2896 CCB->Next = NULL;
2897 if (HostAdapter->FirstCompletedCCB == NULL)
2899 HostAdapter->FirstCompletedCCB = CCB;
2900 HostAdapter->LastCompletedCCB = CCB;
2902 else
2904 HostAdapter->LastCompletedCCB->Next = CCB;
2905 HostAdapter->LastCompletedCCB = CCB;
2907 HostAdapter->ActiveCommands[CCB->TargetID]--;
2912 BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
2913 the Host Adapter Status and Target Device Status.
2916 static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
2917 BusLogic_HostAdapterStatus_T
2918 HostAdapterStatus,
2919 BusLogic_TargetDeviceStatus_T
2920 TargetDeviceStatus)
2922 int HostStatus;
2923 switch (HostAdapterStatus)
2925 case BusLogic_CommandCompletedNormally:
2926 case BusLogic_LinkedCommandCompleted:
2927 case BusLogic_LinkedCommandCompletedWithFlag:
2928 HostStatus = DID_OK;
2929 break;
2930 case BusLogic_SCSISelectionTimeout:
2931 HostStatus = DID_TIME_OUT;
2932 break;
2933 case BusLogic_InvalidOutgoingMailboxActionCode:
2934 case BusLogic_InvalidCommandOperationCode:
2935 case BusLogic_InvalidCommandParameter:
2936 BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n",
2937 HostAdapter, HostAdapterStatus);
2938 case BusLogic_DataUnderRun:
2939 case BusLogic_DataOverRun:
2940 case BusLogic_UnexpectedBusFree:
2941 case BusLogic_LinkedCCBhasInvalidLUN:
2942 case BusLogic_AutoRequestSenseFailed:
2943 case BusLogic_TaggedQueuingMessageRejected:
2944 case BusLogic_UnsupportedMessageReceived:
2945 case BusLogic_HostAdapterHardwareFailed:
2946 case BusLogic_TargetDeviceReconnectedImproperly:
2947 case BusLogic_AbortQueueGenerated:
2948 case BusLogic_HostAdapterSoftwareError:
2949 case BusLogic_HostAdapterHardwareTimeoutError:
2950 case BusLogic_SCSIParityErrorDetected:
2951 HostStatus = DID_ERROR;
2952 break;
2953 case BusLogic_InvalidBusPhaseRequested:
2954 case BusLogic_TargetFailedResponseToATN:
2955 case BusLogic_HostAdapterAssertedRST:
2956 case BusLogic_OtherDeviceAssertedRST:
2957 case BusLogic_HostAdapterAssertedBusDeviceReset:
2958 HostStatus = DID_RESET;
2959 break;
2960 default:
2961 BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n",
2962 HostAdapter, HostAdapterStatus);
2963 HostStatus = DID_ERROR;
2964 break;
2966 return (HostStatus << 16) | TargetDeviceStatus;
2971 BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
2972 Incoming Mailbox entries for completion processing.
2975 static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter)
2978 Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
2979 any completed CCBs for further processing. It is essential that for each
2980 CCB and SCSI Command issued, command completion processing is performed
2981 exactly once. Therefore, only Incoming Mailboxes with completion code
2982 Command Completed Without Error, Command Completed With Error, or Command
2983 Aborted At Host Request are saved for completion processing. When an
2984 Incoming Mailbox has a completion code of Aborted Command Not Found, the
2985 CCB had already completed or been aborted before the current Abort request
2986 was processed, and so completion processing has already occurred and no
2987 further action should be taken.
2989 BusLogic_IncomingMailbox_T *NextIncomingMailbox =
2990 HostAdapter->NextIncomingMailbox;
2991 BusLogic_CompletionCode_T CompletionCode;
2992 while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
2993 BusLogic_IncomingMailboxFree)
2995 BusLogic_CCB_T *CCB = (BusLogic_CCB_T *)
2996 Bus_to_Virtual(NextIncomingMailbox->CCB);
2997 if (CompletionCode != BusLogic_AbortedCommandNotFound)
2999 if (CCB->Status == BusLogic_CCB_Active ||
3000 CCB->Status == BusLogic_CCB_Reset)
3003 Save the Completion Code for this CCB and queue the CCB
3004 for completion processing.
3006 CCB->CompletionCode = CompletionCode;
3007 BusLogic_QueueCompletedCCB(CCB);
3009 else
3012 If a CCB ever appears in an Incoming Mailbox and is not marked
3013 as status Active or Reset, then there is most likely a bug in
3014 the Host Adapter firmware.
3016 BusLogic_Warning("Illegal CCB #%ld status %d in "
3017 "Incoming Mailbox\n", HostAdapter,
3018 CCB->SerialNumber, CCB->Status);
3021 NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
3022 if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
3023 NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
3025 HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
3030 BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
3031 Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
3032 calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
3033 should already have been acquired by the caller.
3036 static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
3038 if (HostAdapter->ProcessCompletedCCBsActive) return;
3039 HostAdapter->ProcessCompletedCCBsActive = true;
3040 while (HostAdapter->FirstCompletedCCB != NULL)
3042 BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
3043 SCSI_Command_T *Command = CCB->Command;
3044 HostAdapter->FirstCompletedCCB = CCB->Next;
3045 if (HostAdapter->FirstCompletedCCB == NULL)
3046 HostAdapter->LastCompletedCCB = NULL;
3048 Process the Completed CCB.
3050 if (CCB->Opcode == BusLogic_BusDeviceReset)
3052 int TargetID = CCB->TargetID;
3053 BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
3054 "%d Completed\n", HostAdapter,
3055 CCB->SerialNumber, TargetID);
3056 BusLogic_IncrementErrorCounter(
3057 &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
3058 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
3059 HostAdapter->CommandsSinceReset[TargetID] = 0;
3060 HostAdapter->LastResetCompleted[TargetID] = jiffies;
3062 Place CCB back on the Host Adapter's free list.
3064 BusLogic_DeallocateCCB(CCB);
3066 Bus Device Reset CCBs have the Command field non-NULL only when a
3067 Bus Device Reset was requested for a Command that did not have a
3068 currently active CCB in the Host Adapter (i.e., a Synchronous
3069 Bus Device Reset), and hence would not have its Completion Routine
3070 called otherwise.
3072 while (Command != NULL)
3074 SCSI_Command_T *NextCommand = Command->reset_chain;
3075 Command->reset_chain = NULL;
3076 Command->result = DID_RESET << 16;
3077 Command->scsi_done(Command);
3078 Command = NextCommand;
3081 Iterate over the CCBs for this Host Adapter performing completion
3082 processing for any CCBs marked as Reset for this Target.
3084 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3085 if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
3087 Command = CCB->Command;
3088 BusLogic_DeallocateCCB(CCB);
3089 HostAdapter->ActiveCommands[TargetID]--;
3090 Command->result = DID_RESET << 16;
3091 Command->scsi_done(Command);
3093 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
3095 else
3098 Translate the Completion Code, Host Adapter Status, and Target
3099 Device Status into a SCSI Subsystem Result Code.
3101 switch (CCB->CompletionCode)
3103 case BusLogic_IncomingMailboxFree:
3104 case BusLogic_AbortedCommandNotFound:
3105 case BusLogic_InvalidCCB:
3106 BusLogic_Warning("CCB #%ld to Target %d Impossible State\n",
3107 HostAdapter, CCB->SerialNumber, CCB->TargetID);
3108 break;
3109 case BusLogic_CommandCompletedWithoutError:
3110 HostAdapter->TargetStatistics[CCB->TargetID]
3111 .CommandsCompleted++;
3112 HostAdapter->TargetFlags[CCB->TargetID]
3113 .CommandSuccessfulFlag = true;
3114 Command->result = DID_OK << 16;
3115 break;
3116 case BusLogic_CommandAbortedAtHostRequest:
3117 BusLogic_Warning("CCB #%ld to Target %d Aborted\n",
3118 HostAdapter, CCB->SerialNumber, CCB->TargetID);
3119 BusLogic_IncrementErrorCounter(
3120 &HostAdapter->TargetStatistics[CCB->TargetID]
3121 .CommandAbortsCompleted);
3122 Command->result = DID_ABORT << 16;
3123 break;
3124 case BusLogic_CommandCompletedWithError:
3125 Command->result =
3126 BusLogic_ComputeResultCode(HostAdapter,
3127 CCB->HostAdapterStatus,
3128 CCB->TargetDeviceStatus);
3129 if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
3131 HostAdapter->TargetStatistics[CCB->TargetID]
3132 .CommandsCompleted++;
3133 if (BusLogic_GlobalOptions.TraceErrors)
3135 int i;
3136 BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
3137 "Adapter Status %02X "
3138 "Target Status %02X\n",
3139 HostAdapter, CCB->SerialNumber,
3140 CCB->TargetID, Command->result,
3141 CCB->HostAdapterStatus,
3142 CCB->TargetDeviceStatus);
3143 BusLogic_Notice("CDB ", HostAdapter);
3144 for (i = 0; i < CCB->CDB_Length; i++)
3145 BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
3146 BusLogic_Notice("\n", HostAdapter);
3147 BusLogic_Notice("Sense ", HostAdapter);
3148 for (i = 0; i < CCB->SenseDataLength; i++)
3149 BusLogic_Notice(" %02X", HostAdapter,
3150 Command->sense_buffer[i]);
3151 BusLogic_Notice("\n", HostAdapter);
3154 break;
3157 When an INQUIRY command completes normally, save the
3158 CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
3159 Wide Data Transfers Supported) bits.
3161 if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 &&
3162 CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
3164 BusLogic_TargetFlags_T *TargetFlags =
3165 &HostAdapter->TargetFlags[CCB->TargetID];
3166 SCSI_Inquiry_T *InquiryResult =
3167 (SCSI_Inquiry_T *) Command->request_buffer;
3168 TargetFlags->TargetExists = true;
3169 TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
3170 TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
3173 Place CCB back on the Host Adapter's free list.
3175 BusLogic_DeallocateCCB(CCB);
3177 Call the SCSI Command Completion Routine.
3179 Command->scsi_done(Command);
3182 HostAdapter->ProcessCompletedCCBsActive = false;
3187 BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
3188 Adapters.
3191 static void BusLogic_InterruptHandler(int IRQ_Channel,
3192 void *DeviceIdentifier,
3193 Registers_T *InterruptRegisters)
3195 BusLogic_HostAdapter_T *HostAdapter =
3196 (BusLogic_HostAdapter_T *) DeviceIdentifier;
3197 ProcessorFlags_T ProcessorFlags;
3199 Acquire exclusive access to Host Adapter.
3201 BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
3203 Handle Interrupts appropriately for each Host Adapter type.
3205 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3207 BusLogic_InterruptRegister_T InterruptRegister;
3209 Read the Host Adapter Interrupt Register.
3211 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
3212 if (InterruptRegister.Bits.InterruptValid)
3215 Acknowledge the interrupt and reset the Host Adapter
3216 Interrupt Register.
3218 BusLogic_InterruptReset(HostAdapter);
3220 Process valid External SCSI Bus Reset and Incoming Mailbox
3221 Loaded Interrupts. Command Complete Interrupts are noted,
3222 and Outgoing Mailbox Available Interrupts are ignored, as
3223 they are never enabled.
3225 if (InterruptRegister.Bits.ExternalBusReset)
3226 HostAdapter->HostAdapterExternalReset = true;
3227 else if (InterruptRegister.Bits.IncomingMailboxLoaded)
3228 BusLogic_ScanIncomingMailboxes(HostAdapter);
3229 else if (InterruptRegister.Bits.CommandComplete)
3230 HostAdapter->HostAdapterCommandCompleted = true;
3233 else
3236 Check if there is a pending interrupt for this Host Adapter.
3238 if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
3239 switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
3241 case FlashPoint_NormalInterrupt:
3242 break;
3243 case FlashPoint_ExternalBusReset:
3244 HostAdapter->HostAdapterExternalReset = true;
3245 break;
3246 case FlashPoint_InternalError:
3247 BusLogic_Warning("Internal FlashPoint Error detected"
3248 " - Resetting Host Adapter\n", HostAdapter);
3249 HostAdapter->HostAdapterInternalError = true;
3250 break;
3254 Process any completed CCBs.
3256 if (HostAdapter->FirstCompletedCCB != NULL)
3257 BusLogic_ProcessCompletedCCBs(HostAdapter);
3259 Reset the Host Adapter if requested.
3261 if (HostAdapter->HostAdapterExternalReset ||
3262 HostAdapter->HostAdapterInternalError)
3264 BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
3265 HostAdapter->HostAdapterExternalReset = false;
3266 HostAdapter->HostAdapterInternalError = false;
3267 scsi_mark_host_reset(HostAdapter->SCSI_Host);
3270 Release exclusive access to Host Adapter.
3272 BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
3277 BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
3278 Mailbox for execution by Host Adapter. The Host Adapter's Lock should
3279 already have been acquired by the caller.
3282 static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T
3283 *HostAdapter,
3284 BusLogic_ActionCode_T ActionCode,
3285 BusLogic_CCB_T *CCB)
3287 BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
3288 NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
3289 if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
3291 CCB->Status = BusLogic_CCB_Active;
3293 The CCB field must be written before the Action Code field since
3294 the Host Adapter is operating asynchronously and the locking code
3295 does not protect against simultaneous access by the Host Adapter.
3297 NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB);
3298 NextOutgoingMailbox->ActionCode = ActionCode;
3299 BusLogic_StartMailboxCommand(HostAdapter);
3300 if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
3301 NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
3302 HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
3303 if (ActionCode == BusLogic_MailboxStartCommand)
3305 HostAdapter->ActiveCommands[CCB->TargetID]++;
3306 if (CCB->Opcode != BusLogic_BusDeviceReset)
3307 HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
3309 return true;
3311 return false;
3316 BusLogic_QueueCommand creates a CCB for Command and places it into an
3317 Outgoing Mailbox for execution by the associated Host Adapter.
3320 int BusLogic_QueueCommand(SCSI_Command_T *Command,
3321 void (*CompletionRoutine)(SCSI_Command_T *))
3323 BusLogic_HostAdapter_T *HostAdapter =
3324 (BusLogic_HostAdapter_T *) Command->host->hostdata;
3325 BusLogic_TargetFlags_T *TargetFlags =
3326 &HostAdapter->TargetFlags[Command->target];
3327 BusLogic_TargetStatistics_T *TargetStatistics =
3328 HostAdapter->TargetStatistics;
3329 unsigned char *CDB = Command->cmnd;
3330 int CDB_Length = Command->cmd_len;
3331 int TargetID = Command->target;
3332 int LogicalUnit = Command->lun;
3333 void *BufferPointer = Command->request_buffer;
3334 int BufferLength = Command->request_bufflen;
3335 int SegmentCount = Command->use_sg;
3336 ProcessorFlags_T ProcessorFlags;
3337 BusLogic_CCB_T *CCB;
3339 SCSI REQUEST_SENSE commands will be executed automatically by the Host
3340 Adapter for any errors, so they should not be executed explicitly unless
3341 the Sense Data is zero indicating that no error occurred.
3343 if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
3345 Command->result = DID_OK << 16;
3346 CompletionRoutine(Command);
3347 return 0;
3350 Acquire exclusive access to Host Adapter.
3352 BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3354 Allocate a CCB from the Host Adapter's free list. In the unlikely event
3355 that there are none available and memory allocation fails, wait 1 second
3356 and try again. If that fails, the Host Adapter is probably hung so signal
3357 an error as a Host Adapter Hard Reset should be initiated soon.
3359 CCB = BusLogic_AllocateCCB(HostAdapter);
3360 if (CCB == NULL)
3362 BusLogic_Delay(1);
3363 CCB = BusLogic_AllocateCCB(HostAdapter);
3364 if (CCB == NULL)
3366 Command->result = DID_ERROR << 16;
3367 CompletionRoutine(Command);
3368 goto Done;
3372 Initialize the fields in the BusLogic Command Control Block (CCB).
3374 if (SegmentCount == 0)
3376 CCB->Opcode = BusLogic_InitiatorCCB;
3377 CCB->DataLength = BufferLength;
3378 CCB->DataPointer = Virtual_to_Bus(BufferPointer);
3380 else
3382 SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer;
3383 int Segment;
3384 CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
3385 CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T);
3386 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3387 CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList);
3388 else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
3389 for (Segment = 0; Segment < SegmentCount; Segment++)
3391 CCB->ScatterGatherList[Segment].SegmentByteCount =
3392 ScatterList[Segment].length;
3393 CCB->ScatterGatherList[Segment].SegmentDataPointer =
3394 Virtual_to_Bus(ScatterList[Segment].address);
3397 switch (CDB[0])
3399 case READ_6:
3400 case READ_10:
3401 CCB->DataDirection = BusLogic_DataInLengthChecked;
3402 TargetStatistics[TargetID].ReadCommands++;
3403 BusLogic_IncrementByteCounter(
3404 &TargetStatistics[TargetID].TotalBytesRead, BufferLength);
3405 BusLogic_IncrementSizeBucket(
3406 TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
3407 break;
3408 case WRITE_6:
3409 case WRITE_10:
3410 CCB->DataDirection = BusLogic_DataOutLengthChecked;
3411 TargetStatistics[TargetID].WriteCommands++;
3412 BusLogic_IncrementByteCounter(
3413 &TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
3414 BusLogic_IncrementSizeBucket(
3415 TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
3416 break;
3417 default:
3418 CCB->DataDirection = BusLogic_UncheckedDataTransfer;
3419 break;
3421 CCB->CDB_Length = CDB_Length;
3422 CCB->SenseDataLength = sizeof(Command->sense_buffer);
3423 CCB->HostAdapterStatus = 0;
3424 CCB->TargetDeviceStatus = 0;
3425 CCB->TargetID = TargetID;
3426 CCB->LogicalUnit = LogicalUnit;
3427 CCB->TagEnable = false;
3428 CCB->LegacyTagEnable = false;
3430 BusLogic recommends that after a Reset the first couple of commands that
3431 are sent to a Target Device be sent in a non Tagged Queue fashion so that
3432 the Host Adapter and Target Device can establish Synchronous and Wide
3433 Transfer before Queue Tag messages can interfere with the Synchronous and
3434 Wide Negotiation messages. By waiting to enable Tagged Queuing until after
3435 the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
3436 assured that after a Reset any pending commands are requeued before Tagged
3437 Queuing is enabled and that the Tagged Queuing message will not occur while
3438 the partition table is being printed. In addition, some devices do not
3439 properly handle the transition from non-tagged to tagged commands, so it is
3440 necessary to wait until there are no pending commands for a target device
3441 before queuing tagged commands.
3443 if (HostAdapter->CommandsSinceReset[TargetID]++ >=
3444 BusLogic_MaxTaggedQueueDepth &&
3445 !TargetFlags->TaggedQueuingActive &&
3446 HostAdapter->ActiveCommands[TargetID] == 0 &&
3447 TargetFlags->TaggedQueuingSupported &&
3448 (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
3450 TargetFlags->TaggedQueuingActive = true;
3451 BusLogic_Notice("Tagged Queuing now active for Target %d\n",
3452 HostAdapter, TargetID);
3454 if (TargetFlags->TaggedQueuingActive)
3456 BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
3458 When using Tagged Queuing with Simple Queue Tags, it appears that disk
3459 drive controllers do not guarantee that a queued command will not
3460 remain in a disconnected state indefinitely if commands that read or
3461 write nearer the head position continue to arrive without interruption.
3462 Therefore, for each Target Device this driver keeps track of the last
3463 time either the queue was empty or an Ordered Queue Tag was issued. If
3464 more than 4 seconds (one fifth of the 20 second disk timeout) have
3465 elapsed since this last sequence point, this command will be issued
3466 with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
3467 the Target Device to complete all previously queued commands before
3468 this command may be executed.
3470 if (HostAdapter->ActiveCommands[TargetID] == 0)
3471 HostAdapter->LastSequencePoint[TargetID] = jiffies;
3472 else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
3474 HostAdapter->LastSequencePoint[TargetID] = jiffies;
3475 QueueTag = BusLogic_OrderedQueueTag;
3477 if (HostAdapter->ExtendedLUNSupport)
3479 CCB->TagEnable = true;
3480 CCB->QueueTag = QueueTag;
3482 else
3484 CCB->LegacyTagEnable = true;
3485 CCB->LegacyQueueTag = QueueTag;
3488 memcpy(CCB->CDB, CDB, CDB_Length);
3489 CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer);
3490 CCB->Command = Command;
3491 Command->scsi_done = CompletionRoutine;
3492 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3495 Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI
3496 Subsystem should not attempt to queue more commands than can be placed
3497 in Outgoing Mailboxes, so there should always be one free. In the
3498 unlikely event that there are none available, wait 1 second and try
3499 again. If that fails, the Host Adapter is probably hung so signal an
3500 error as a Host Adapter Hard Reset should be initiated soon.
3502 if (!BusLogic_WriteOutgoingMailbox(
3503 HostAdapter, BusLogic_MailboxStartCommand, CCB))
3505 BusLogic_Warning("Unable to write Outgoing Mailbox - "
3506 "Pausing for 1 second\n", HostAdapter);
3507 BusLogic_Delay(1);
3508 if (!BusLogic_WriteOutgoingMailbox(
3509 HostAdapter, BusLogic_MailboxStartCommand, CCB))
3511 BusLogic_Warning("Still unable to write Outgoing Mailbox - "
3512 "Host Adapter Dead?\n", HostAdapter);
3513 BusLogic_DeallocateCCB(CCB);
3514 Command->result = DID_ERROR << 16;
3515 Command->scsi_done(Command);
3519 else
3522 Call the FlashPoint SCCB Manager to start execution of the CCB.
3524 CCB->Status = BusLogic_CCB_Active;
3525 HostAdapter->ActiveCommands[TargetID]++;
3526 TargetStatistics[TargetID].CommandsAttempted++;
3527 FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
3529 The Command may have already completed and BusLogic_QueueCompletedCCB
3530 been called, or it may still be pending.
3532 if (CCB->Status == BusLogic_CCB_Completed)
3533 BusLogic_ProcessCompletedCCBs(HostAdapter);
3536 Release exclusive access to Host Adapter.
3538 Done:
3539 BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3540 return 0;
3545 BusLogic_AbortCommand aborts Command if possible.
3548 int BusLogic_AbortCommand(SCSI_Command_T *Command)
3550 BusLogic_HostAdapter_T *HostAdapter =
3551 (BusLogic_HostAdapter_T *) Command->host->hostdata;
3552 int TargetID = Command->target;
3553 ProcessorFlags_T ProcessorFlags;
3554 BusLogic_CCB_T *CCB;
3555 int Result;
3556 BusLogic_IncrementErrorCounter(
3557 &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
3559 Acquire exclusive access to Host Adapter.
3561 BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3563 If this Command has already completed, then no Abort is necessary.
3565 if (Command->serial_number != Command->serial_number_at_timeout)
3567 BusLogic_Warning("Unable to Abort Command to Target %d - "
3568 "Already Completed\n", HostAdapter, TargetID);
3569 Result = SCSI_ABORT_NOT_RUNNING;
3570 goto Done;
3573 Attempt to find an Active CCB for this Command. If no Active CCB for this
3574 Command is found, then no Abort is necessary.
3576 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3577 if (CCB->Command == Command) break;
3578 if (CCB == NULL)
3580 BusLogic_Warning("Unable to Abort Command to Target %d - "
3581 "No CCB Found\n", HostAdapter, TargetID);
3582 Result = SCSI_ABORT_NOT_RUNNING;
3583 goto Done;
3585 else if (CCB->Status == BusLogic_CCB_Completed)
3587 BusLogic_Warning("Unable to Abort Command to Target %d - "
3588 "CCB Completed\n", HostAdapter, TargetID);
3589 Result = SCSI_ABORT_NOT_RUNNING;
3590 goto Done;
3592 else if (CCB->Status == BusLogic_CCB_Reset)
3594 BusLogic_Warning("Unable to Abort Command to Target %d - "
3595 "CCB Reset\n", HostAdapter, TargetID);
3596 Result = SCSI_ABORT_PENDING;
3597 goto Done;
3599 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3602 Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx
3603 do not generate Abort Tag messages, but only generate the non-tagged
3604 Abort message. Since non-tagged commands are not sent by the Host
3605 Adapter until the queue of outstanding tagged commands has completed,
3606 and the Abort message is treated as a non-tagged command, it is
3607 effectively impossible to abort commands when Tagged Queuing is active.
3608 Firmware version 5.xx does generate Abort Tag messages, so it is
3609 possible to abort commands when Tagged Queuing is active.
3611 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
3612 HostAdapter->FirmwareVersion[0] < '5')
3614 BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
3615 "Abort Tag Not Supported\n",
3616 HostAdapter, CCB->SerialNumber, TargetID);
3617 Result = SCSI_ABORT_SNOOZE;
3619 else if (BusLogic_WriteOutgoingMailbox(
3620 HostAdapter, BusLogic_MailboxAbortCommand, CCB))
3622 BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
3623 HostAdapter, CCB->SerialNumber, TargetID);
3624 BusLogic_IncrementErrorCounter(
3625 &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3626 Result = SCSI_ABORT_PENDING;
3628 else
3630 BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
3631 "No Outgoing Mailboxes\n",
3632 HostAdapter, CCB->SerialNumber, TargetID);
3633 Result = SCSI_ABORT_BUSY;
3636 else
3639 Call the FlashPoint SCCB Manager to abort execution of the CCB.
3641 BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
3642 HostAdapter, CCB->SerialNumber, TargetID);
3643 BusLogic_IncrementErrorCounter(
3644 &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3645 FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
3647 The Abort may have already been completed and
3648 BusLogic_QueueCompletedCCB been called, or it
3649 may still be pending.
3651 Result = SCSI_ABORT_PENDING;
3652 if (CCB->Status == BusLogic_CCB_Completed)
3654 BusLogic_ProcessCompletedCCBs(HostAdapter);
3655 Result = SCSI_ABORT_SUCCESS;
3659 Release exclusive access to Host Adapter.
3661 Done:
3662 BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3663 return Result;
3668 BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
3669 currently executing SCSI Commands as having been Reset.
3672 static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
3673 SCSI_Command_T *Command,
3674 unsigned int ResetFlags)
3676 ProcessorFlags_T ProcessorFlags;
3677 BusLogic_CCB_T *CCB;
3678 int TargetID, Result;
3679 boolean HardReset;
3680 if (HostAdapter->HostAdapterExternalReset)
3682 BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
3683 HardReset = false;
3685 else if (HostAdapter->HostAdapterInternalError)
3687 BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
3688 HardReset = true;
3690 else
3692 BusLogic_IncrementErrorCounter(
3693 &HostAdapter->TargetStatistics[Command->target]
3694 .HostAdapterResetsRequested);
3695 HardReset = true;
3698 Acquire exclusive access to Host Adapter.
3700 BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3702 If this is an Asynchronous Reset and this Command has already completed,
3703 then no Reset is necessary.
3705 if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
3707 TargetID = Command->target;
3708 if (Command->serial_number != Command->serial_number_at_timeout)
3710 BusLogic_Warning("Unable to Reset Command to Target %d - "
3711 "Already Completed or Reset\n",
3712 HostAdapter, TargetID);
3713 Result = SCSI_RESET_NOT_RUNNING;
3714 goto Done;
3716 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3717 if (CCB->Command == Command) break;
3718 if (CCB == NULL)
3720 BusLogic_Warning("Unable to Reset Command to Target %d - "
3721 "No CCB Found\n", HostAdapter, TargetID);
3722 Result = SCSI_RESET_NOT_RUNNING;
3723 goto Done;
3725 else if (CCB->Status == BusLogic_CCB_Completed)
3727 BusLogic_Warning("Unable to Reset Command to Target %d - "
3728 "CCB Completed\n", HostAdapter, TargetID);
3729 Result = SCSI_RESET_NOT_RUNNING;
3730 goto Done;
3732 else if (CCB->Status == BusLogic_CCB_Reset &&
3733 HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL)
3735 BusLogic_Warning("Unable to Reset Command to Target %d - "
3736 "Reset Pending\n", HostAdapter, TargetID);
3737 Result = SCSI_RESET_PENDING;
3738 goto Done;
3741 if (Command == NULL)
3743 if (HostAdapter->HostAdapterInternalError)
3744 BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n",
3745 HostAdapter, HostAdapter->FullModelName);
3746 else BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n",
3747 HostAdapter, HostAdapter->FullModelName);
3749 else
3751 BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter,
3752 HostAdapter->FullModelName, Command->target);
3753 BusLogic_IncrementErrorCounter(
3754 &HostAdapter->TargetStatistics[Command->target]
3755 .HostAdapterResetsAttempted);
3758 Attempt to Reset and Reinitialize the Host Adapter.
3760 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
3761 BusLogic_InitializeHostAdapter(HostAdapter)))
3763 BusLogic_Error("Resetting %s Failed\n", HostAdapter,
3764 HostAdapter->FullModelName);
3765 Result = SCSI_RESET_ERROR;
3766 goto Done;
3768 if (Command != NULL)
3769 BusLogic_IncrementErrorCounter(
3770 &HostAdapter->TargetStatistics[Command->target]
3771 .HostAdapterResetsCompleted);
3773 Mark all currently executing CCBs as having been Reset.
3775 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3776 if (CCB->Status == BusLogic_CCB_Active)
3777 CCB->Status = BusLogic_CCB_Reset;
3779 Wait a few seconds between the Host Adapter Hard Reset which initiates
3780 a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
3781 confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
3782 Note that a timer interrupt may occur here, but all active CCBs have
3783 already been marked Reset and so a reentrant call will return Pending.
3785 if (HardReset)
3786 BusLogic_Delay(HostAdapter->BusSettleTime);
3788 If this is a Synchronous Reset, perform completion processing for
3789 the Command being Reset.
3791 if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3793 Command->result = DID_RESET << 16;
3794 Command->scsi_done(Command);
3797 Perform completion processing for all CCBs marked as Reset.
3799 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3800 if (CCB->Status == BusLogic_CCB_Reset)
3802 Command = CCB->Command;
3803 BusLogic_DeallocateCCB(CCB);
3804 while (Command != NULL)
3806 SCSI_Command_T *NextCommand = Command->reset_chain;
3807 Command->reset_chain = NULL;
3808 Command->result = DID_RESET << 16;
3809 Command->scsi_done(Command);
3810 Command = NextCommand;
3813 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
3815 HostAdapter->LastResetAttempted[TargetID] = jiffies;
3816 HostAdapter->LastResetCompleted[TargetID] = jiffies;
3818 Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
3820 Release exclusive access to Host Adapter.
3822 Done:
3823 BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3824 return Result;
3829 BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target
3830 Device associated with Command.
3833 static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
3834 SCSI_Command_T *Command,
3835 unsigned int ResetFlags)
3837 int TargetID = Command->target;
3838 BusLogic_CCB_T *CCB, *XCCB;
3839 ProcessorFlags_T ProcessorFlags;
3840 int Result = -1;
3841 BusLogic_IncrementErrorCounter(
3842 &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
3844 Acquire exclusive access to Host Adapter.
3846 BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3848 If this is an Asynchronous Reset and this Command has already completed,
3849 then no Reset is necessary.
3851 if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
3853 if (Command->serial_number != Command->serial_number_at_timeout)
3855 BusLogic_Warning("Unable to Reset Command to Target %d - "
3856 "Already Completed\n", HostAdapter, TargetID);
3857 Result = SCSI_RESET_NOT_RUNNING;
3858 goto Done;
3860 for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3861 if (CCB->Command == Command) break;
3862 if (CCB == NULL)
3864 BusLogic_Warning("Unable to Reset Command to Target %d - "
3865 "No CCB Found\n", HostAdapter, TargetID);
3866 Result = SCSI_RESET_NOT_RUNNING;
3867 goto Done;
3869 else if (CCB->Status == BusLogic_CCB_Completed)
3871 BusLogic_Warning("Unable to Reset Command to Target %d - "
3872 "CCB Completed\n", HostAdapter, TargetID);
3873 Result = SCSI_RESET_NOT_RUNNING;
3874 goto Done;
3876 else if (CCB->Status == BusLogic_CCB_Reset)
3878 BusLogic_Warning("Unable to Reset Command to Target %d - "
3879 "Reset Pending\n", HostAdapter, TargetID);
3880 Result = SCSI_RESET_PENDING;
3881 goto Done;
3883 else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
3885 BusLogic_Warning("Bus Device Reset already pending to Target %d\n",
3886 HostAdapter, TargetID);
3887 goto Done;
3891 If this is a Synchronous Reset and a Bus Device Reset is already pending
3892 for this Target Device, do not send a second one. Add this Command to
3893 the list of Commands for which completion processing must be performed
3894 when the Bus Device Reset CCB completes.
3896 if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3897 if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL)
3899 Command->reset_chain = CCB->Command;
3900 CCB->Command = Command;
3901 BusLogic_Warning("Unable to Reset Command to Target %d - "
3902 "Reset Pending\n", HostAdapter, TargetID);
3903 Result = SCSI_RESET_PENDING;
3904 goto Done;
3906 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3909 MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as
3910 a non-tagged command. Since non-tagged commands are not sent by the
3911 Host Adapter until the queue of outstanding tagged commands has
3912 completed, it is effectively impossible to send a Bus Device Reset
3913 while there are tagged commands outstanding. Therefore, in that case a
3914 full Host Adapter Hard Reset and SCSI Bus Reset must be done.
3916 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
3917 HostAdapter->ActiveCommands[TargetID] > 0 &&
3918 HostAdapter->FirmwareVersion[0] < '5')
3919 goto Done;
3922 Allocate a CCB from the Host Adapter's free list. In the unlikely event
3923 that there are none available and memory allocation fails, attempt a full
3924 Host Adapter Hard Reset and SCSI Bus Reset.
3926 CCB = BusLogic_AllocateCCB(HostAdapter);
3927 if (CCB == NULL) goto Done;
3928 BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n",
3929 HostAdapter, CCB->SerialNumber, TargetID);
3930 CCB->Opcode = BusLogic_BusDeviceReset;
3931 CCB->TargetID = TargetID;
3933 For Synchronous Resets, arrange for the interrupt handler to perform
3934 completion processing for the Command being Reset.
3936 if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3938 Command->reset_chain = NULL;
3939 CCB->Command = Command;
3941 if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3944 Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
3945 If sending a Bus Device Reset is impossible, attempt a full Host
3946 Adapter Hard Reset and SCSI Bus Reset.
3948 if (!(BusLogic_WriteOutgoingMailbox(
3949 HostAdapter, BusLogic_MailboxStartCommand, CCB)))
3951 BusLogic_Warning("Unable to write Outgoing Mailbox for "
3952 "Bus Device Reset\n", HostAdapter);
3953 BusLogic_DeallocateCCB(CCB);
3954 goto Done;
3957 else
3960 Call the FlashPoint SCCB Manager to start execution of the CCB.
3962 CCB->Status = BusLogic_CCB_Active;
3963 HostAdapter->ActiveCommands[TargetID]++;
3964 FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
3967 If there is a currently executing CCB in the Host Adapter for this Command
3968 (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
3969 made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
3970 If there is no active CCB for this Command (i.e. this is a Synchronous
3971 Reset), then the Bus Device Reset CCB's Command field will have been set
3972 to the Command so that the interrupt for the completion of the Bus Device
3973 Reset can call the Completion Routine for the Command. On successful
3974 execution of a Bus Device Reset, older firmware versions did return the
3975 pending CCBs with the appropriate completion code, but more recent firmware
3976 versions only return the Bus Device Reset CCB itself. This driver handles
3977 both cases by marking all the currently executing CCBs to this Target
3978 Device as Reset. When the Bus Device Reset CCB is processed by the
3979 interrupt handler, any remaining CCBs marked as Reset will have completion
3980 processing performed.
3982 BusLogic_IncrementErrorCounter(
3983 &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
3984 HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
3985 HostAdapter->LastResetAttempted[TargetID] = jiffies;
3986 for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll)
3987 if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID)
3988 XCCB->Status = BusLogic_CCB_Reset;
3990 FlashPoint Host Adapters may have already completed the Bus Device
3991 Reset and BusLogic_QueueCompletedCCB been called, or it may still be
3992 pending.
3994 Result = SCSI_RESET_PENDING;
3995 if (BusLogic_FlashPointHostAdapterP(HostAdapter))
3996 if (CCB->Status == BusLogic_CCB_Completed)
3998 BusLogic_ProcessCompletedCCBs(HostAdapter);
3999 Result = SCSI_RESET_SUCCESS;
4002 If a Bus Device Reset was not possible for some reason, force a full
4003 Host Adapter Hard Reset and SCSI Bus Reset.
4005 Done:
4006 if (Result < 0)
4007 Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4009 Release exclusive access to Host Adapter.
4011 BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
4012 return Result;
4017 BusLogic_ResetCommand takes appropriate action to reset Command.
4020 int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags)
4022 BusLogic_HostAdapter_T *HostAdapter =
4023 (BusLogic_HostAdapter_T *) Command->host->hostdata;
4024 int TargetID = Command->target;
4025 BusLogic_ErrorRecoveryStrategy_T
4026 ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID];
4028 Disable Tagged Queuing if it is active for this Target Device and if
4029 it has been less than 10 minutes since the last reset occurred, or since
4030 the system was initialized if no prior resets have occurred.
4032 if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
4033 jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ)
4035 HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
4036 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
4037 BusLogic_Warning("Tagged Queuing now disabled for Target %d\n",
4038 HostAdapter, TargetID);
4040 switch (ErrorRecoveryStrategy)
4042 case BusLogic_ErrorRecovery_Default:
4043 if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET)
4044 return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4045 else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
4046 return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4047 /* Fall through to Bus Device Reset case. */
4048 case BusLogic_ErrorRecovery_BusDeviceReset:
4050 The Bus Device Reset Error Recovery Strategy only graduates to a Hard
4051 Reset when no commands have completed successfully since the last Bus
4052 Device Reset and it has been at least 100 milliseconds. This prevents
4053 a sequence of commands that all timeout together from immediately
4054 forcing a Hard Reset before the Bus Device Reset has had a chance to
4055 clear the error condition.
4057 if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag ||
4058 jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10)
4060 HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
4061 return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags);
4063 /* Fall through to Hard Reset case. */
4064 case BusLogic_ErrorRecovery_HardReset:
4065 return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4066 case BusLogic_ErrorRecovery_None:
4067 BusLogic_Warning("Error Recovery for Target %d Suppressed\n",
4068 HostAdapter, TargetID);
4069 break;
4071 return SCSI_RESET_PUNT;
4076 BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
4077 Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
4078 the appropriate number of cylinders so as not to exceed drive capacity. In
4079 order for disks equal to or larger than 1 GB to be addressable by the BIOS
4080 without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
4081 may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
4082 series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
4083 series MultiMaster Host Adapters. With Extended Translation enabled, drives
4084 between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
4085 heads and 32 sectors, and drives above 2 GB inclusive are given a disk
4086 geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
4087 Extended Translation setting does not match the geometry in the partition
4088 table, then the translation inferred from the partition table will be used by
4089 the BIOS, and a warning may be displayed.
4092 int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
4093 int *Parameters)
4095 BusLogic_HostAdapter_T *HostAdapter =
4096 (BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
4097 BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
4098 struct buffer_head *BufferHead;
4099 if (HostAdapter->ExtendedTranslationEnabled &&
4100 Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
4102 if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
4104 DiskParameters->Heads = 255;
4105 DiskParameters->Sectors = 63;
4107 else
4109 DiskParameters->Heads = 128;
4110 DiskParameters->Sectors = 32;
4113 else
4115 DiskParameters->Heads = 64;
4116 DiskParameters->Sectors = 32;
4118 DiskParameters->Cylinders =
4119 Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
4121 Attempt to read the first 1024 bytes from the disk device.
4123 BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, 1024);
4124 if (BufferHead == NULL) return 0;
4126 If the boot sector partition table flag is valid, search for a partition
4127 table entry whose end_head matches one of the standard BusLogic geometry
4128 translations (64/32, 128/32, or 255/63).
4130 if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55)
4132 PartitionTable_T *FirstPartitionEntry =
4133 (PartitionTable_T *) (BufferHead->b_data + 0x1BE);
4134 PartitionTable_T *PartitionEntry = FirstPartitionEntry;
4135 int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
4136 unsigned char PartitionEntryEndHead, PartitionEntryEndSector;
4137 for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
4139 PartitionEntryEndHead = PartitionEntry->end_head;
4140 PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
4141 if (PartitionEntryEndHead == 64-1)
4143 DiskParameters->Heads = 64;
4144 DiskParameters->Sectors = 32;
4145 break;
4147 else if (PartitionEntryEndHead == 128-1)
4149 DiskParameters->Heads = 128;
4150 DiskParameters->Sectors = 32;
4151 break;
4153 else if (PartitionEntryEndHead == 255-1)
4155 DiskParameters->Heads = 255;
4156 DiskParameters->Sectors = 63;
4157 break;
4159 PartitionEntry++;
4161 if (PartitionNumber == 4)
4163 PartitionEntryEndHead = FirstPartitionEntry->end_head;
4164 PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
4166 DiskParameters->Cylinders =
4167 Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
4168 if (PartitionNumber < 4 &&
4169 PartitionEntryEndSector == DiskParameters->Sectors)
4171 if (DiskParameters->Cylinders != SavedCylinders)
4172 BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n",
4173 HostAdapter,
4174 DiskParameters->Heads, DiskParameters->Sectors);
4176 else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
4178 BusLogic_Warning("Warning: Partition Table appears to "
4179 "have Geometry %d/%d which is\n", HostAdapter,
4180 PartitionEntryEndHead + 1,
4181 PartitionEntryEndSector);
4182 BusLogic_Warning("not compatible with current BusLogic "
4183 "Host Adapter Geometry %d/%d\n", HostAdapter,
4184 DiskParameters->Heads, DiskParameters->Sectors);
4187 brelse(BufferHead);
4188 return 0;
4193 BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
4196 int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer,
4197 off_t Offset, int BytesAvailable,
4198 int HostNumber, int WriteFlag)
4200 BusLogic_HostAdapter_T *HostAdapter;
4201 BusLogic_TargetStatistics_T *TargetStatistics;
4202 int TargetID, Length;
4203 char *Buffer;
4204 for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
4205 HostAdapter != NULL;
4206 HostAdapter = HostAdapter->Next)
4207 if (HostAdapter->HostNumber == HostNumber) break;
4208 if (HostAdapter == NULL)
4210 BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n",
4211 NULL, HostNumber);
4212 return 0;
4214 TargetStatistics = HostAdapter->TargetStatistics;
4215 if (WriteFlag)
4217 HostAdapter->ExternalHostAdapterResets = 0;
4218 HostAdapter->HostAdapterInternalErrors = 0;
4219 memset(TargetStatistics, 0,
4220 BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T));
4221 return 0;
4223 Buffer = HostAdapter->MessageBuffer;
4224 Length = HostAdapter->MessageBufferLength;
4225 Length += sprintf(&Buffer[Length], "\n\
4226 Current Driver Queue Depth: %d\n\
4227 Currently Allocated CCBs: %d\n",
4228 HostAdapter->DriverQueueDepth,
4229 HostAdapter->AllocatedCCBs);
4230 Length += sprintf(&Buffer[Length], "\n\n\
4231 DATA TRANSFER STATISTICS\n\
4233 Target Tagged Queuing Queue Depth Active Attempted Completed\n\
4234 ====== ============== =========== ====== ========= =========\n");
4235 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4237 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4238 if (!TargetFlags->TargetExists) continue;
4239 Length +=
4240 sprintf(&Buffer[Length], " %2d %s", TargetID,
4241 (TargetFlags->TaggedQueuingSupported
4242 ? (TargetFlags->TaggedQueuingActive
4243 ? " Active"
4244 : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
4245 ? " Permitted" : " Disabled"))
4246 : "Not Supported"));
4247 Length += sprintf(&Buffer[Length],
4248 " %3d %3u %9u %9u\n",
4249 HostAdapter->QueueDepth[TargetID],
4250 HostAdapter->ActiveCommands[TargetID],
4251 TargetStatistics[TargetID].CommandsAttempted,
4252 TargetStatistics[TargetID].CommandsCompleted);
4254 Length += sprintf(&Buffer[Length], "\n\
4255 Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
4256 ====== ============= ============== =================== ===================\n");
4257 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4259 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4260 if (!TargetFlags->TargetExists) continue;
4261 Length +=
4262 sprintf(&Buffer[Length], " %2d %9u %9u", TargetID,
4263 TargetStatistics[TargetID].ReadCommands,
4264 TargetStatistics[TargetID].WriteCommands);
4265 if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
4266 Length +=
4267 sprintf(&Buffer[Length], " %9u%09u",
4268 TargetStatistics[TargetID].TotalBytesRead.Billions,
4269 TargetStatistics[TargetID].TotalBytesRead.Units);
4270 else
4271 Length +=
4272 sprintf(&Buffer[Length], " %9u",
4273 TargetStatistics[TargetID].TotalBytesRead.Units);
4274 if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
4275 Length +=
4276 sprintf(&Buffer[Length], " %9u%09u\n",
4277 TargetStatistics[TargetID].TotalBytesWritten.Billions,
4278 TargetStatistics[TargetID].TotalBytesWritten.Units);
4279 else
4280 Length +=
4281 sprintf(&Buffer[Length], " %9u\n",
4282 TargetStatistics[TargetID].TotalBytesWritten.Units);
4284 Length += sprintf(&Buffer[Length], "\n\
4285 Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
4286 ====== ======= ========= ========= ========= ========= =========\n");
4287 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4289 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4290 if (!TargetFlags->TargetExists) continue;
4291 Length +=
4292 sprintf(&Buffer[Length],
4293 " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
4294 TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
4295 TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
4296 TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
4297 TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
4298 TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
4299 Length +=
4300 sprintf(&Buffer[Length],
4301 " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
4302 TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
4303 TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
4304 TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
4305 TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
4306 TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
4308 Length += sprintf(&Buffer[Length], "\n\
4309 Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
4310 ====== ======= ========= ========= ========= ========= =========\n");
4311 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4313 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4314 if (!TargetFlags->TargetExists) continue;
4315 Length +=
4316 sprintf(&Buffer[Length],
4317 " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
4318 TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
4319 TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
4320 TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
4321 TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
4322 TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
4323 Length +=
4324 sprintf(&Buffer[Length],
4325 " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
4326 TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
4327 TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
4328 TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
4329 TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
4330 TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
4332 Length += sprintf(&Buffer[Length], "\n\n\
4333 ERROR RECOVERY STATISTICS\n\
4335 Command Aborts Bus Device Resets Host Adapter Resets\n\
4336 Target Requested Completed Requested Completed Requested Completed\n\
4337 ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
4338 ====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
4339 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4341 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4342 if (!TargetFlags->TargetExists) continue;
4343 Length +=
4344 sprintf(&Buffer[Length], "\
4345 %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID,
4346 TargetStatistics[TargetID].CommandAbortsRequested,
4347 TargetStatistics[TargetID].CommandAbortsAttempted,
4348 TargetStatistics[TargetID].CommandAbortsCompleted,
4349 TargetStatistics[TargetID].BusDeviceResetsRequested,
4350 TargetStatistics[TargetID].BusDeviceResetsAttempted,
4351 TargetStatistics[TargetID].BusDeviceResetsCompleted,
4352 TargetStatistics[TargetID].HostAdapterResetsRequested,
4353 TargetStatistics[TargetID].HostAdapterResetsAttempted,
4354 TargetStatistics[TargetID].HostAdapterResetsCompleted);
4356 Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n",
4357 HostAdapter->ExternalHostAdapterResets);
4358 Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n",
4359 HostAdapter->HostAdapterInternalErrors);
4360 if (Length >= BusLogic_MessageBufferSize)
4361 BusLogic_Error("Message Buffer length %d exceeds size %d\n",
4362 HostAdapter, Length, BusLogic_MessageBufferSize);
4363 if ((Length -= Offset) <= 0) return 0;
4364 if (Length >= BytesAvailable) Length = BytesAvailable;
4365 *StartPointer = &HostAdapter->MessageBuffer[Offset];
4366 return Length;
4371 BusLogic_Message prints Driver Messages.
4374 static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel,
4375 char *Format,
4376 BusLogic_HostAdapter_T *HostAdapter,
4377 ...)
4379 static char Buffer[BusLogic_LineBufferSize];
4380 static boolean BeginningOfLine = true;
4381 va_list Arguments;
4382 int Length = 0;
4383 va_start(Arguments, HostAdapter);
4384 Length = vsprintf(Buffer, Format, Arguments);
4385 va_end(Arguments);
4386 if (MessageLevel == BusLogic_AnnounceLevel)
4388 static int AnnouncementLines = 0;
4389 strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
4390 Buffer);
4391 HostAdapter->MessageBufferLength += Length;
4392 if (++AnnouncementLines <= 2)
4393 printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
4395 else if (MessageLevel == BusLogic_InfoLevel)
4397 strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
4398 Buffer);
4399 HostAdapter->MessageBufferLength += Length;
4400 if (BeginningOfLine)
4402 if (Buffer[0] != '\n' || Length > 1)
4403 printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
4404 HostAdapter->HostNumber, Buffer);
4406 else printk("%s", Buffer);
4408 else
4410 if (BeginningOfLine)
4412 if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
4413 printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
4414 HostAdapter->HostNumber, Buffer);
4415 else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
4417 else printk("%s", Buffer);
4419 BeginningOfLine = (Buffer[Length-1] == '\n');
4424 BusLogic_ParseKeyword parses an individual option keyword. It returns true
4425 and updates the pointer if the keyword is recognized and false otherwise.
4428 static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
4430 char *Pointer = *StringPointer;
4431 while (*Keyword != '\0')
4433 char StringChar = *Pointer++;
4434 char KeywordChar = *Keyword++;
4435 if (StringChar >= 'A' && StringChar <= 'Z')
4436 StringChar += 'a' - 'Z';
4437 if (KeywordChar >= 'A' && KeywordChar <= 'Z')
4438 KeywordChar += 'a' - 'Z';
4439 if (StringChar != KeywordChar) return false;
4441 *StringPointer = Pointer;
4442 return true;
4447 BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
4448 specifications.
4450 BusLogic Driver Options may be specified either via the Linux Kernel Command
4451 Line or via the Loadable Kernel Module Installation Facility. Driver Options
4452 for multiple host adapters may be specified either by separating the option
4453 strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
4454 command line. Individual option specifications for a single host adapter are
4455 separated by commas. The Probing and Debugging Options apply to all host
4456 adapters whereas the remaining options apply individually only to the
4457 selected host adapter.
4459 The BusLogic Driver Probing Options comprise the following:
4461 IO:<integer>
4463 The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
4464 MultiMaster Host Adapter. If neither "IO:" nor "NoProbeISA" options are
4465 specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
4466 will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134). Multiple
4467 "IO:" options may be specified to precisely determine the I/O Addresses to
4468 be probed, but the probe order will always follow the standard list.
4470 NoProbe
4472 The "NoProbe" option disables all probing and therefore no BusLogic Host
4473 Adapters will be detected.
4475 NoProbeISA
4477 The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
4478 Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
4479 will be detected.
4481 NoProbePCI
4483 The "NoProbePCI" options disables the interrogation of PCI Configuration
4484 Space and therefore only ISA Multimaster Host Adapters will be detected, as
4485 well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
4486 Port set to "Primary" or "Alternate".
4488 NoSortPCI
4490 The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
4491 enumerated in the order provided by the PCI BIOS, ignoring any setting of
4492 the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
4494 MultiMasterFirst
4496 The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
4497 before FlashPoint Host Adapters. By default, if both FlashPoint and PCI
4498 MultiMaster Host Adapters are present, this driver will probe for
4499 FlashPoint Host Adapters first unless the BIOS primary disk is controlled
4500 by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
4501 Adapters will be probed first.
4503 FlashPointFirst
4505 The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
4506 before MultiMaster Host Adapters.
4508 The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
4509 the Queue Depth and whether Tagged Queuing is permitted for each Target
4510 Device (assuming that the Target Device supports Tagged Queuing). The Queue
4511 Depth is the number of SCSI Commands that are allowed to be concurrently
4512 presented for execution (either to the Host Adapter or Target Device). Note
4513 that explicitly enabling Tagged Queuing may lead to problems; the option to
4514 enable or disable Tagged Queuing is provided primarily to allow disabling
4515 Tagged Queuing on Target Devices that do not implement it correctly. The
4516 following options are available:
4518 QueueDepth:<integer>
4520 The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
4521 Target Devices that support Tagged Queuing, as well as the maximum Queue
4522 Depth for devices that do not support Tagged Queuing. If no Queue Depth
4523 option is provided, the Queue Depth will be determined automatically based
4524 on the Host Adapter's Total Queue Depth and the number, type, speed, and
4525 capabilities of the detected Target Devices. For Host Adapters that
4526 require ISA Bounce Buffers, the Queue Depth is automatically set by default
4527 to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
4528 excessive preallocation of DMA Bounce Buffer memory. Target Devices that
4529 do not support Tagged Queuing always have their Queue Depth set to
4530 BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
4531 lower Queue Depth option is provided. A Queue Depth of 1 automatically
4532 disables Tagged Queuing.
4534 QueueDepth:[<integer>,<integer>...]
4536 The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
4537 individually for each Target Device. If an <integer> is omitted, the
4538 associated Target Device will have its Queue Depth selected automatically.
4540 TaggedQueuing:Default
4542 The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
4543 based on the firmware version of the BusLogic Host Adapter and based on
4544 whether the Queue Depth allows queuing multiple commands.
4546 TaggedQueuing:Enable
4548 The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
4549 all Target Devices on this Host Adapter, overriding any limitation that
4550 would otherwise be imposed based on the Host Adapter firmware version.
4552 TaggedQueuing:Disable
4554 The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
4555 for all Target Devices on this Host Adapter.
4557 TaggedQueuing:<Target-Spec>
4559 The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
4560 Tagged Queuing individually for each Target Device. <Target-Spec> is a
4561 sequence of "Y", "N", and "X" characters. "Y" enables Tagged Queuing, "N"
4562 disables Tagged Queuing, and "X" accepts the default based on the firmware
4563 version. The first character refers to Target Device 0, the second to
4564 Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
4565 does not cover all the Target Devices, unspecified characters are assumed
4566 to be "X".
4568 The BusLogic Driver Error Recovery Option allows for explicitly specifying
4569 the Error Recovery action to be performed when BusLogic_ResetCommand is
4570 called due to a SCSI Command failing to complete successfully. The following
4571 options are available:
4573 ErrorRecovery:Default
4575 The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
4576 Reset and Bus Device Reset options based on the recommendation of the SCSI
4577 Subsystem.
4579 ErrorRecovery:HardReset
4581 The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
4582 Adapter Hard Reset which also causes a SCSI Bus Reset.
4584 ErrorRecovery:BusDeviceReset
4586 The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
4587 a Bus Device Reset message to the individual Target Device causing the
4588 error. If Error Recovery is again initiated for this Target Device and no
4589 SCSI Command to this Target Device has completed successfully since the Bus
4590 Device Reset message was sent, then a Hard Reset will be attempted.
4592 ErrorRecovery:None
4594 The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
4595 This option should only be selected if a SCSI Bus Reset or Bus Device Reset
4596 will cause the Target Device or a critical operation to suffer a complete
4597 and unrecoverable failure.
4599 ErrorRecovery:<Target-Spec>
4601 The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
4602 Error Recovery individually for each Target Device. <Target-Spec> is a
4603 sequence of "D", "H", "B", and "N" characters. "D" selects Default, "H"
4604 selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
4605 The first character refers to Target Device 0, the second to Target Device
4606 1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
4607 cover all the possible Target Devices, unspecified characters are assumed
4608 to be "D".
4610 The BusLogic Driver Miscellaneous Options comprise the following:
4612 BusSettleTime:<seconds>
4614 The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
4615 seconds. The Bus Settle Time is the amount of time to wait between a Host
4616 Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
4617 Commands. If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
4619 InhibitTargetInquiry
4621 The "InhibitTargetInquiry" option inhibits the execution of an Inquire
4622 Target Devices or Inquire Installed Devices command on MultiMaster Host
4623 Adapters. This may be necessary with some older Target Devices that do not
4624 respond correctly when Logical Units above 0 are addressed.
4626 The BusLogic Driver Debugging Options comprise the following:
4628 TraceProbe
4630 The "TraceProbe" option enables tracing of Host Adapter Probing.
4632 TraceHardwareReset
4634 The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
4635 Reset.
4637 TraceConfiguration
4639 The "TraceConfiguration" option enables tracing of Host Adapter
4640 Configuration.
4642 TraceErrors
4644 The "TraceErrors" option enables tracing of SCSI Commands that return an
4645 error from the Target Device. The CDB and Sense Data will be printed for
4646 each SCSI Command that fails.
4648 Debug
4650 The "Debug" option enables all debugging options.
4652 The following examples demonstrate setting the Queue Depth for Target Devices
4653 1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
4654 Devices on the second host adapter to 31, and the Bus Settle Time on the
4655 second host adapter to 30 seconds.
4657 Linux Kernel Command Line:
4659 linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
4661 LILO Linux Boot Loader (in /etc/lilo.conf):
4663 append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
4665 INSMOD Loadable Kernel Module Installation Facility:
4667 insmod BusLogic.o \
4668 'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
4670 NOTE: Module Utilities 2.1.71 or later is required for correct parsing
4671 of driver options containing commas.
4675 static void BusLogic_ParseDriverOptions(char *OptionsString)
4677 while (true)
4679 BusLogic_DriverOptions_T *DriverOptions =
4680 &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
4681 int TargetID;
4682 memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T));
4683 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
4684 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4685 BusLogic_ErrorRecovery_Default;
4686 while (*OptionsString != '\0' && *OptionsString != ';')
4688 /* Probing Options. */
4689 if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
4691 BusLogic_IO_Address_T IO_Address =
4692 simple_strtoul(OptionsString, &OptionsString, 0);
4693 BusLogic_ProbeOptions.LimitedProbeISA = true;
4694 switch (IO_Address)
4696 case 0x330:
4697 BusLogic_ProbeOptions.Probe330 = true;
4698 break;
4699 case 0x334:
4700 BusLogic_ProbeOptions.Probe334 = true;
4701 break;
4702 case 0x230:
4703 BusLogic_ProbeOptions.Probe230 = true;
4704 break;
4705 case 0x234:
4706 BusLogic_ProbeOptions.Probe234 = true;
4707 break;
4708 case 0x130:
4709 BusLogic_ProbeOptions.Probe130 = true;
4710 break;
4711 case 0x134:
4712 BusLogic_ProbeOptions.Probe134 = true;
4713 break;
4714 default:
4715 BusLogic_Error("BusLogic: Invalid Driver Options "
4716 "(illegal I/O Address 0x%X)\n",
4717 NULL, IO_Address);
4718 return;
4721 else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
4722 BusLogic_ProbeOptions.NoProbeISA = true;
4723 else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
4724 BusLogic_ProbeOptions.NoProbePCI = true;
4725 else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
4726 BusLogic_ProbeOptions.NoProbe = true;
4727 else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
4728 BusLogic_ProbeOptions.NoSortPCI = true;
4729 else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
4730 BusLogic_ProbeOptions.MultiMasterFirst = true;
4731 else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
4732 BusLogic_ProbeOptions.FlashPointFirst = true;
4733 /* Tagged Queuing Options. */
4734 else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
4735 BusLogic_ParseKeyword(&OptionsString, "QD:["))
4737 for (TargetID = 0;
4738 TargetID < BusLogic_MaxTargetDevices;
4739 TargetID++)
4741 unsigned short QueueDepth =
4742 simple_strtoul(OptionsString, &OptionsString, 0);
4743 if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
4745 BusLogic_Error("BusLogic: Invalid Driver Options "
4746 "(illegal Queue Depth %d)\n",
4747 NULL, QueueDepth);
4748 return;
4750 DriverOptions->QueueDepth[TargetID] = QueueDepth;
4751 if (*OptionsString == ',')
4752 OptionsString++;
4753 else if (*OptionsString == ']')
4754 break;
4755 else
4757 BusLogic_Error("BusLogic: Invalid Driver Options "
4758 "(',' or ']' expected at '%s')\n",
4759 NULL, OptionsString);
4760 return;
4763 if (*OptionsString != ']')
4765 BusLogic_Error("BusLogic: Invalid Driver Options "
4766 "(']' expected at '%s')\n",
4767 NULL, OptionsString);
4768 return;
4770 else OptionsString++;
4772 else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
4773 BusLogic_ParseKeyword(&OptionsString, "QD:"))
4775 unsigned short QueueDepth =
4776 simple_strtoul(OptionsString, &OptionsString, 0);
4777 if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
4779 BusLogic_Error("BusLogic: Invalid Driver Options "
4780 "(illegal Queue Depth %d)\n",
4781 NULL, QueueDepth);
4782 return;
4784 DriverOptions->CommonQueueDepth = QueueDepth;
4785 for (TargetID = 0;
4786 TargetID < BusLogic_MaxTargetDevices;
4787 TargetID++)
4788 DriverOptions->QueueDepth[TargetID] = QueueDepth;
4790 else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
4791 BusLogic_ParseKeyword(&OptionsString, "TQ:"))
4793 if (BusLogic_ParseKeyword(&OptionsString, "Default"))
4795 DriverOptions->TaggedQueuingPermitted = 0x0000;
4796 DriverOptions->TaggedQueuingPermittedMask = 0x0000;
4798 else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
4800 DriverOptions->TaggedQueuingPermitted = 0xFFFF;
4801 DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
4803 else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
4805 DriverOptions->TaggedQueuingPermitted = 0x0000;
4806 DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
4808 else
4810 unsigned short TargetBit;
4811 for (TargetID = 0, TargetBit = 1;
4812 TargetID < BusLogic_MaxTargetDevices;
4813 TargetID++, TargetBit <<= 1)
4814 switch (*OptionsString++)
4816 case 'Y':
4817 DriverOptions->TaggedQueuingPermitted |= TargetBit;
4818 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4819 break;
4820 case 'N':
4821 DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
4822 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4823 break;
4824 case 'X':
4825 break;
4826 default:
4827 OptionsString--;
4828 TargetID = BusLogic_MaxTargetDevices;
4829 break;
4833 /* Error Recovery Option. */
4834 else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") ||
4835 BusLogic_ParseKeyword(&OptionsString, "ER:"))
4837 if (BusLogic_ParseKeyword(&OptionsString, "Default"))
4838 for (TargetID = 0;
4839 TargetID < BusLogic_MaxTargetDevices;
4840 TargetID++)
4841 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4842 BusLogic_ErrorRecovery_Default;
4843 else if (BusLogic_ParseKeyword(&OptionsString, "HardReset"))
4844 for (TargetID = 0;
4845 TargetID < BusLogic_MaxTargetDevices;
4846 TargetID++)
4847 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4848 BusLogic_ErrorRecovery_HardReset;
4849 else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset"))
4850 for (TargetID = 0;
4851 TargetID < BusLogic_MaxTargetDevices;
4852 TargetID++)
4853 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4854 BusLogic_ErrorRecovery_BusDeviceReset;
4855 else if (BusLogic_ParseKeyword(&OptionsString, "None"))
4856 for (TargetID = 0;
4857 TargetID < BusLogic_MaxTargetDevices;
4858 TargetID++)
4859 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4860 BusLogic_ErrorRecovery_None;
4861 else
4862 for (TargetID = 0;
4863 TargetID < BusLogic_MaxTargetDevices;
4864 TargetID++)
4865 switch (*OptionsString++)
4867 case 'D':
4868 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4869 BusLogic_ErrorRecovery_Default;
4870 break;
4871 case 'H':
4872 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4873 BusLogic_ErrorRecovery_HardReset;
4874 break;
4875 case 'B':
4876 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4877 BusLogic_ErrorRecovery_BusDeviceReset;
4878 break;
4879 case 'N':
4880 DriverOptions->ErrorRecoveryStrategy[TargetID] =
4881 BusLogic_ErrorRecovery_None;
4882 break;
4883 default:
4884 OptionsString--;
4885 TargetID = BusLogic_MaxTargetDevices;
4886 break;
4889 /* Miscellaneous Options. */
4890 else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
4891 BusLogic_ParseKeyword(&OptionsString, "BST:"))
4893 unsigned short BusSettleTime =
4894 simple_strtoul(OptionsString, &OptionsString, 0);
4895 if (BusSettleTime > 5 * 60)
4897 BusLogic_Error("BusLogic: Invalid Driver Options "
4898 "(illegal Bus Settle Time %d)\n",
4899 NULL, BusSettleTime);
4900 return;
4902 DriverOptions->BusSettleTime = BusSettleTime;
4904 else if (BusLogic_ParseKeyword(&OptionsString,
4905 "InhibitTargetInquiry"))
4906 DriverOptions->LocalOptions.InhibitTargetInquiry = true;
4907 /* Debugging Options. */
4908 else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
4909 BusLogic_GlobalOptions.TraceProbe = true;
4910 else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
4911 BusLogic_GlobalOptions.TraceHardwareReset = true;
4912 else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
4913 BusLogic_GlobalOptions.TraceConfiguration = true;
4914 else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
4915 BusLogic_GlobalOptions.TraceErrors = true;
4916 else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
4918 BusLogic_GlobalOptions.TraceProbe = true;
4919 BusLogic_GlobalOptions.TraceHardwareReset = true;
4920 BusLogic_GlobalOptions.TraceConfiguration = true;
4921 BusLogic_GlobalOptions.TraceErrors = true;
4923 if (*OptionsString == ',')
4924 OptionsString++;
4925 else if (*OptionsString != ';' && *OptionsString != '\0')
4927 BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
4928 "ignored\n", NULL, OptionsString);
4929 *OptionsString = '\0';
4932 if (!(BusLogic_DriverOptionsCount == 0 ||
4933 BusLogic_ProbeInfoCount == 0 ||
4934 BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
4936 BusLogic_Error("BusLogic: Invalid Driver Options "
4937 "(all or no I/O Addresses must be specified)\n", NULL);
4938 return;
4941 Tagged Queuing is disabled when the Queue Depth is 1 since queuing
4942 multiple commands is not possible.
4944 for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
4945 if (DriverOptions->QueueDepth[TargetID] == 1)
4947 unsigned short TargetBit = 1 << TargetID;
4948 DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
4949 DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4951 if (*OptionsString == ';') OptionsString++;
4952 if (*OptionsString == '\0') return;
4958 BusLogic_Setup handles processing of Kernel Command Line Arguments.
4961 void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers)
4963 if (CommandLineIntegers[0] != 0)
4965 BusLogic_Error("BusLogic: Obsolete Command Line Entry "
4966 "Format Ignored\n", NULL);
4967 return;
4969 if (CommandLineString == NULL || *CommandLineString == '\0') return;
4970 BusLogic_ParseDriverOptions(CommandLineString);
4975 Include Module support if requested.
4978 #ifdef MODULE
4980 MODULE_PARM(BusLogic_Options, "s");
4982 SCSI_Host_Template_T driver_template = BUSLOGIC;
4984 #include "scsi_module.c"
4986 #endif