root/drivers/scsi/BusLogic.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. BusLogic_AnnounceDriver
  2. BusLogic_DriverInfo
  3. BusLogic_InitializeAddressProbeList
  4. BusLogic_RegisterHostAdapter
  5. BusLogic_UnregisterHostAdapter
  6. BusLogic_CreateCCBs
  7. BusLogic_DestroyCCBs
  8. BusLogic_AllocateCCB
  9. BusLogic_DeallocateCCB
  10. BusLogic_Command
  11. BusLogic_Failure
  12. BusLogic_ProbeHostAdapter
  13. BusLogic_HardResetHostAdapter
  14. BusLogic_CheckHostAdapter
  15. BusLogic_ReadHostAdapterConfiguration
  16. BusLogic_AcquireResources
  17. BusLogic_ReleaseResources
  18. BusLogic_TestInterrupts
  19. BusLogic_InitializeHostAdapter
  20. BusLogic_InquireTargetDevices
  21. BusLogic_DetectHostAdapter
  22. BusLogic_ReleaseHostAdapter
  23. BusLogic_ComputeResultCode
  24. BusLogic_InterruptHandler
  25. BusLogic_WriteOutgoingMailboxEntry
  26. BusLogic_QueueCommand
  27. BusLogic_AbortCommand
  28. BusLogic_ResetHostAdapter
  29. BusLogic_BusDeviceReset
  30. BusLogic_ResetCommand
  31. BusLogic_BIOSDiskParameters
  32. BusLogic_Setup

   1 /*
   2 
   3   Linux Driver for BusLogic SCSI Host Adapters
   4 
   5   Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>
   6 
   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, provided that none of the source code or runtime
  10   copyright notices are removed or modified.
  11 
  12   This program is distributed in the hope that it will be useful, but
  13   WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
  14   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15   for complete details.
  16 
  17   The author respectfully requests that all modifications to this software be
  18   sent directly to him for evaluation and testing.
  19 
  20   Special thanks to Alex T. Win of BusLogic, whose advice has been invaluable,
  21   and to David B. Gentzel, for writing the original Linux BusLogic driver.
  22 
  23 */
  24 
  25 
  26 #define BusLogic_DriverVersion          "1.3.0"
  27 #define BusLogic_DriverDate             "13 November 1995"
  28 
  29 
  30 #include <linux/config.h>
  31 #include <linux/types.h>
  32 #include <linux/blkdev.h>
  33 #include <linux/delay.h>
  34 #include <linux/ioport.h>
  35 #include <linux/kernel_stat.h>
  36 #include <linux/mm.h>
  37 #include <linux/sched.h>
  38 #include <linux/stat.h>
  39 #include <linux/pci.h>
  40 #include <linux/bios32.h>
  41 #include <asm/dma.h>
  42 #include <asm/io.h>
  43 #include <asm/system.h>
  44 #include "scsi.h"
  45 #include "hosts.h"
  46 #include "sd.h"
  47 #include "BusLogic.h"
  48 
  49 
  50 /*
  51   BusLogic_CommandLineEntryCount is a count of the number of "BusLogic="
  52   entries provided on the Linux Kernel Command Line.
  53 */
  54 
  55 static int
  56   BusLogic_CommandLineEntryCount =      0;
  57 
  58 
  59 /*
  60   BusLogic_CommandLineEntries is an array of Command Line Entry structures
  61   representing the "BusLogic=" entries provided on the Linux Kernel Command
  62   Line.
  63 */
  64 
  65 static BusLogic_CommandLineEntry_T
  66   BusLogic_CommandLineEntries[BusLogic_MaxHostAdapters];
  67 
  68 
  69 /*
  70   BusLogic_TracingOptions is a bit mask of Tracing Options to be applied
  71   across all Host Adapters.
  72 */
  73 
  74 static int
  75   BusLogic_TracingOptions =             0;
  76 
  77 
  78 /*
  79   BusLogic_RegisteredHostAdapters is a linked list of all the registered
  80   BusLogic Host Adapters.
  81 */
  82 
  83 static BusLogic_HostAdapter_T
  84   *BusLogic_RegisteredHostAdapters =    NULL;
  85 
  86 
  87 /*
  88   BusLogic_Standard_IO_Addresses is the list of standard I/O Addresses at which
  89   BusLogic Host Adapters may potentially be found.
  90 */
  91 
  92 static unsigned short
  93   BusLogic_IO_StandardAddresses[] =
  94     { 0x330, 0x334, 0x230, 0x234, 0x130, 0x134, 0 };
  95 
  96 
  97 /*
  98   BusLogic_IO_AddressProbeList is the list of I/O Addresses to be probed for
  99   potential BusLogic Host Adapters.  It is initialized by interrogating the
 100   PCI Configuration Space on PCI machines as well as from the list of
 101   standard BusLogic I/O Addresses.
 102 */
 103 
 104 static unsigned short
 105   BusLogic_IO_AddressProbeList[BusLogic_IO_MaxProbeAddresses+1] =   { 0 };
 106 
 107 
 108 /*
 109   BusLogic_IRQ_UsageCount stores a count of the number of Host Adapters using
 110   a given IRQ Channel, which is necessary to support PCI, EISA, or MCA shared
 111   interrupts.  Only IRQ Channels 9, 10, 11, 12, 14, and 15 are supported by
 112   BusLogic Host Adapters.
 113 */
 114 
 115 static short
 116   BusLogic_IRQ_UsageCount[7] =          { 0 };
 117 
 118 
 119 /*
 120   BusLogic_CommandFailureReason holds a string identifying the reason why a
 121   call to BusLogic_Command failed.  It is only valid when BusLogic_Command
 122   returns a failure code.
 123 */
 124 
 125 static char
 126   *BusLogic_CommandFailureReason;
 127 
 128 
 129 /*
 130   BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
 131 */
 132 
 133 static struct proc_dir_entry
 134   BusLogic_ProcDirectoryEntry =
 135     { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
 136 
 137 
 138 /*
 139   BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
 140   Name, Copyright Notice, and Contact Address.
 141 */
 142 
 143 static void BusLogic_AnnounceDriver(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145   static boolean DriverAnnouncementPrinted = false;
 146   if (DriverAnnouncementPrinted) return;
 147   printk("scsi: ***** BusLogic SCSI Driver Version "
 148          BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n");
 149   printk("scsi: Copyright 1995 by Leonard N. Zubkoff "
 150          "<lnz@dandelion.com>\n");
 151   DriverAnnouncementPrinted = true;
 152 }
 153 
 154 
 155 /*
 156   BusLogic_DriverInfo returns the Board Name to identify this SCSI Driver
 157   and Host Adapter.
 158 */
 159 
 160 const char *BusLogic_DriverInfo(SCSI_Host_T *Host)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162   BusLogic_HostAdapter_T *HostAdapter =
 163     (BusLogic_HostAdapter_T *) Host->hostdata;
 164   return HostAdapter->BoardName;
 165 }
 166 
 167 
 168 /*
 169   BusLogic_InitializeAddressProbeList initializes the list of I/O Addresses
 170   to be probed for potential BusLogic SCSI Host Adapters by interrogating the
 171   PCI Configuration Space on PCI machines as well as from the list of standard
 172   BusLogic I/O Addresses.
 173 */
 174 
 175 static void BusLogic_InitializeAddressProbeList(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177   int DestinationIndex = 0, SourceIndex = 0;
 178   /*
 179     If BusLogic_Setup has been called, do not override the Kernel Command
 180     Line specifications.
 181   */
 182   if (BusLogic_IO_AddressProbeList[0] != 0) return;
 183 #ifdef CONFIG_PCI
 184   /*
 185     Interrogate PCI Configuration Space for any BusLogic SCSI Host Adapters.
 186   */
 187   if (pcibios_present())
 188     {
 189       unsigned short Index = 0, VendorID;
 190       unsigned char Bus, DeviceAndFunction;
 191       unsigned int BaseAddress0;
 192       while (pcibios_find_class(PCI_CLASS_STORAGE_SCSI<<8, Index++,
 193                                 &Bus, &DeviceAndFunction) == 0)
 194         if (pcibios_read_config_word(Bus, DeviceAndFunction,
 195                                      PCI_VENDOR_ID, &VendorID) == 0 &&
 196             VendorID == PCI_VENDOR_ID_BUSLOGIC &&
 197             pcibios_read_config_dword(Bus, DeviceAndFunction,
 198                                       PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
 199             (BaseAddress0 & PCI_BASE_ADDRESS_SPACE) ==
 200               PCI_BASE_ADDRESS_SPACE_IO)
 201           {
 202             BusLogic_IO_AddressProbeList[DestinationIndex++] =
 203               BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
 204           }
 205     }
 206 #endif
 207   /*
 208     Append the list of standard BusLogic I/O Addresses.
 209   */
 210   while (DestinationIndex < BusLogic_IO_MaxProbeAddresses &&
 211          BusLogic_IO_StandardAddresses[SourceIndex] > 0)
 212     BusLogic_IO_AddressProbeList[DestinationIndex++] =
 213       BusLogic_IO_StandardAddresses[SourceIndex++];
 214   BusLogic_IO_AddressProbeList[DestinationIndex] = 0;
 215 }
 216 
 217 
 218 /*
 219   BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
 220   BusLogic Host Adapters.
 221 */
 222 
 223 static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225   HostAdapter->Next = NULL;
 226   if (BusLogic_RegisteredHostAdapters != NULL)
 227     {
 228       BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters;
 229       BusLogic_HostAdapter_T *NextHostAdapter;
 230       while ((NextHostAdapter = LastHostAdapter->Next) != NULL)
 231         LastHostAdapter = NextHostAdapter;
 232       LastHostAdapter->Next = HostAdapter;
 233     }
 234   else BusLogic_RegisteredHostAdapters = HostAdapter;
 235 }
 236 
 237 
 238 /*
 239   BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
 240   registered BusLogic Host Adapters.
 241 */
 242 
 243 static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245   if (BusLogic_RegisteredHostAdapters != HostAdapter)
 246     {
 247       BusLogic_HostAdapter_T *LastHostAdapter = BusLogic_RegisteredHostAdapters;
 248       while (LastHostAdapter != NULL && LastHostAdapter->Next != HostAdapter)
 249         LastHostAdapter = LastHostAdapter->Next;
 250       if (LastHostAdapter != NULL)
 251         LastHostAdapter->Next = HostAdapter->Next;
 252     }
 253   else BusLogic_RegisteredHostAdapters = HostAdapter->Next;
 254   HostAdapter->Next = NULL;
 255 }
 256 
 257 
 258 /*
 259   BusLogic_CreateCCBs allocates the initial Command Control Blocks (CCBs)
 260   for Host Adapter.
 261 */
 262 
 263 static boolean BusLogic_CreateCCBs(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 264 {
 265   int i;
 266   for (i = 0; i < BusLogic_InitialCCBs; i++)
 267     {
 268       BusLogic_CCB_T *CCB = (BusLogic_CCB_T *)
 269         scsi_init_malloc(sizeof(BusLogic_CCB_T), GFP_ATOMIC | GFP_DMA);
 270       if (CCB == NULL)
 271         {
 272           printk("scsi%d: UNABLE TO ALLOCATE CCB %d - DETACHING\n",
 273                  HostAdapter->HostNumber, i);
 274           return false;
 275         }
 276       memset(CCB, 0, sizeof(BusLogic_CCB_T));
 277       CCB->HostAdapter = HostAdapter;
 278       CCB->Status = BusLogic_CCB_Free;
 279       CCB->Next = HostAdapter->Free_CCBs;
 280       CCB->NextAll = HostAdapter->All_CCBs;
 281       HostAdapter->Free_CCBs = CCB;
 282       HostAdapter->All_CCBs = CCB;
 283     }
 284   return true;
 285 }
 286 
 287 
 288 /*
 289   BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
 290 */
 291 
 292 static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294   BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB;
 295   HostAdapter->All_CCBs = NULL;
 296   HostAdapter->Free_CCBs = NULL;
 297   while ((CCB = NextCCB) != NULL)
 298     {
 299       NextCCB = CCB->NextAll;
 300       scsi_init_free((char *) CCB, sizeof(BusLogic_CCB_T));
 301     }
 302 }
 303 
 304 
 305 /*
 306   BusLogic_AllocateCCB allocates a CCB from the Host Adapter's free list,
 307   allocating more memory from the Kernel if necessary.
 308 */
 309 
 310 static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312   static unsigned int SerialNumber = 0;
 313   BusLogic_CCB_T *CCB;
 314   BusLogic_LockHostAdapter(HostAdapter);
 315   CCB = HostAdapter->Free_CCBs;
 316   if (CCB != NULL)
 317     {
 318       CCB->SerialNumber = SerialNumber++;
 319       HostAdapter->Free_CCBs = CCB->Next;
 320       BusLogic_UnlockHostAdapter(HostAdapter);
 321       return CCB;
 322     }
 323   BusLogic_UnlockHostAdapter(HostAdapter);
 324   CCB = (BusLogic_CCB_T *) scsi_init_malloc(sizeof(BusLogic_CCB_T),
 325                                             GFP_ATOMIC | GFP_DMA);
 326   if (CCB == NULL)
 327     {
 328       printk("scsi%d: Failed to allocate an additional CCB\n",
 329              HostAdapter->HostNumber);
 330       return NULL;
 331     }
 332   printk("scsi%d: Allocated an additional CCB\n", HostAdapter->HostNumber);
 333   memset(CCB, 0, sizeof(BusLogic_CCB_T));
 334   CCB->HostAdapter = HostAdapter;
 335   CCB->Status = BusLogic_CCB_Free;
 336   BusLogic_LockHostAdapter(HostAdapter);
 337   CCB->SerialNumber = SerialNumber++;
 338   CCB->NextAll = HostAdapter->All_CCBs;
 339   HostAdapter->All_CCBs = CCB;
 340   BusLogic_UnlockHostAdapter(HostAdapter);
 341   return CCB;
 342 }
 343 
 344 
 345 /*
 346   BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
 347   free list.
 348 */
 349 
 350 static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352   BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
 353   BusLogic_LockHostAdapter(HostAdapter);
 354   CCB->Command = NULL;
 355   CCB->Status = BusLogic_CCB_Free;
 356   CCB->SerialNumber = 0;
 357   CCB->Next = HostAdapter->Free_CCBs;
 358   HostAdapter->Free_CCBs = CCB;
 359   BusLogic_UnlockHostAdapter(HostAdapter);
 360 }
 361 
 362 
 363 /*
 364   BusLogic_Command sends the command OperationCode to HostAdapter, optionally
 365   providing ParameterLength bytes of ParameterData and receiving at most
 366   ReplyLength bytes of ReplyData; any excess reply data is received but
 367   discarded.
 368 
 369   On success, this function returns the number of reply bytes read from
 370   the Host Adapter (including any discarded data); on failure, it returns
 371   -1 if the command was invalid, or -2 if a timeout occurred.
 372 
 373   This function is only called during board detection and initialization, so
 374   performance and latency are not critical, and exclusive access to the Host
 375   Adapter hardware is assumed.  Once the board and driver are initialized, the
 376   only Host Adapter command that is issued is the single byte Start Mailbox
 377   Scan command, which does not require waiting for the Host Adapter Ready bit
 378   to be set in the Status Register.
 379 */
 380 
 381 static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
     /* [previous][next][first][last][top][bottom][index][help] */
 382                             BusLogic_OperationCode_T OperationCode,
 383                             void *ParameterData,
 384                             int ParameterLength,
 385                             void *ReplyData,
 386                             int ReplyLength)
 387 {
 388   unsigned char *ParameterPointer = (unsigned char *) ParameterData;
 389   unsigned char *ReplyPointer = (unsigned char *) ReplyData;
 390   unsigned char StatusRegister = 0, InterruptRegister;
 391   long TimeoutCounter;
 392   int ReplyBytes = 0;
 393   /*
 394     Clear out the Reply Data if provided.
 395   */
 396   if (ReplyLength > 0)
 397     memset(ReplyData, 0, ReplyLength);
 398   /*
 399     Select an appropriate timeout value.
 400   */
 401   switch (OperationCode)
 402     {
 403     case BusLogic_InquireInstalledDevicesID0to7:
 404     case BusLogic_InquireInstalledDevicesID8to15:
 405       /* Approximately 60 seconds. */
 406       TimeoutCounter = loops_per_sec << 2;
 407       break;
 408     default:
 409       /* Approximately 1 second. */
 410       TimeoutCounter = loops_per_sec >> 4;
 411       break;
 412     }
 413   /*
 414     Wait for the Host Adapter Ready bit to be set and the Command/Parameter
 415     Register Busy bit to be reset in the Status Register.
 416   */
 417   while (--TimeoutCounter >= 0)
 418     {
 419       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 420       if ((StatusRegister & BusLogic_HostAdapterReady) &&
 421           !(StatusRegister & BusLogic_CommandParameterRegisterBusy))
 422         break;
 423     }
 424   BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
 425   if (TimeoutCounter < 0) return -2;
 426   /*
 427     Write the OperationCode to the Command/Parameter Register.
 428   */
 429   BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
 430   /*
 431     Write any additional Parameter Bytes.
 432   */
 433   HostAdapter->HostAdapterCommandCompleted = false;
 434   while (--ParameterLength >= 0)
 435     {
 436       InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter);
 437       if (InterruptRegister & BusLogic_CommandComplete) break;
 438       if (HostAdapter->HostAdapterCommandCompleted) break;
 439       while (--TimeoutCounter >= 0)
 440         {
 441           StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 442           if (!(StatusRegister & BusLogic_CommandParameterRegisterBusy)) break;
 443         }
 444       BusLogic_CommandFailureReason =
 445         "Timeout waiting for Parameter Acceptance";
 446       if (TimeoutCounter < 0) return -2;
 447       BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
 448     }
 449   BusLogic_CommandFailureReason = "Excess Parameters Supplied";
 450   if (ParameterLength >= 0) return -1;
 451   /*
 452     The Modify I/O Address command does not cause a Command Complete Interrupt.
 453   */
 454   if (OperationCode == BusLogic_ModifyIOAddress)
 455     {
 456       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 457       BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
 458       return ((StatusRegister & BusLogic_CommandInvalid) ? -1 : 0);
 459     }
 460   /*
 461     Receive any Reply Bytes, waiting for either the Command Complete bit to
 462     be set in the Interrupt Register, or for the Interrupt Handler to set the
 463     HostAdapterCommandCompleted bit in the Host Adapter structure.
 464   */
 465   HostAdapter->HostAdapterCommandCompleted = false;
 466   while (--TimeoutCounter >= 0)
 467     {
 468       InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter);
 469       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 470       if (InterruptRegister & BusLogic_CommandComplete) break;
 471       if (HostAdapter->HostAdapterCommandCompleted) break;
 472       if (StatusRegister & BusLogic_DataInRegisterReady)
 473         if (++ReplyBytes <= ReplyLength)
 474           *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
 475         else BusLogic_ReadDataInRegister(HostAdapter);
 476   }
 477   BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
 478   if (TimeoutCounter < 0) return -2;
 479   /*
 480     Clear any pending Command Complete Interrupt, unless this is a
 481     Test Command Complete Interrupt command.
 482   */
 483   if (OperationCode != BusLogic_TestCommandCompleteInterrupt)
 484     BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset);
 485   if (BusLogic_TracingOptions & BusLogic_TraceConfiguration)
 486     if (OperationCode != BusLogic_TestCommandCompleteInterrupt)
 487       {
 488         int i;
 489         printk("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
 490                OperationCode, StatusRegister, ReplyLength, ReplyBytes);
 491         for (i = 0; i < ReplyBytes; i++)
 492           printk(" %02X", ((unsigned char *) ReplyData)[i]);
 493         printk("\n");
 494       }
 495   /*
 496     Return count of Reply Bytes, or -1 if the command was invalid.
 497   */
 498   BusLogic_CommandFailureReason = "Command Invalid";
 499   return ((StatusRegister & BusLogic_CommandInvalid) ? -1 : ReplyBytes);
 500 }
 501 
 502 
 503 /*
 504   BusLogic_Failure prints a standardized error message for tests that are
 505   executed before the SCSI Host is registered, and then returns false.
 506 */
 507 
 508 static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter,
     /* [previous][next][first][last][top][bottom][index][help] */
 509                                 char *ErrorMessage)
 510 {
 511   BusLogic_AnnounceDriver();
 512   printk("While configuring BusLogic Host Adapter at I/O Address 0x%X:\n",
 513          HostAdapter->IO_Address);
 514   printk("%s FAILED - DETACHING\n", ErrorMessage);
 515   if (BusLogic_CommandFailureReason != NULL)
 516     printk("ADDITIONAL FAILURE INFO - %s\n", BusLogic_CommandFailureReason);
 517   return false;
 518 }
 519 
 520 
 521 /*
 522   BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
 523 */
 524 
 525 static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 526 {
 527   boolean TraceProbe = (BusLogic_TracingOptions & BusLogic_TraceProbe);
 528   unsigned char StatusRegister, GeometryRegister;
 529   /*
 530     Read the Status Register to test if there is an I/O port that responds.  A
 531     nonexistent I/O port will return 0xFF, in which case there is definitely no
 532     BusLogic Host Adapter at this base I/O Address.
 533   */
 534   StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 535   if (TraceProbe)
 536     printk("BusLogic_Probe(0x%X): Status 0x%02X\n",
 537            HostAdapter->IO_Address, StatusRegister);
 538   if (StatusRegister == 0xFF) return false;
 539   /*
 540     Read the undocumented BusLogic Geometry Register to test if there is an I/O
 541     port that responds.  Adaptec Host Adapters do not implement the Geometry
 542     Register, so this test helps serve to avoid incorrectly recognizing an
 543     Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
 544     series does respond to the Geometry Register I/O port, but it will be
 545     rejected later when the Inquire Extended Setup Information command is
 546     issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
 547     BusLogic clone that implements the same interface as earlier BusLogic
 548     boards, including the undocumented commands, and is therefore supported by
 549     this driver.  However, the AMI FastDisk always returns 0x00 upon reading
 550     the Geometry Register, so the extended translation option should always be
 551     left disabled on the AMI FastDisk.
 552   */
 553   GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter);
 554   if (TraceProbe)
 555     printk("BusLogic_Probe(0x%X): Geometry 0x%02X\n",
 556            HostAdapter->IO_Address, GeometryRegister);
 557   if (GeometryRegister == 0xFF) return false;
 558   /*
 559     Indicate the Host Adapter Probe completed successfully.
 560   */
 561   return true;
 562 }
 563 
 564 
 565 /*
 566   BusLogic_HardResetHostAdapter issues a Hard Reset to the Host Adapter,
 567   and waits for Host Adapter Diagnostics to complete.
 568 */
 569 
 570 static boolean BusLogic_HardResetHostAdapter(BusLogic_HostAdapter_T
     /* [previous][next][first][last][top][bottom][index][help] */
 571                                              *HostAdapter)
 572 {
 573   boolean TraceHardReset = (BusLogic_TracingOptions & BusLogic_TraceHardReset);
 574   long TimeoutCounter = loops_per_sec >> 2;
 575   unsigned char StatusRegister = 0;
 576   /*
 577     Issue a Hard Reset Command to the Host Adapter.  The Host Adapter should
 578     respond by setting Diagnostic Active in the Status Register.
 579   */
 580   BusLogic_WriteControlRegister(HostAdapter, BusLogic_HardReset);
 581   /*
 582     Wait until Diagnostic Active is set in the Status Register.
 583   */
 584   while (--TimeoutCounter >= 0)
 585     {
 586       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 587       if ((StatusRegister & BusLogic_DiagnosticActive)) break;
 588     }
 589   if (TraceHardReset)
 590     printk("BusLogic_HardReset(0x%X): Diagnostic Active, Status 0x%02X\n",
 591            HostAdapter->IO_Address, StatusRegister);
 592   if (TimeoutCounter < 0) return false;
 593   /*
 594     Wait until Diagnostic Active is reset in the Status Register.
 595   */
 596   while (--TimeoutCounter >= 0)
 597     {
 598       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 599       if (!(StatusRegister & BusLogic_DiagnosticActive)) break;
 600     }
 601   if (TraceHardReset)
 602     printk("BusLogic_HardReset(0x%X): Diagnostic Completed, Status 0x%02X\n",
 603            HostAdapter->IO_Address, StatusRegister);
 604   if (TimeoutCounter < 0) return false;
 605   /*
 606     Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
 607     or Data In Register Ready bits is set in the Status Register.
 608   */
 609   while (--TimeoutCounter >= 0)
 610     {
 611       StatusRegister = BusLogic_ReadStatusRegister(HostAdapter);
 612       if (StatusRegister & (BusLogic_DiagnosticFailure |
 613                             BusLogic_HostAdapterReady |
 614                             BusLogic_DataInRegisterReady))
 615         break;
 616     }
 617   if (TraceHardReset)
 618     printk("BusLogic_HardReset(0x%X): Host Adapter Ready, Status 0x%02X\n",
 619            HostAdapter->IO_Address, StatusRegister);
 620   if (TimeoutCounter < 0) return false;
 621   /*
 622     If Diagnostic Failure is set or Host Adapter Ready is reset, then an
 623     error occurred during the Host Adapter diagnostics.  If Data In Register
 624     Ready is set, then there is an Error Code available.
 625   */
 626   if ((StatusRegister & BusLogic_DiagnosticFailure) ||
 627       !(StatusRegister & BusLogic_HostAdapterReady))
 628     {
 629       BusLogic_CommandFailureReason = NULL;
 630       BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
 631       printk("HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister);
 632       if (StatusRegister & BusLogic_DataInRegisterReady)
 633         {
 634           unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
 635           printk("HOST ADAPTER ERROR CODE = %d\n", ErrorCode);
 636         }
 637       return false;
 638     }
 639   /*
 640     Indicate the Host Adapter Hard Reset completed successfully.
 641   */
 642   return true;
 643 }
 644 
 645 
 646 /*
 647   BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
 648   Host Adapter.
 649 */
 650 
 651 static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
 654   BusLogic_RequestedReplyLength_T RequestedReplyLength;
 655   unsigned long ProcessorFlags;
 656   int Result;
 657   /*
 658     Issue the Inquire Setup Information command.  Only genuine BusLogic Host
 659     Adapters and true clones support this command.  Adaptec 1542C series Host
 660     Adapters that respond to the Geometry Register I/O port will fail this
 661     command.  Interrupts must be disabled around the call to BusLogic_Command
 662     since a Command Complete interrupt could occur if the IRQ Channel was
 663     previously enabled for another BusLogic Host Adapter sharing the same IRQ
 664     Channel.
 665   */
 666   save_flags(ProcessorFlags);
 667   cli();
 668   RequestedReplyLength = sizeof(ExtendedSetupInformation);
 669   Result = BusLogic_Command(HostAdapter,
 670                             BusLogic_InquireExtendedSetupInformation,
 671                             &RequestedReplyLength, sizeof(RequestedReplyLength),
 672                             &ExtendedSetupInformation,
 673                             sizeof(ExtendedSetupInformation));
 674   restore_flags(ProcessorFlags);
 675   if (BusLogic_TracingOptions & BusLogic_TraceProbe)
 676     printk("BusLogic_Check(0x%X): Result %d\n",
 677            HostAdapter->IO_Address, Result);
 678   return (Result == sizeof(ExtendedSetupInformation));
 679 }
 680 
 681 
 682 /*
 683   BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
 684   from Host Adapter.
 685 */
 686 
 687 static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
     /* [previous][next][first][last][top][bottom][index][help] */
 688                                                      *HostAdapter)
 689 {
 690   BusLogic_BoardID_T BoardID;
 691   BusLogic_Configuration_T Configuration;
 692   BusLogic_SetupInformation_T SetupInformation;
 693   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
 694   BusLogic_ModelAndRevision_T ModelAndRevision;
 695   BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
 696   BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
 697   BusLogic_RequestedReplyLength_T RequestedReplyLength;
 698   unsigned char GeometryRegister, *TargetPointer, Character;
 699   unsigned short AllTargetsMask, DisconnectPermitted;
 700   unsigned short TaggedQueuingPermitted, TaggedQueuingPermittedDefault;
 701   boolean CommonErrorRecovery;
 702   int TargetID, i;
 703   /*
 704     Issue the Inquire Board ID command.
 705   */
 706   if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
 707                        &BoardID, sizeof(BoardID)) != sizeof(BoardID))
 708     return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
 709   /*
 710     Issue the Inquire Configuration command.
 711   */
 712   if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
 713                        &Configuration, sizeof(Configuration))
 714       != sizeof(Configuration))
 715     return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
 716   /*
 717     Issue the Inquire Setup Information command.
 718   */
 719   RequestedReplyLength = sizeof(SetupInformation);
 720   if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
 721                        &RequestedReplyLength, sizeof(RequestedReplyLength),
 722                        &SetupInformation, sizeof(SetupInformation))
 723       != sizeof(SetupInformation))
 724     return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
 725   /*
 726     Issue the Inquire Extended Setup Information command.
 727   */
 728   RequestedReplyLength = sizeof(ExtendedSetupInformation);
 729   if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
 730                        &RequestedReplyLength, sizeof(RequestedReplyLength),
 731                        &ExtendedSetupInformation,
 732                        sizeof(ExtendedSetupInformation))
 733       != sizeof(ExtendedSetupInformation))
 734     return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
 735   /*
 736     Issue the Inquire Board Model and Revision command.
 737   */
 738   RequestedReplyLength = sizeof(ModelAndRevision);
 739   if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardModelAndRevision,
 740                        &RequestedReplyLength, sizeof(RequestedReplyLength),
 741                        &ModelAndRevision, sizeof(ModelAndRevision))
 742       != sizeof(ModelAndRevision))
 743     return BusLogic_Failure(HostAdapter, "INQUIRE BOARD MODEL AND REVISION");
 744   /*
 745     Issue the Inquire Firmware Version 3rd Digit command.
 746   */
 747   if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
 748                        NULL, 0, &FirmwareVersion3rdDigit,
 749                        sizeof(FirmwareVersion3rdDigit))
 750       != sizeof(FirmwareVersion3rdDigit))
 751     return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
 752   /*
 753     Issue the Inquire Firmware Version Letter command.
 754   */
 755   FirmwareVersionLetter = '\0';
 756   if (BoardID.FirmwareVersion1stDigit >= '3')
 757     if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
 758                          NULL, 0, &FirmwareVersionLetter,
 759                          sizeof(FirmwareVersionLetter))
 760         != sizeof(FirmwareVersionLetter))
 761       return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER");
 762   /*
 763     BusLogic Host Adapters can be identified by their model number and
 764     the major version number of their firmware as follows:
 765 
 766     4.xx        BusLogic "C" Series Host Adapters:
 767                   946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
 768     3.xx        BusLogic "S" Series Host Adapters:
 769                   747S/747D/757S/757D/445S/545S/542D
 770                   542B/742A (revision H)
 771     2.xx        BusLogic "A" Series Host Adapters:
 772                   542B/742A (revision G and below)
 773     0.xx        AMI FastDisk VLB BusLogic Clone Host Adapter
 774   */
 775   /*
 776     Save the Model Name and Board Name in the Host Adapter structure.
 777   */
 778   TargetPointer = HostAdapter->ModelName;
 779   for (i = 0; i < sizeof(ModelAndRevision.Model); i++)
 780     {
 781       Character = ModelAndRevision.Model[i];
 782       if (Character == ' ' || Character == '\0') break;
 783       *TargetPointer++ = Character;
 784     }
 785   *TargetPointer++ = '\0';
 786   strcpy(HostAdapter->BoardName, "BusLogic ");
 787   strcat(HostAdapter->BoardName, HostAdapter->ModelName);
 788   strcpy(HostAdapter->InterruptLabel, HostAdapter->BoardName);
 789   /*
 790     Save the Firmware Version in the Host Adapter structure.
 791   */
 792   TargetPointer = HostAdapter->FirmwareVersion;
 793   *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
 794   *TargetPointer++ = '.';
 795   *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
 796   if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
 797     *TargetPointer++ = FirmwareVersion3rdDigit;
 798   if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
 799     *TargetPointer++ = FirmwareVersionLetter;
 800   *TargetPointer++ = '\0';
 801   /*
 802     Determine the IRQ Channel and save it in the Host Adapter structure.
 803   */
 804   if (Configuration.IRQ_Channel9)
 805     HostAdapter->IRQ_Channel = 9;
 806   else if (Configuration.IRQ_Channel10)
 807     HostAdapter->IRQ_Channel = 10;
 808   else if (Configuration.IRQ_Channel11)
 809     HostAdapter->IRQ_Channel = 11;
 810   else if (Configuration.IRQ_Channel12)
 811     HostAdapter->IRQ_Channel = 12;
 812   else if (Configuration.IRQ_Channel14)
 813     HostAdapter->IRQ_Channel = 14;
 814   else if (Configuration.IRQ_Channel15)
 815     HostAdapter->IRQ_Channel = 15;
 816   /*
 817     Determine the DMA Channel and save it in the Host Adapter structure.
 818   */
 819   if (Configuration.DMA_Channel5)
 820     HostAdapter->DMA_Channel = 5;
 821   else if (Configuration.DMA_Channel6)
 822     HostAdapter->DMA_Channel = 6;
 823   else if (Configuration.DMA_Channel7)
 824     HostAdapter->DMA_Channel = 7;
 825   /*
 826     Save the Host Adapter SCSI ID in the Host Adapter structure.
 827   */
 828   HostAdapter->SCSI_ID = Configuration.HostAdapterID;
 829   /*
 830     Save the Synchronous Initiation flag and SCSI Parity Checking flag
 831     in the Host Adapter structure.
 832   */
 833   HostAdapter->SynchronousInitiation =
 834     SetupInformation.SynchronousInitiationEnabled;
 835   HostAdapter->ParityChecking = SetupInformation.ParityCheckEnabled;
 836   /*
 837     Determine the Bus Type and save it in the Host Adapter structure,
 838     overriding the DMA Channel if it is inappropriate for the bus type.
 839   */
 840   if (ExtendedSetupInformation.BusType == 'A')
 841     HostAdapter->BusType = BusLogic_ISA_Bus;
 842   else
 843     switch (HostAdapter->ModelName[0])
 844       {
 845       case '4':
 846         HostAdapter->BusType = BusLogic_VESA_Bus;
 847         HostAdapter->DMA_Channel = 0;
 848         break;
 849       case '5':
 850         HostAdapter->BusType = BusLogic_ISA_Bus;
 851         break;
 852       case '6':
 853         HostAdapter->BusType = BusLogic_MCA_Bus;
 854         HostAdapter->DMA_Channel = 0;
 855         break;
 856       case '7':
 857         HostAdapter->BusType = BusLogic_EISA_Bus;
 858         HostAdapter->DMA_Channel = 0;
 859         break;
 860       case '9':
 861         HostAdapter->BusType = BusLogic_PCI_Bus;
 862         HostAdapter->DMA_Channel = 0;
 863         break;
 864       }
 865   /*
 866     Determine whether Extended Translation is enabled and save it in
 867     the Host Adapter structure.
 868   */
 869   GeometryRegister = BusLogic_ReadGeometryRegister(HostAdapter);
 870   if (GeometryRegister & BusLogic_ExtendedTranslationEnabled)
 871     HostAdapter->ExtendedTranslation = true;
 872   /*
 873     Save the Disconnect/Reconnect Permitted flag bits in the Host Adapter
 874     structure.  The Disconnect Permitted information is only valid on "C"
 875     Series boards, but Disconnect/Reconnect is always permitted on "S" and
 876     "A" Series boards.
 877   */
 878   if (HostAdapter->FirmwareVersion[0] >= '4')
 879     HostAdapter->DisconnectPermitted =
 880       (SetupInformation.DisconnectPermittedID8to15 << 8)
 881       | SetupInformation.DisconnectPermittedID0to7;
 882   else HostAdapter->DisconnectPermitted = 0xFF;
 883   /*
 884     Save the Scatter Gather Limits, Level Triggered Interrupts flag,
 885     Wide SCSI flag, and Differential SCSI flag in the Host Adapter structure.
 886   */
 887   HostAdapter->HostAdapterScatterGatherLimit =
 888     ExtendedSetupInformation.ScatterGatherLimit;
 889   HostAdapter->DriverScatterGatherLimit =
 890     HostAdapter->HostAdapterScatterGatherLimit;
 891   if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
 892     HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
 893   if (ExtendedSetupInformation.Misc.LevelTriggeredInterrupts)
 894     HostAdapter->LevelTriggeredInterrupts = true;
 895   if (ExtendedSetupInformation.HostWideSCSI)
 896     {
 897       HostAdapter->HostWideSCSI = true;
 898       HostAdapter->MaxTargetIDs = 16;
 899       HostAdapter->MaxLogicalUnits = 64;
 900     }
 901   else
 902     {
 903       HostAdapter->HostWideSCSI = false;
 904       HostAdapter->MaxTargetIDs = 8;
 905       HostAdapter->MaxLogicalUnits = 8;
 906     }
 907   HostAdapter->HostDifferentialSCSI =
 908     ExtendedSetupInformation.HostDifferentialSCSI;
 909   /*
 910     Determine the Host Adapter BIOS Address if the BIOS is enabled and
 911     save it in the Host Adapter structure.  The BIOS is disabled if the
 912     BIOS_Address is 0.
 913   */
 914   HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
 915   /*
 916     Select an appropriate value for Concurrency (Commands per Logical Unit)
 917     either from a Command Line Entry, or based on whether this is an ISA
 918     or non-ISA Host Adapter.
 919   */
 920   if (HostAdapter->CommandLineEntry != NULL &&
 921       HostAdapter->CommandLineEntry->Concurrency > 0)
 922     HostAdapter->Concurrency = HostAdapter->CommandLineEntry->Concurrency;
 923   else if (HostAdapter->BusType == BusLogic_ISA_Bus)
 924     HostAdapter->Concurrency = BusLogic_Concurrency_ISA;
 925   else HostAdapter->Concurrency = BusLogic_Concurrency;
 926   /*
 927     Select an appropriate value for Bus Settle Time either from a Command
 928     Line Entry, or from BusLogic_DefaultBusSettleTime.
 929   */
 930   if (HostAdapter->CommandLineEntry != NULL &&
 931       HostAdapter->CommandLineEntry->BusSettleTime > 0)
 932     HostAdapter->BusSettleTime = HostAdapter->CommandLineEntry->BusSettleTime;
 933   else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
 934   /*
 935     Select appropriate values for the Error Recovery Option array either from
 936     a Command Line Entry, or using BusLogic_ErrorRecoveryDefault.
 937   */
 938   if (HostAdapter->CommandLineEntry != NULL)
 939     memcpy(HostAdapter->ErrorRecoveryOption,
 940            HostAdapter->CommandLineEntry->ErrorRecoveryOption,
 941            sizeof(HostAdapter->ErrorRecoveryOption));
 942   else memset(HostAdapter->ErrorRecoveryOption,
 943               BusLogic_ErrorRecoveryDefault,
 944               sizeof(HostAdapter->ErrorRecoveryOption));
 945   /*
 946     Tagged Queuing support is available and operates properly only on "C"
 947     Series boards with firmware version 4.22 and above and on "S" Series
 948     boards with firmware version 3.35 and above.  Tagged Queuing is disabled
 949     by default when the Concurrency value is 1 since queuing multiple commands
 950     is not possible.
 951   */
 952   TaggedQueuingPermittedDefault = 0;
 953   if (HostAdapter->Concurrency > 1)
 954     switch (HostAdapter->FirmwareVersion[0])
 955       {
 956       case '4':
 957         if (HostAdapter->FirmwareVersion[2] > '2' ||
 958             (HostAdapter->FirmwareVersion[2] == '2' &&
 959              HostAdapter->FirmwareVersion[3] >= '2'))
 960           TaggedQueuingPermittedDefault = 0xFFFF;
 961         break;
 962       case '3':
 963         if (HostAdapter->FirmwareVersion[2] > '3' ||
 964             (HostAdapter->FirmwareVersion[2] == '3' &&
 965              HostAdapter->FirmwareVersion[3] >= '5'))
 966           TaggedQueuingPermittedDefault = 0xFFFF;
 967         break;
 968       }
 969   /*
 970     Combine the default Tagged Queuing permission based on the Host Adapter
 971     firmware version and Concurrency with any Command Line Entry Tagged
 972     Queuing specification.
 973   */
 974   if (HostAdapter->CommandLineEntry != NULL)
 975     HostAdapter->TaggedQueuingPermitted =
 976       (HostAdapter->CommandLineEntry->TaggedQueuingPermitted &
 977        HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask) |
 978       (TaggedQueuingPermittedDefault &
 979        ~HostAdapter->CommandLineEntry->TaggedQueuingPermittedMask);
 980   else HostAdapter->TaggedQueuingPermitted = TaggedQueuingPermittedDefault;
 981   /*
 982     Announce the Host Adapter Configuration.
 983   */
 984   printk("scsi%d: Configuring BusLogic Model %s %s%s%s SCSI Host Adapter\n",
 985          HostAdapter->HostNumber, HostAdapter->ModelName,
 986          BusLogic_BusNames[HostAdapter->BusType],
 987          (HostAdapter->HostWideSCSI ? " Wide" : ""),
 988          (HostAdapter->HostDifferentialSCSI ? " Differential" : ""));
 989   printk("scsi%d:   Firmware Version: %s, I/O Address: 0x%X, "
 990          "IRQ Channel: %d/%s\n",
 991          HostAdapter->HostNumber, HostAdapter->FirmwareVersion,
 992          HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
 993          (HostAdapter->LevelTriggeredInterrupts ? "Level" : "Edge"));
 994   printk("scsi%d:   DMA Channel: ", HostAdapter->HostNumber);
 995   if (HostAdapter->DMA_Channel > 0)
 996     printk("%d, ", HostAdapter->DMA_Channel);
 997   else printk("None, ");
 998   if (HostAdapter->BIOS_Address > 0)
 999     printk("BIOS Address: 0x%lX, ", HostAdapter->BIOS_Address);
1000   else printk("BIOS Address: None, ");
1001   printk("Host Adapter SCSI ID: %d\n", HostAdapter->SCSI_ID);
1002   printk("scsi%d:   Scatter/Gather Limit: %d segments, "
1003          "Synchronous Initiation: %s\n", HostAdapter->HostNumber,
1004          HostAdapter->HostAdapterScatterGatherLimit,
1005          (HostAdapter->SynchronousInitiation ? "Enabled" : "Disabled"));
1006   printk("scsi%d:   SCSI Parity Checking: %s, "
1007          "Extended Disk Translation: %s\n", HostAdapter->HostNumber,
1008          (HostAdapter->ParityChecking ? "Enabled" : "Disabled"),
1009          (HostAdapter->ExtendedTranslation ? "Enabled" : "Disabled"));
1010   AllTargetsMask = (1 << HostAdapter->MaxTargetIDs) - 1;
1011   DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
1012   printk("scsi%d:   Disconnect/Reconnect: ", HostAdapter->HostNumber);
1013   if (DisconnectPermitted == 0)
1014     printk("Disabled");
1015   else if (DisconnectPermitted == AllTargetsMask)
1016     printk("Enabled");
1017   else
1018     for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++)
1019       printk("%c", (DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
1020   printk(", Tagged Queuing: ");
1021   TaggedQueuingPermitted =
1022     HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
1023   if (TaggedQueuingPermitted == 0)
1024     printk("Disabled");
1025   else if (TaggedQueuingPermitted == AllTargetsMask)
1026     printk("Enabled");
1027   else
1028     for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++)
1029       printk("%c", (TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
1030   printk("\n");
1031   CommonErrorRecovery = true;
1032   for (TargetID = 1; TargetID < HostAdapter->MaxTargetIDs; TargetID++)
1033     if (HostAdapter->ErrorRecoveryOption[TargetID] !=
1034         HostAdapter->ErrorRecoveryOption[0])
1035       {
1036         CommonErrorRecovery = false;
1037         break;
1038       }
1039   printk("scsi%d:   Error Recovery: ", HostAdapter->HostNumber);
1040   if (CommonErrorRecovery)
1041     printk("%s", BusLogic_ErrorRecoveryOptions[
1042                    HostAdapter->ErrorRecoveryOption[0]]);
1043   else
1044     for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++)
1045       printk("%s", BusLogic_ErrorRecoveryOptions2[
1046                      HostAdapter->ErrorRecoveryOption[TargetID]]);
1047   printk(", Mailboxes: %d, Initial CCBs: %d\n",
1048          BusLogic_MailboxCount, BusLogic_InitialCCBs);
1049   printk("scsi%d:   Driver Scatter/Gather Limit: %d segments, "
1050          "Concurrency: %d\n", HostAdapter->HostNumber,
1051          HostAdapter->DriverScatterGatherLimit, HostAdapter->Concurrency);
1052   /*
1053     Indicate reading the Host Adapter Configuration completed successfully.
1054   */
1055   return true;
1056 }
1057 
1058 
1059 /*
1060   BusLogic_AcquireResources acquires the system resources necessary to use Host
1061   Adapter, and initializes the fields in the SCSI Host structure.  The base,
1062   io_port, n_io_ports, irq, and dma_channel fields in the SCSI Host structure
1063   are intentionally left uninitialized, as this driver handles acquisition and
1064   release of these resources explicitly, as well as ensuring exclusive access
1065   to the Host Adapter hardware and data structures through explicit locking.
1066 */
1067 
1068 static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter,
     /* [previous][next][first][last][top][bottom][index][help] */
1069                                          SCSI_Host_T *Host)
1070 {
1071   /*
1072     Acquire exclusive or shared access to the IRQ Channel.  A usage count is
1073     maintained so that PCI, EISA, or MCA shared Interrupts can be supported.
1074   */
1075   if (BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]++ == 0)
1076     {
1077       if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
1078                       SA_INTERRUPT, HostAdapter->InterruptLabel) < 0)
1079         {
1080           BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9]--;
1081           printk("scsi%d: UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
1082                  HostAdapter->HostNumber, HostAdapter->IRQ_Channel);
1083           return false;
1084         }
1085     }
1086   else
1087     {
1088       BusLogic_HostAdapter_T *FirstHostAdapter =
1089         BusLogic_RegisteredHostAdapters;
1090       while (FirstHostAdapter != NULL)
1091         {
1092           if (FirstHostAdapter->IRQ_Channel == HostAdapter->IRQ_Channel)
1093             {
1094               if (strlen(FirstHostAdapter->InterruptLabel) + 8
1095                   < sizeof(FirstHostAdapter->InterruptLabel))
1096                 {
1097                   strcat(FirstHostAdapter->InterruptLabel, " + ");
1098                   strcat(FirstHostAdapter->InterruptLabel,
1099                          HostAdapter->ModelName);
1100                 }
1101               break;
1102             }
1103           FirstHostAdapter = FirstHostAdapter->Next;
1104         }
1105     }
1106   HostAdapter->IRQ_ChannelAcquired = true;
1107   /*
1108     Acquire exclusive access to the DMA Channel.
1109   */
1110   if (HostAdapter->DMA_Channel > 0)
1111     {
1112       if (request_dma(HostAdapter->DMA_Channel, HostAdapter->BoardName) < 0)
1113         {
1114           printk("scsi%d: UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
1115                  HostAdapter->HostNumber, HostAdapter->DMA_Channel);
1116           return false;
1117         }
1118       set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
1119       enable_dma(HostAdapter->DMA_Channel);
1120       HostAdapter->DMA_ChannelAcquired = true;
1121     }
1122   /*
1123     Initialize necessary fields in the SCSI Host structure.
1124   */
1125   Host->max_id = HostAdapter->MaxTargetIDs;
1126   Host->max_lun = HostAdapter->MaxLogicalUnits;
1127   Host->max_channel = 0;
1128   Host->this_id = HostAdapter->SCSI_ID;
1129   Host->can_queue = BusLogic_MailboxCount;
1130   Host->cmd_per_lun = HostAdapter->Concurrency;
1131   Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
1132   Host->unchecked_isa_dma = (HostAdapter->BusType == BusLogic_ISA_Bus);
1133   /*
1134     BusLogic 445S Host Adapters prior to board revision D have a hardware bug
1135     whereby when the BIOS is enabled, transfers to/from the same address range
1136     the BIOS occupies modulo 16MB are handled incorrectly.  Since 16KB out of
1137     each 16MB after the first is such a small amount of memory, this memory
1138     can be marked as reserved without a significant loss of performance; this
1139     is a much cheaper solution than requiring that ISA bounce buffers be used.
1140   */
1141   if (HostAdapter->BIOS_Address > 0 &&
1142       strcmp(HostAdapter->ModelName, "445S") == 0)
1143     {
1144       Host->forbidden_addr = HostAdapter->BIOS_Address;
1145       Host->forbidden_size = 16*1024;
1146     }
1147   /*
1148     Indicate the System Resource Acquisition completed successfully,
1149   */
1150   return true;
1151 }
1152 
1153 
1154 /*
1155   BusLogic_ReleaseResources releases any system resources previously acquired
1156   by BusLogic_AcquireResources.
1157 */
1158 
1159 static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
1160 {
1161   /*
1162     Release exclusive or shared access to the IRQ Channel.
1163   */
1164   if (HostAdapter->IRQ_ChannelAcquired)
1165     if (--BusLogic_IRQ_UsageCount[HostAdapter->IRQ_Channel - 9] == 0)
1166       free_irq(HostAdapter->IRQ_Channel);
1167   /*
1168     Release exclusive access to the DMA Channel.
1169   */
1170   if (HostAdapter->DMA_ChannelAcquired)
1171     free_dma(HostAdapter->DMA_Channel);
1172 }
1173 
1174 
1175 /*
1176   BusLogic_TestInterrupts tests for proper functioning of the Host Adapter
1177   Interrupt Register and that interrupts generated by the Host Adapter are
1178   getting through to the Interrupt Handler.  A large proportion of initial
1179   problems with installing PCI Host Adapters are due to configuration problems
1180   where either the Host Adapter or Motherboard is configured incorrectly, and
1181   interrupts do not get through as a result.
1182 */
1183 
1184 static boolean BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter)
     /* [previous][next][first][last][top][bottom][index][help] */
1185 {
1186   unsigned int InitialInterruptCount, FinalInterruptCount;
1187   int TestCount = 5, i;
1188   InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel];
1189   /*
1190     Issue the Test Command Complete Interrupt commands.
1191   */
1192   for (i = 0; i < TestCount; i++)
1193     BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt,
1194                      NULL, 0, NULL, 0);
1195   /*
1196     Verify that BusLogic_InterruptHandler was called at least TestCount times.
1197     Shared IRQ Channels could cause more than TestCount interrupts to occur,
1198     but there should never be fewer than TestCount.
1199   */
1200   FinalInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel];
1201   if (FinalInterruptCount < InitialInterruptCount + TestCount)
1202     {
1203       printk("scsi%d: HOST ADAPTER INTERRUPT TEST FAILED - DETACHING\n",
1204              HostAdapter->HostNumber);
1205       printk("scsi%d:  Interrupts are not getting through "
1206              "from the Host Adapter to the\n", HostAdapter->HostNumber);
1207       printk("scsi%d:  BusLogic Driver Interrupt Handler.  "
1208              "The most likely cause is that\n", HostAdapter->HostNumber);
1209       printk("scsi%d:  either the Host Adapter or Motherboard "
1210              "is configured incorrectly.\n", HostAdapter->HostNumber);
1211       printk("scsi%d:  Please check the Host Adapter configuration "
1212              "with AutoSCSI or by\n", HostAdapter->HostNumber);
1213       printk("scsi%d:  examining any dip switch and jumper settings "
1214              "on the Host Adapter, and\n", HostAdapter->HostNumber);
1215       printk("scsi%d:  verify that no other device is attempting to "
1216              "use the same IRQ Channel.\n", HostAdapter->HostNumber);
1217       printk("scsi%d:  For PCI Host Adapters, it may also be necessary "
1218              "to investigate and\n", HostAdapter->HostNumber);
1219       printk("scsi%d:  manually set the PCI interrupt assignments "
1220              "and edge/level interrupt\n", HostAdapter->HostNumber);
1221       printk("scsi%d:  type selection in the BIOS Setup Program or "
1222              "with Motherboard jumpers.\n", HostAdapter->HostNumber);
1223       return false;
1224     }
1225   /*
1226     Indicate the Host Adapter Interrupt Test completed successfully.
1227   */
1228   return true;
1229 }
1230 
1231 
1232 /*
1233   BusLogic_InitializeHostAdapter initializes Host Adapter.  This is the only
1234   function called during SCSI Host Adapter detection which modifies the state
1235   of the Host Adapter from its initial power on or hard reset state.
1236 */
1237 
1238 static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T
     /* [previous][next][first][last][top][bottom][index][help] */
1239                                               *HostAdapter)
1240 {
1241   BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
1242   BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest;
1243   BusLogic_WideModeCCBRequest_T WideModeCCBRequest;
1244   BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest;
1245   /*
1246     Initialize Read/Write Operation Count and Command Successful Flag
1247     for each Target.
1248   */
1249   memset(HostAdapter->ReadWriteOperationCount, 0,
1250          sizeof(HostAdapter->ReadWriteOperationCount));
1251   memset(HostAdapter->CommandSuccessfulFlag, false,
1252          sizeof(HostAdapter->CommandSuccessfulFlag));
1253   /*
1254     Initialize the Outgoing and Incoming Mailbox structures.
1255   */
1256   memset(HostAdapter->OutgoingMailboxes, 0,
1257          sizeof(HostAdapter->OutgoingMailboxes));
1258   memset(HostAdapter->IncomingMailboxes, 0,
1259          sizeof(HostAdapter->IncomingMailboxes));
1260   /*
1261     Initialize the pointers to the First, Last, and Next Mailboxes.
1262   */
1263   HostAdapter->FirstOutgoingMailbox = &HostAdapter->OutgoingMailboxes[0];
1264   HostAdapter->LastOutgoingMailbox =
1265     &HostAdapter->OutgoingMailboxes[BusLogic_MailboxCount-1];
1266   HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
1267   HostAdapter->FirstIncomingMailbox = &HostAdapter->IncomingMailboxes[0];
1268   HostAdapter->LastIncomingMailbox =
1269     &HostAdapter->IncomingMailboxes[BusLogic_MailboxCount-1];
1270   HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
1271   /*
1272     Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
1273   */
1274   ExtendedMailboxRequest.MailboxCount = BusLogic_MailboxCount;
1275   ExtendedMailboxRequest.BaseMailboxAddress = HostAdapter->OutgoingMailboxes;
1276   if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
1277                        &ExtendedMailboxRequest,
1278                        sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
1279     {
1280       printk("scsi%d: MAILBOX INITIALIZATION FAILED - DETACHING\n",
1281              HostAdapter->HostNumber);
1282       return false;
1283     }
1284   /*
1285     Enable Strict Round Robin Mode if supported by the Host Adapter.  In Strict
1286     Round Robin Mode, the Host Adapter only looks at the next Outgoing Mailbox
1287     for each new command, rather than scanning through all the Outgoing
1288     Mailboxes to find any that have new commands in them.  BusLogic indicates
1289     that Strict Round Robin Mode is significantly more efficient.
1290   */
1291   RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
1292   BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
1293                    &RoundRobinModeRequest,
1294                    sizeof(RoundRobinModeRequest), NULL, 0);
1295   /*
1296     For Wide SCSI Host Adapters, issue the Enable Wide Mode CCB command to
1297     allow more than 8 Logical Units per Target to be supported.
1298   */
1299   if (HostAdapter->HostWideSCSI)
1300     {
1301       WideModeCCBRequest = BusLogic_WideModeCCB;
1302       if (BusLogic_Command(HostAdapter, BusLogic_EnableWideModeCCB,
1303                            &WideModeCCBRequest,
1304                            sizeof(WideModeCCBRequest), NULL, 0) < 0)
1305         {
1306           printk("scsi%d: ENABLE WIDE MODE CCB FAILED - DETACHING\n",
1307                  HostAdapter->HostNumber);
1308           return false;
1309         }
1310     }
1311   /*
1312     For PCI Host Adapters being accessed through the PCI compliant I/O
1313     Address, disable the ISA compatible I/O Address to avoid detecting the
1314     same Host Adapter at both I/O Addresses.
1315   */
1316   if (HostAdapter->BusType == BusLogic_PCI_Bus)
1317     {
1318       int Index;
1319       for (Index = 0; BusLogic_IO_StandardAddresses[Index] > 0; Index++)
1320         if (HostAdapter->IO_Address == BusLogic_IO_StandardAddresses[Index])
1321           break;
1322       if (BusLogic_IO_StandardAddresses[Index] == 0)
1323         {
1324           ModifyIOAddressRequest = BusLogic_ModifyIO_Disable;
1325           if (BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
1326                                &ModifyIOAddressRequest,
1327                                sizeof(ModifyIOAddressRequest), NULL, 0) < 0)
1328             {
1329               printk("scsi%d: MODIFY I/O ADDRESS FAILED - DETACHING\n",
1330                      HostAdapter->HostNumber);
1331               return false;
1332             }
1333         }
1334     }
1335   /*
1336     Announce Successful Initialization.
1337   */
1338   printk("scsi%d: *** %s Initialized Successfully ***\n",
1339          HostAdapter->HostNumber, HostAdapter->BoardName);
1340   /*
1341     Indicate the Host Adapter Initialization completed successfully.
1342   */
1343   return true;
1344 }
1345 
1346 
1347 /*
1348   BusLogic_InquireTargetDevices inquires about the Target Devices accessible
1349   through Host Adapter and reports on the results.
1350 */
1351 
1352 static boolean BusLogic_InquireTargetDevices(BusLogic_HostAdapter_T
     /* [previous][next][first][last][top][bottom][index][help] */
1353                                              *HostAdapter)
1354 {
1355   BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
1356   BusLogic_InstalledDevices8_T InstalledDevicesID8to15;
1357   BusLogic_SetupInformation_T SetupInformation;
1358   BusLogic_SynchronousPeriod_T SynchronousPeriod;
1359   BusLogic_RequestedReplyLength_T RequestedReplyLength;
1360   int TargetDevicesFound = 0, TargetID;
1361   /*
1362     Wait a few seconds between the Host Adapter Hard Reset which initiates
1363     a SCSI Bus Reset and issuing any SCSI commands.  Some SCSI devices get
1364     confused if they receive SCSI commands too soon after a SCSI Bus Reset.
1365   */
1366   BusLogic_Delay(HostAdapter->BusSettleTime);
1367   /*
1368     Issue the Inquire Installed Devices ID 0 to 7 command, and for Wide SCSI
1369     Host Adapters the Inquire Installed Devices ID 8 to 15 command.  This is
1370     necessary to force Synchronous Transfer Negotiation so that the Inquire
1371     Setup Information and Inquire Synchronous Period commands will return
1372     valid data.
1373   */
1374   if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
1375                        NULL, 0, &InstalledDevicesID0to7,
1376                        sizeof(InstalledDevicesID0to7))
1377       != sizeof(InstalledDevicesID0to7))
1378     return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7");
1379   if (HostAdapter->HostWideSCSI)
1380     if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID8to15,
1381                          NULL, 0, &InstalledDevicesID8to15,
1382                          sizeof(InstalledDevicesID8to15))
1383         != sizeof(InstalledDevicesID8to15))
1384       return BusLogic_Failure(HostAdapter,
1385                               "INQUIRE INSTALLED DEVICES ID 8 TO 15");
1386   /*
1387     Issue the Inquire Setup Information command.
1388   */
1389   RequestedReplyLength = sizeof(SetupInformation);
1390   if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
1391                        &RequestedReplyLength, sizeof(RequestedReplyLength),
1392                        &SetupInformation, sizeof(SetupInformation))
1393       != sizeof(SetupInformation))
1394     return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
1395   /*
1396     Issue the Inquire Synchronous Period command.
1397   */
1398   RequestedReplyLength = sizeof(SynchronousPeriod);
1399   if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
1400                        &RequestedReplyLength, 1,
1401                        &SynchronousPeriod, sizeof(SynchronousPeriod))
1402       != sizeof(SynchronousPeriod))
1403     return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
1404   /*
1405     Save the Installed Devices, Synchronous Values, and Synchronous Period
1406     information in the Host Adapter structure.
1407   */
1408   memcpy(HostAdapter->InstalledDevices, InstalledDevicesID0to7,
1409          sizeof(BusLogic_InstalledDevices8_T));
1410   memcpy(HostAdapter->SynchronousValues,
1411          SetupInformation.SynchronousValuesID0to7,
1412          sizeof(BusLogic_SynchronousValues8_T));
1413   if (HostAdapter->HostWideSCSI)
1414     {
1415       memcpy(&HostAdapter->InstalledDevices[8], InstalledDevicesID8to15,
1416              sizeof(BusLogic_InstalledDevices8_T));
1417       memcpy(&HostAdapter->SynchronousValues[8],
1418              SetupInformation.SynchronousValuesID8to15,
1419              sizeof(BusLogic_SynchronousValues8_T));
1420     }
1421   memcpy(HostAdapter->SynchronousPeriod, SynchronousPeriod,
1422          sizeof(BusLogic_SynchronousPeriod_T));
1423   for (TargetID = 0; TargetID < HostAdapter->MaxTargetIDs; TargetID++)
1424     if (HostAdapter->InstalledDevices[TargetID] != 0)
1425       {
1426         int SynchronousPeriod = HostAdapter->SynchronousPeriod[TargetID];
1427         if (SynchronousPeriod > 10)
1428           {
1429             int SynchronousTransferRate = 100000000 / SynchronousPeriod;
1430             int RoundedSynchronousTransferRate =
1431               (SynchronousTransferRate + 5000) / 10000;
1432             printk("scsi%d:   Target %d: Synchronous at "
1433                    "%d.%02d mega-transfers/sec, offset %d\n",
1434                    HostAdapter->HostNumber, TargetID,
1435                    RoundedSynchronousTransferRate / 100,
1436                    RoundedSynchronousTransferRate % 100,
1437                    HostAdapter->SynchronousValues[TargetID].Offset);
1438           }
1439         else if (SynchronousPeriod > 0)
1440           {
1441             int SynchronousTransferRate = 100000000 / SynchronousPeriod;
1442             int RoundedSynchronousTransferRate =
1443               (SynchronousTransferRate + 50000) / 100000;
1444             printk("scsi%d:   Target %d: Synchronous at "
1445                    "%d.%01d mega-transfers/sec, offset %d\n",
1446                    HostAdapter->HostNumber, TargetID,
1447                    RoundedSynchronousTransferRate / 10,
1448                    RoundedSynchronousTransferRate % 10,
1449                    HostAdapter->SynchronousValues[TargetID].Offset);
1450           }
1451         else printk("scsi%d:   Target %d: Asynchronous\n",
1452                     HostAdapter->HostNumber, TargetID);
1453         TargetDevicesFound++;
1454       }
1455   if (TargetDevicesFound == 0)
1456     printk("scsi%d:   No Target Devices Found\n", HostAdapter->HostNumber);
1457   /*
1458     Indicate the Target Device Inquiry completed successfully.
1459   */
1460   return true;
1461 }
1462 
1463 
1464 /*
1465   BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
1466   I/O Addresses where they may be located, initializing, registering, and
1467   reporting the configuration of each BusLogic Host Adapter it finds.  It
1468   returns the number of BusLogic Host Adapters successfully initialized and
1469   registered.
1470 */
1471 
1472 int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
     /* [previous][next][first][last][top][bottom][index][help] */
1473 {
1474   int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0;
1475   int AddressProbeIndex = 0;
1476   BusLogic_InitializeAddressProbeList();
1477   while (BusLogic_IO_AddressProbeList[AddressProbeIndex] > 0)
1478     {
1479       BusLogic_HostAdapter_T HostAdapterPrototype;
1480       BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype;
1481       SCSI_Host_T *Host;
1482       memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
1483       HostAdapter->IO_Address =
1484         BusLogic_IO_AddressProbeList[AddressProbeIndex++];
1485       /*
1486         Initialize the Command Line Entry field if an explicit I/O Address
1487         was specified.
1488       */
1489       if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount &&
1490           BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address ==
1491           HostAdapter->IO_Address)
1492         HostAdapter->CommandLineEntry =
1493           &BusLogic_CommandLineEntries[CommandLineEntryIndex++];
1494       /*
1495         Check whether the I/O Address range is already in use.
1496       */
1497       if (check_region(HostAdapter->IO_Address, BusLogic_IO_PortCount) < 0)
1498         continue;
1499       /*
1500         Probe the Host Adapter.  If unsuccessful, abort further initialization.
1501       */
1502       if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
1503       /*
1504         Hard Reset the Host Adapter.  If unsuccessful, abort further
1505         initialization.
1506       */
1507       if (!BusLogic_HardResetHostAdapter(HostAdapter)) continue;
1508       /*
1509         Check the Host Adapter.  If unsuccessful, abort further initialization.
1510       */
1511       if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
1512       /*
1513         Initialize the Command Line Entry field if an explicit I/O Address
1514         was not specified.
1515       */
1516       if (CommandLineEntryIndex < BusLogic_CommandLineEntryCount &&
1517           BusLogic_CommandLineEntries[CommandLineEntryIndex].IO_Address == 0)
1518         HostAdapter->CommandLineEntry =
1519           &BusLogic_CommandLineEntries[CommandLineEntryIndex++];
1520       /*
1521         Announce the Driver Version and Date, Author's Name, Copyright Notice,
1522         and Contact Address.
1523       */
1524       BusLogic_AnnounceDriver();
1525       /*
1526         Register usage of the I/O Address range.  From this point onward, any
1527         failure will be assumed to be due to a problem with the Host Adapter,
1528         rather than due to having mistakenly identified this port as belonging
1529         to a BusLogic Host Adapter.  The I/O Address range will not be
1530         released, thereby preventing it from being incorrectly identified as
1531         any other type of Host Adapter.
1532       */
1533       request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount,
1534                      "BusLogic");
1535       /*
1536         Register the SCSI Host structure.
1537       */
1538       HostTemplate->proc_dir = &BusLogic_ProcDirectoryEntry;
1539       Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T));
1540       HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata;
1541       memcpy(HostAdapter, &HostAdapterPrototype,
1542              sizeof(BusLogic_HostAdapter_T));
1543       HostAdapter->SCSI_Host = Host;
1544       HostAdapter->HostNumber = Host->host_no;
1545       /*
1546         Add Host Adapter to the end of the list of registered BusLogic
1547         Host Adapters.  In order for Command Complete Interrupts to be
1548         properly dismissed by BusLogic_InterruptHandler, the Host Adapter
1549         must be registered.  This must be done before the IRQ Channel is
1550         acquired, and in a shared IRQ Channel environment, must be done
1551         before any Command Complete Interrupts occur, since the IRQ Channel
1552         may have already been acquired by a previous BusLogic Host Adapter.
1553       */
1554       BusLogic_RegisterHostAdapter(HostAdapter);
1555       /*
1556         Read the Host Adapter Configuration, Acquire the System Resources
1557         necessary to use Host Adapter and initialize the fields in the SCSI
1558         Host structure, then Test Interrupts, Create the CCBs, and finally
1559         Initialize the Host Adapter.
1560       */
1561       if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
1562           BusLogic_AcquireResources(HostAdapter, Host) &&
1563           BusLogic_TestInterrupts(HostAdapter) &&
1564           BusLogic_CreateCCBs(HostAdapter) &&
1565           BusLogic_InitializeHostAdapter(HostAdapter) &&
1566           BusLogic_InquireTargetDevices(HostAdapter))
1567         {
1568           /*
1569             Initialization has been completed successfully.  Release and
1570             re-register usage of the I/O Address range so that the Model
1571             Name of the Host Adapter will appear.
1572           */
1573           release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount);
1574           request_region(HostAdapter->IO_Address, BusLogic_IO_PortCount,
1575                          HostAdapter->BoardName);
1576           BusLogicHostAdapterCount++;
1577         }
1578       else
1579         {
1580           /*
1581             An error occurred during Host Adapter Configuration Querying,
1582             Resource Acquisition, Interrupt Testing, CCB Creation, or Host
1583             Adapter Initialization, so remove Host Adapter from the list of
1584             registered BusLogic Host Adapters, destroy the CCBs, Release
1585             the System Resources, and Unregister the SCSI Host.
1586           */
1587           BusLogic_DestroyCCBs(HostAdapter);
1588           BusLogic_ReleaseResources(HostAdapter);
1589           BusLogic_UnregisterHostAdapter(HostAdapter);
1590           scsi_unregister(Host);
1591         }
1592     }
1593   return BusLogicHostAdapterCount;
1594 }
1595 
1596 
1597 /*
1598   BusLogic_ReleaseHostAdapter releases all resources previously acquired to
1599   support a specific Host Adapter, including the I/O Address range, and
1600   unregisters the BusLogic Host Adapter.
1601 */
1602 
1603 int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
     /* [previous][next][first][last][top][bottom][index][help] */
1604 {
1605   BusLogic_HostAdapter_T *HostAdapter =
1606     (BusLogic_HostAdapter_T *) Host->hostdata;
1607   /*
1608     Destroy the CCBs and release any system resources acquired to use
1609     Host Adapter.
1610   */
1611   BusLogic_DestroyCCBs(HostAdapter);
1612   BusLogic_ReleaseResources(HostAdapter);
1613   /*
1614     Release usage of the I/O Address range.
1615   */
1616   release_region(HostAdapter->IO_Address, BusLogic_IO_PortCount);
1617   /*
1618     Remove Host Adapter from the list of registered BusLogic Host Adapters.
1619   */
1620   BusLogic_UnregisterHostAdapter(HostAdapter);
1621   return 0;
1622 }
1623 
1624 
1625 /*
1626   BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
1627   the Host Adapter Status and Target Device Status.
1628 */
1629 
1630 static int BusLogic_ComputeResultCode(BusLogic_HostAdapterStatus_T
     /* [previous][next][first][last][top][bottom][index][help] */
1631                                         HostAdapterStatus,
1632                                       BusLogic_TargetDeviceStatus_T
1633                                         TargetDeviceStatus)
1634 {
1635   int HostStatus;
1636   switch (HostAdapterStatus)
1637     {
1638     case BusLogic_CommandCompletedNormally:
1639     case BusLogic_LinkedCommandCompleted:
1640     case BusLogic_LinkedCommandCompletedWithFlag:
1641       HostStatus = DID_OK;
1642       break;
1643     case BusLogic_SCSISelectionTimeout:
1644       HostStatus = DID_TIME_OUT;
1645       break;
1646     case BusLogic_InvalidOutgoingMailboxActionCode:
1647     case BusLogic_InvalidCommandOperationCode:
1648     case BusLogic_InvalidCommandParameter:
1649       printk("BusLogic: BusLogic Driver Protocol Error 0x%02X\n",
1650              HostAdapterStatus);
1651     case BusLogic_DataOverUnderRun:
1652     case BusLogic_UnexpectedBusFree:
1653     case BusLogic_LinkedCCBhasInvalidLUN:
1654     case BusLogic_AutoRequestSenseFailed:
1655     case BusLogic_TaggedQueuingMessageRejected:
1656     case BusLogic_UnsupportedMessageReceived:
1657     case BusLogic_HostAdapterHardwareFailed:
1658     case BusLogic_TargetDeviceReconnectedImproperly:
1659     case BusLogic_AbortQueueGenerated:
1660     case BusLogic_HostAdapterSoftwareError:
1661     case BusLogic_HostAdapterHardwareTimeoutError:
1662     case BusLogic_SCSIParityErrorDetected:
1663       HostStatus = DID_ERROR;
1664       break;
1665     case BusLogic_InvalidBusPhaseRequested:
1666     case BusLogic_TargetFailedResponseToATN:
1667     case BusLogic_HostAdapterAssertedRST:
1668     case BusLogic_OtherDeviceAssertedRST:
1669     case BusLogic_HostAdapterAssertedBusDeviceReset:
1670       HostStatus = DID_RESET;
1671       break;
1672     default:
1673       printk("BusLogic: unknown Host Adapter Status 0x%02X\n",
1674              HostAdapterStatus);
1675       HostStatus = DID_ERROR;
1676       break;
1677     }
1678   return (HostStatus << 16) | TargetDeviceStatus;
1679 }
1680 
1681 
1682 /*
1683   BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
1684   Adapters.  To simplify handling shared IRQ Channels, all installed BusLogic
1685   Host Adapters are scanned whenever any one of them signals a hardware
1686   interrupt.
1687 */
1688 
1689 static void BusLogic_InterruptHandler(int IRQ_Channel,
     /* [previous][next][first][last][top][bottom][index][help] */
1690                                       Registers_T *InterruptRegisters)
1691 {
1692   BusLogic_CCB_T *FirstCompletedCCB = NULL, *LastCompletedCCB = NULL;
1693   BusLogic_HostAdapter_T *HostAdapter;
1694   int HostAdapterResetPendingCount = 0;
1695   /*
1696     Iterate over the installed BusLogic Host Adapters accepting any Incoming
1697     Mailbox entries and saving the completed CCBs for processing.  This
1698     interrupt handler is installed with SA_INTERRUPT, so interrupts are
1699     disabled when the interrupt handler is entered.
1700   */
1701   for (HostAdapter = BusLogic_RegisteredHostAdapters;
1702        HostAdapter != NULL;
1703        HostAdapter = HostAdapter->Next)
1704     {
1705       unsigned char InterruptRegister;
1706       /*
1707         Acquire exclusive access to Host Adapter.
1708       */
1709       BusLogic_LockHostAdapterID(HostAdapter);
1710       /*
1711         Read the Host Adapter Interrupt Register.
1712       */
1713       InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter);
1714       if (InterruptRegister & BusLogic_InterruptValid)
1715         {
1716           /*
1717             Acknowledge the interrupt and reset the Host Adapter
1718             Interrupt Register.
1719           */
1720           BusLogic_WriteControlRegister(HostAdapter, BusLogic_InterruptReset);
1721           /*
1722             Process valid SCSI Reset State and Incoming Mailbox Loaded
1723             interrupts.  Command Complete interrupts are noted, and
1724             Outgoing Mailbox Available interrupts are ignored, as they
1725             are never enabled.
1726           */
1727           if (InterruptRegister & BusLogic_SCSIResetState)
1728             {
1729               HostAdapter->HostAdapterResetPending = true;
1730               HostAdapterResetPendingCount++;
1731             }
1732           else if (InterruptRegister & BusLogic_IncomingMailboxLoaded)
1733             {
1734               /*
1735                 Scan through the Incoming Mailboxes in Strict Round Robin
1736                 fashion, saving any completed CCBs for further processing.
1737                 It is essential that for each CCB and SCSI Command issued,
1738                 completion processing is performed exactly once.  Therefore,
1739                 only Incoming Mailbox entries with completion code Command
1740                 Completed Without Error, Command Completed With Error, or
1741                 Command Aborted At Host Request are saved for completion
1742                 processing.  When an Incoming Mailbox entry has a completion
1743                 code of Aborted Command Not Found, the CCB had already
1744                 completed or been aborted before the current Abort request
1745                 was processed, and so completion processing has already
1746                 occurred and no further action should be taken.
1747               */
1748               BusLogic_IncomingMailbox_T *NextIncomingMailbox =
1749                 HostAdapter->NextIncomingMailbox;
1750               while (NextIncomingMailbox->CompletionCode !=
1751                      BusLogic_IncomingMailboxFree)
1752                 {
1753                   BusLogic_CCB_T *CCB = NextIncomingMailbox->CCB;
1754                   BusLogic_CompletionCode_T MailboxCompletionCode =
1755                     NextIncomingMailbox->CompletionCode;
1756                   if (MailboxCompletionCode != BusLogic_AbortedCommandNotFound)
1757                     {
1758                       /*
1759                         Mark this CCB as completed and add it to the end
1760                         of the list of completed CCBs.
1761                       */
1762                       CCB->Status = BusLogic_CCB_Completed;
1763                       CCB->MailboxCompletionCode = MailboxCompletionCode;
1764                       CCB->Next = NULL;
1765                       if (FirstCompletedCCB == NULL)
1766                         {
1767                           FirstCompletedCCB = CCB;
1768                           LastCompletedCCB = CCB;
1769                         }
1770                       else
1771                         {
1772                           LastCompletedCCB->Next = CCB;
1773                           LastCompletedCCB = CCB;
1774                         }
1775                     }
1776                   else printk("scsi%d: Aborted CCB #%d Not Found\n",
1777                               HostAdapter->HostNumber, CCB->SerialNumber);
1778                   NextIncomingMailbox->CompletionCode =
1779                     BusLogic_IncomingMailboxFree;
1780                   if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
1781                     NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
1782                 }
1783               HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
1784             }
1785           else if (InterruptRegister & BusLogic_CommandComplete)
1786             HostAdapter->HostAdapterCommandCompleted = true;
1787         }
1788       /*
1789         Release exclusive access to Host Adapter.
1790       */
1791       BusLogic_UnlockHostAdapterID(HostAdapter);
1792     }
1793   /*
1794     Enable interrupts while the completed CCBs are processed.
1795   */
1796   sti();
1797   /*
1798     Iterate over the Host Adapters performing any pending Host Adapter Resets.
1799   */
1800   if (HostAdapterResetPendingCount > 0)
1801     for (HostAdapter = BusLogic_RegisteredHostAdapters;
1802          HostAdapter != NULL;
1803          HostAdapter = HostAdapter->Next)
1804       if (HostAdapter->HostAdapterResetPending)
1805         {
1806           BusLogic_ResetHostAdapter(HostAdapter, NULL);
1807           HostAdapter->HostAdapterResetPending = false;
1808           scsi_mark_host_bus_reset(HostAdapter->SCSI_Host);
1809         }
1810   /*
1811     Iterate over the completed CCBs setting the SCSI Command Result Codes,
1812     deallocating the CCBs, and calling the Completion Routines.
1813   */
1814   while (FirstCompletedCCB != NULL)
1815     {
1816       BusLogic_CCB_T *CCB = FirstCompletedCCB;
1817       SCSI_Command_T *Command = CCB->Command;
1818       FirstCompletedCCB = FirstCompletedCCB->Next;
1819       HostAdapter = CCB->HostAdapter;
1820       /*
1821         Bus Device Reset CCBs have the Command field non-NULL only when a Bus
1822         Device Reset was requested for a command that was not currently active
1823         in the Host Adapter, and hence would not have its Completion Routine
1824         called otherwise.
1825       */
1826       if (CCB->Opcode == BusLogic_SCSIBusDeviceReset)
1827         {
1828           printk("scsi%d: Bus Device Reset CCB #%d to Target %d Completed\n",
1829                  HostAdapter->HostNumber, CCB->SerialNumber, CCB->TargetID);
1830           if (Command != NULL) Command->result = DID_RESET << 16;
1831         }
1832       else
1833         /*
1834           Translate the Mailbox Completion Code, Host Adapter Status, and
1835           Target Device Status into a SCSI Subsystem Result Code.
1836         */
1837         switch (CCB->MailboxCompletionCode)
1838           {
1839           case BusLogic_IncomingMailboxFree:
1840           case BusLogic_AbortedCommandNotFound:
1841             printk("scsi%d: CCB #%d Impossible State\n",
1842                    HostAdapter->HostNumber, CCB->SerialNumber);
1843             break;
1844           case BusLogic_CommandCompletedWithoutError:
1845             HostAdapter->CommandSuccessfulFlag[CCB->TargetID] = true;
1846             Command->result = DID_OK << 16;
1847             break;
1848           case BusLogic_CommandAbortedAtHostRequest:
1849             printk("scsi%d: CCB #%d Aborted\n",
1850                    HostAdapter->HostNumber, CCB->SerialNumber);
1851             Command->result = DID_ABORT << 16;
1852             break;
1853           case BusLogic_CommandCompletedWithError:
1854             Command->result =
1855               BusLogic_ComputeResultCode(CCB->HostAdapterStatus,
1856                                          CCB->TargetDeviceStatus);
1857             if (BusLogic_TracingOptions & BusLogic_TraceErrors)
1858               if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
1859                 {
1860                   int i;
1861                   printk("scsi%d: CCB #%d Target %d: Result %X "
1862                          "Host Adapter Status %02X Target Status %02X\n",
1863                          HostAdapter->HostNumber, CCB->SerialNumber,
1864                          CCB->TargetID, Command->result,
1865                          CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
1866                   printk("scsi%d: CDB   ", HostAdapter->HostNumber);
1867                   for (i = 0; i < CCB->CDB_Length; i++)
1868                     printk(" %02X", CCB->CDB[i]);
1869                   printk("\n");
1870                   printk("scsi%d: Sense ", HostAdapter->HostNumber);
1871                   for (i = 0; i < CCB->SenseDataLength; i++)
1872                     printk(" %02X", (*CCB->SenseDataPointer)[i]);
1873                   printk("\n");
1874                 }
1875             break;
1876           }
1877       /*
1878         Place CCB back on the Host Adapter's free list.
1879       */
1880       BusLogic_DeallocateCCB(CCB);
1881       /*
1882         Call the SCSI Command Completion Routine if appropriate.
1883       */
1884       if (Command != NULL) Command->scsi_done(Command);
1885     }
1886 }
1887 
1888 
1889 /*
1890   BusLogic_WriteOutgoingMailboxEntry writes an Outgoing Mailbox entry
1891   for Host Adapter with Action Code and CCB.
1892 */
1893 
1894 static boolean BusLogic_WriteOutgoingMailboxEntry(BusLogic_HostAdapter_T
     /* [previous][next][first][last][top][bottom][index][help] */
1895                                                     *HostAdapter,
1896                                                   BusLogic_ActionCode_T
1897                                                     ActionCode,
1898                                                   BusLogic_CCB_T *CCB)
1899 {
1900   BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
1901   boolean Result = false;
1902   BusLogic_LockHostAdapter(HostAdapter);
1903   NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
1904   if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
1905     {
1906       NextOutgoingMailbox->ActionCode = ActionCode;
1907       NextOutgoingMailbox->CCB = CCB;
1908       CCB->Status = BusLogic_CCB_Active;
1909       BusLogic_StartMailboxScan(HostAdapter);
1910       if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
1911         NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
1912       HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
1913       Result = true;
1914     }
1915   BusLogic_UnlockHostAdapter(HostAdapter);
1916   return Result;
1917 }
1918 
1919 
1920 /*
1921   BusLogic_QueueCommand creates a CCB for Command and places it into an
1922   Outgoing Mailbox for execution by the associated Host Adapter.
1923 */
1924 
1925 int BusLogic_QueueCommand(SCSI_Command_T *Command,
     /* [previous][next][first][last][top][bottom][index][help] */
1926                           void (*CompletionRoutine)(SCSI_Command_T *))
1927 {
1928   BusLogic_HostAdapter_T *HostAdapter =
1929     (BusLogic_HostAdapter_T *) Command->host->hostdata;
1930   unsigned char *CDB = Command->cmnd;
1931   unsigned char CDB_Length = Command->cmd_len;
1932   unsigned char TargetID = Command->target;
1933   unsigned char LogicalUnit = Command->lun;
1934   void *BufferPointer = Command->request_buffer;
1935   int BufferLength = Command->request_bufflen;
1936   int SegmentCount = Command->use_sg;
1937   BusLogic_CCB_T *CCB;
1938   long EnableTQ;
1939   /*
1940     SCSI REQUEST_SENSE commands will be executed automatically by the Host
1941     Adapter for any errors, so they should not be executed explicitly unless
1942     the Sense Data is zero indicating that no error occurred.
1943   */
1944   if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
1945     {
1946       Command->result = DID_OK << 16;
1947       CompletionRoutine(Command);
1948       return 0;
1949     }
1950   /*
1951     Allocate a CCB from the Host Adapter's free list, aborting the command
1952     with an error if there are none available and memory allocation fails.
1953   */
1954   CCB = BusLogic_AllocateCCB(HostAdapter);
1955   if (CCB == NULL)
1956     {
1957       Command->result = DID_ERROR << 16;
1958       CompletionRoutine(Command);
1959       return 0;
1960     }
1961   /*
1962     Initialize the fields in the BusLogic Command Control Block (CCB).
1963   */
1964   if (SegmentCount == 0)
1965     {
1966       CCB->Opcode = BusLogic_InitiatorCCB;
1967       CCB->DataLength = BufferLength;
1968       CCB->DataPointer = BufferPointer;
1969     }
1970   else
1971     {
1972       SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer;
1973       int Segment;
1974       CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
1975       CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T);
1976       CCB->DataPointer = CCB->ScatterGatherList;
1977       for (Segment = 0; Segment < SegmentCount; Segment++)
1978         {
1979           CCB->ScatterGatherList[Segment].SegmentByteCount =
1980             ScatterList[Segment].length;
1981           CCB->ScatterGatherList[Segment].SegmentDataPointer =
1982             ScatterList[Segment].address;
1983         }
1984     }
1985   switch (CDB[0])
1986     {
1987     case READ_6:
1988     case READ_10:
1989       CCB->DataDirection = BusLogic_DataInLengthChecked;
1990       HostAdapter->ReadWriteOperationCount[TargetID]++;
1991       break;
1992     case WRITE_6:
1993     case WRITE_10:
1994       CCB->DataDirection = BusLogic_DataOutLengthChecked;
1995       HostAdapter->ReadWriteOperationCount[TargetID]++;
1996       break;
1997     default:
1998       CCB->DataDirection = BusLogic_UncheckedDataTransfer;
1999       break;
2000     }
2001   CCB->CDB_Length = CDB_Length;
2002   CCB->SenseDataLength = sizeof(Command->sense_buffer);
2003   CCB->TargetID = TargetID;
2004   CCB->LogicalUnit = LogicalUnit;
2005   /*
2006     For Wide SCSI Host Adapters, Wide Mode CCBs are used to support more than
2007     8 Logical Units per Target, and this requires setting the overloaded
2008     TagEnable field to Logical Unit bit 5.
2009   */
2010   if (HostAdapter->HostWideSCSI)
2011     {
2012       CCB->TagEnable = LogicalUnit >> 5;
2013       CCB->WideModeTagEnable = false;
2014     }
2015   else CCB->TagEnable = false;
2016   /*
2017     BusLogic recommends that after a Reset the first couple of commands that
2018     are sent to a Target be sent in a non Tagged Queue fashion so that the Host
2019     Adapter and Target can establish Synchronous Transfer before Queue Tag
2020     messages can interfere with the Synchronous Negotiation message.
2021   */
2022   if ((HostAdapter->TaggedQueuingPermitted & (1 << TargetID)) &&
2023       Command->device->tagged_supported &&
2024       (EnableTQ = HostAdapter->ReadWriteOperationCount[TargetID] - 5) >= 0)
2025     {
2026       if (EnableTQ == 0)
2027         printk("scsi%d: Tagged Queuing now active for Target %d\n",
2028                HostAdapter->HostNumber, TargetID);
2029       if (HostAdapter->HostWideSCSI)
2030         {
2031           CCB->WideModeTagEnable = true;
2032           CCB->WideModeQueueTag = BusLogic_SimpleQueueTag;
2033         }
2034       else
2035         {
2036           CCB->TagEnable = true;
2037           CCB->QueueTag = BusLogic_SimpleQueueTag;
2038         }
2039     }
2040   memcpy(CCB->CDB, CDB, CDB_Length);
2041   CCB->SenseDataPointer = (SCSI_SenseData_T *) &Command->sense_buffer;
2042   CCB->Command = Command;
2043   Command->scsi_done = CompletionRoutine;
2044   /*
2045     Place the CCB in an Outgoing Mailbox, aborting the command with an
2046     error if there are none available.
2047   */
2048   if (!(BusLogic_WriteOutgoingMailboxEntry(
2049           HostAdapter, BusLogic_MailboxStartCommand, CCB)))
2050     {
2051       printk("scsi%d: cannot write Outgoing Mailbox Entry\n",
2052              HostAdapter->HostNumber);
2053       BusLogic_DeallocateCCB(CCB);
2054       Command->result = DID_ERROR << 16;
2055       CompletionRoutine(Command);
2056     }
2057   return 0;
2058 }
2059 
2060 
2061 /*
2062   BusLogic_AbortCommand aborts Command if possible.
2063 */
2064 
2065 int BusLogic_AbortCommand(SCSI_Command_T *Command)
     /* [previous][next][first][last][top][bottom][index][help] */
2066 {
2067   BusLogic_HostAdapter_T *HostAdapter =
2068     (BusLogic_HostAdapter_T *) Command->host->hostdata;
2069   unsigned char InterruptRegister;
2070   BusLogic_CCB_T *CCB;
2071   int Result;
2072   /*
2073     If the Host Adapter has posted an interrupt but the Interrupt Handler
2074     has not been called for some reason (i.e. the interrupt was lost), try
2075     calling the Interrupt Handler directly to process the commands that
2076     have been completed.
2077   */
2078   InterruptRegister = BusLogic_ReadInterruptRegister(HostAdapter);
2079   if (InterruptRegister & BusLogic_InterruptValid)
2080     {
2081       unsigned long ProcessorFlags;
2082       printk("scsi%d: Recovering Lost Interrupt for IRQ Channel %d\n",
2083              HostAdapter->HostNumber, HostAdapter->IRQ_Channel);
2084       save_flags(ProcessorFlags);
2085       cli();
2086       BusLogic_InterruptHandler(HostAdapter->IRQ_Channel, NULL);
2087       restore_flags(ProcessorFlags);
2088       return SCSI_ABORT_SNOOZE;
2089     }
2090   /*
2091     Find the CCB to be aborted and determine how to proceed.
2092   */
2093   BusLogic_LockHostAdapter(HostAdapter);
2094   Result = SCSI_ABORT_NOT_RUNNING;
2095   for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
2096     if (CCB->Command == Command)
2097       {
2098         if (CCB->Status == BusLogic_CCB_Active)
2099           if ((HostAdapter->HostWideSCSI && CCB->WideModeTagEnable &&
2100                CCB->WideModeQueueTag != BusLogic_SimpleQueueTag) ||
2101               (!HostAdapter->HostWideSCSI && CCB->TagEnable &&
2102                CCB->QueueTag != BusLogic_SimpleQueueTag))
2103             {
2104               /*
2105                 CCBs using Tagged Queuing with other than Simple Queue Tag
2106                 should not be aborted.
2107               */
2108               Result = SCSI_ABORT_BUSY;
2109             }
2110           else
2111             {
2112               /*
2113                 Attempt to abort the CCB.
2114               */
2115               if (BusLogic_WriteOutgoingMailboxEntry(
2116                     HostAdapter, BusLogic_MailboxAbortCommand, CCB))
2117                 {
2118                   printk("scsi%d: Aborting CCB #%d\n",
2119                          HostAdapter->HostNumber, CCB->SerialNumber);
2120                   Result = SCSI_ABORT_PENDING;
2121                 }
2122               else Result = SCSI_ABORT_BUSY;
2123             }
2124         break;
2125       }
2126   BusLogic_UnlockHostAdapter(HostAdapter);
2127   return Result;
2128 }
2129 
2130 
2131 /*
2132   BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
2133   currently executing SCSI commands as having been reset, as well as
2134   the specified Command if non-NULL.
2135 */
2136 
2137 static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
     /* [previous][next][first][last][top][bottom][index][help] */
2138                                      SCSI_Command_T *Command)
2139 {
2140   BusLogic_CCB_T *CCB;
2141   if (Command == NULL)
2142     printk("scsi%d: Resetting %s due to SCSI Reset State Interrupt\n",
2143            HostAdapter->HostNumber, HostAdapter->BoardName);
2144   else printk("scsi%d: Resetting %s due to Target %d\n",
2145               HostAdapter->HostNumber, HostAdapter->BoardName, Command->target);
2146   /*
2147     Attempt to Reset and Reinitialize the Host Adapter.
2148   */
2149   BusLogic_LockHostAdapter(HostAdapter);
2150   if (!(BusLogic_HardResetHostAdapter(HostAdapter) &&
2151         BusLogic_InitializeHostAdapter(HostAdapter)))
2152     {
2153       printk("scsi%d: Resetting %s Failed\n",
2154               HostAdapter->HostNumber, HostAdapter->BoardName);
2155       BusLogic_UnlockHostAdapter(HostAdapter);
2156       return SCSI_RESET_ERROR;
2157     }
2158   BusLogic_UnlockHostAdapter(HostAdapter);
2159   /*
2160     Wait a few seconds between the Host Adapter Hard Reset which initiates
2161     a SCSI Bus Reset and issuing any SCSI commands.  Some SCSI devices get
2162     confused if they receive SCSI commands too soon after a SCSI Bus Reset.
2163   */
2164   BusLogic_Delay(HostAdapter->BusSettleTime);
2165   /*
2166     Mark all currently executing CCBs as having been reset.
2167   */
2168   for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
2169     if (CCB->Status == BusLogic_CCB_Active)
2170       {
2171         SCSI_Command_T *ActiveCommand = CCB->Command;
2172         if (ActiveCommand == Command) Command = NULL;
2173         BusLogic_DeallocateCCB(CCB);
2174         if (ActiveCommand != NULL)
2175           {
2176             ActiveCommand->result = DID_RESET << 16;
2177             ActiveCommand->scsi_done(ActiveCommand);
2178           }
2179       }
2180   if (Command != NULL)
2181     {
2182       Command->result = DID_RESET << 16;
2183       Command->scsi_done(Command);
2184     }
2185   return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
2186 }
2187 
2188 
2189 /*
2190   BusLogic_BusDeviceReset sends a Bus Device Reset to the Target
2191   associated with Command.
2192 */
2193 
2194 static int BusLogic_BusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
     /* [previous][next][first][last][top][bottom][index][help] */
2195                                    SCSI_Command_T *Command)
2196 {
2197   BusLogic_CCB_T *CCB = BusLogic_AllocateCCB(HostAdapter), *XCCB;
2198   unsigned char TargetID = Command->target;
2199   /*
2200     If sending a Bus Device Reset is impossible, attempt a full Host
2201     Adapter Hard Reset and SCSI Bus Reset.
2202   */
2203   if (CCB == NULL)
2204     return BusLogic_ResetHostAdapter(HostAdapter, Command);
2205   printk("scsi%d: Sending Bus Device Reset CCB #%d to Target %d\n",
2206          HostAdapter->HostNumber, CCB->SerialNumber, TargetID);
2207   CCB->Opcode = BusLogic_SCSIBusDeviceReset;
2208   CCB->TargetID = TargetID;
2209   CCB->Command = Command;
2210   /*
2211     If there is a currently executing CCB in the Host Adapter for this Command,
2212     then an Incoming Mailbox entry will be made with a completion code of
2213     BusLogic_HostAdapterAssertedBusDeviceReset.  Otherwise, the CCB Command
2214     field will be left pointing to the Command so that the interrupt for the
2215     completion of the Bus Device Reset can call the Completion Routine for the
2216     Command.
2217   */
2218   BusLogic_LockHostAdapter(HostAdapter);
2219   for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll)
2220     if (XCCB->Status == BusLogic_CCB_Active && XCCB->Command == Command)
2221       {
2222         CCB->Command = NULL;
2223         break;
2224       }
2225   BusLogic_UnlockHostAdapter(HostAdapter);
2226   /*
2227     Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
2228     If sending a Bus Device Reset is impossible, attempt a full Host
2229     Adapter Hard Reset and SCSI Bus Reset.
2230   */
2231   if (!(BusLogic_WriteOutgoingMailboxEntry(
2232           HostAdapter, BusLogic_MailboxStartCommand, CCB)))
2233     {
2234       printk("scsi%d: cannot write Outgoing Mailbox Entry for "
2235              "Bus Device Reset\n", HostAdapter->HostNumber);
2236       BusLogic_DeallocateCCB(CCB);
2237       return BusLogic_ResetHostAdapter(HostAdapter, Command);
2238     }
2239   HostAdapter->ReadWriteOperationCount[TargetID] = 0;
2240   return SCSI_RESET_PENDING;
2241 }
2242 
2243 
2244 /*
2245   BusLogic_ResetCommand takes appropriate action to reset Command.
2246 */
2247 
2248 int BusLogic_ResetCommand(SCSI_Command_T *Command)
     /* [previous][next][first][last][top][bottom][index][help] */
2249 {
2250   BusLogic_HostAdapter_T *HostAdapter =
2251     (BusLogic_HostAdapter_T *) Command->host->hostdata;
2252   unsigned char TargetID = Command->target;
2253   unsigned char ErrorRecoveryOption =
2254     HostAdapter->ErrorRecoveryOption[TargetID];
2255   if (ErrorRecoveryOption == BusLogic_ErrorRecoveryDefault)
2256     if (Command->host->suggest_bus_reset)
2257       ErrorRecoveryOption = BusLogic_ErrorRecoveryHardReset;
2258     else ErrorRecoveryOption = BusLogic_ErrorRecoveryBusDeviceReset;
2259   switch (ErrorRecoveryOption)
2260     {
2261     case BusLogic_ErrorRecoveryHardReset:
2262       return BusLogic_ResetHostAdapter(HostAdapter, Command);
2263     case BusLogic_ErrorRecoveryBusDeviceReset:
2264       if (HostAdapter->CommandSuccessfulFlag[TargetID])
2265         {
2266           HostAdapter->CommandSuccessfulFlag[TargetID] = false;
2267           return BusLogic_BusDeviceReset(HostAdapter, Command);
2268         }
2269       else return BusLogic_ResetHostAdapter(HostAdapter, Command);
2270     }
2271   printk("scsi%d: Error Recovery Suppressed\n", HostAdapter->HostNumber);
2272   return SCSI_RESET_PUNT;
2273 }
2274 
2275 
2276 /*
2277   BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
2278   Parameters for Disk.  The default disk geometry is 64 heads, 32 sectors, and
2279   the appropriate number of cylinders so as not to exceed drive capacity.  In
2280   order for disks equal to or larger than 1 GB to be addressable by the BIOS
2281   without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
2282   may be enabled in AutoSCSI on "C" Series boards or by a dip switch setting
2283   on older boards.  With Extended Translation enabled, drives between 1 GB
2284   inclusive and 2 GB exclusive are given a disk geometry of 128 heads and 32
2285   sectors, and drives between 2 GB inclusive and 8 GB exclusive are given a
2286   disk geometry of 255 heads and 63 sectors.  On "C" Series boards the firmware
2287   can be queried for the precise translation in effect for each drive
2288   individually, but there is really no need to do so since we know the total
2289   capacity of the drive and whether Extended Translation is enabled, hence we
2290   can deduce the BIOS disk geometry that must be in effect.
2291 */
2292 
2293 int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
     /* [previous][next][first][last][top][bottom][index][help] */
2294                                 int *Parameters)
2295 {
2296   BusLogic_HostAdapter_T *HostAdapter =
2297     (BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
2298   BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
2299   if (HostAdapter->ExtendedTranslation &&
2300       Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
2301     if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
2302       {
2303         DiskParameters->Heads = 255;
2304         DiskParameters->Sectors = 63;
2305       }
2306     else
2307       {
2308         DiskParameters->Heads = 128;
2309         DiskParameters->Sectors = 32;
2310       }
2311   else
2312     {
2313       DiskParameters->Heads = 64;
2314       DiskParameters->Sectors = 32;
2315     }
2316   DiskParameters->Cylinders =
2317     Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
2318   return 0;
2319 }
2320 
2321 
2322 /*
2323   BusLogic_Setup handles processing of Kernel Command Line Arguments.
2324 
2325   For the BusLogic driver, a kernel command line entry comprises the driver
2326   identifier "BusLogic=" optionally followed by a comma-separated sequence of
2327   integers and then optionally followed by a comma-separated sequence of
2328   strings.  Each command line entry applies to one BusLogic Host Adapter.
2329   Multiple command line entries may be used in systems which contain multiple
2330   BusLogic Host Adapters.
2331 
2332   The first integer specified is the I/O Address at which the Host Adapter is
2333   located.  If unspecified, it defaults to 0 which means to apply this entry to
2334   the first BusLogic Host Adapter found during the default probe sequence.  If
2335   any I/O Address parameters are provided on the command line, then the default
2336   probe sequence is omitted.
2337 
2338   The second integer specified is the number of Concurrent Commands per Logical
2339   Unit to allow for Target Devices on the Host Adapter.  If unspecified, it
2340   defaults to 0 which means to use the value of BusLogic_Concurrency for
2341   non-ISA Host Adapters, or BusLogic_Concurrency_ISA for ISA Host Adapters.
2342 
2343   The third integer specified is the Bus Settle Time in seconds.  This is
2344   the amount of time to wait between a Host Adapter Hard Reset which initiates
2345   a SCSI Bus Reset and issuing any SCSI commands.  If unspecified, it defaults
2346   to 0 which means to use the value of BusLogic_DefaultBusSettleTime.
2347 
2348   The fourth integer specified is the Tracing Options.  If unspecified, it
2349   defaults to 0 which means that no special tracing information is to be
2350   printed.  Note that Tracing Options are applied across all Host Adapters.
2351 
2352   The string options are used to provide control over Tagged Queuing and Error
2353   Recovery. If both Tagged Queuing and Error Recovery strings are provided, the
2354   Tagged Queuing specification string must come first.
2355 
2356   The Tagged Queuing specification begins with "TQ:" and allows for explicitly
2357   specifying whether Tagged Queuing is permitted on Target Devices that support
2358   it.  The following specification options are available:
2359 
2360   TQ:Default            Tagged Queuing will be permitted based on the firmware
2361                         version of the BusLogic Host Adapter and based on
2362                         whether the Concurrency value allows queuing multiple
2363                         commands.
2364 
2365   TQ:Enable             Tagged Queuing will be enabled for all Target Devices
2366                         on this Host Adapter overriding any limitation that
2367                         would otherwise be imposed based on the Host Adapter
2368                         firmware version.
2369 
2370   TQ:Disable            Tagged Queuing will be disabled for all Target Devices
2371                         on this Host Adapter.
2372 
2373   TQ:<Per-Target-Spec>  Tagged Queuing will be controlled individually for each
2374                         Target Device.  <Per-Target-Spec> is a sequence of "Y",
2375                         "N", and "X" characters.  "Y" enabled Tagged Queuing,
2376                         "N" disables Tagged Queuing, and "X" accepts the
2377                         default based on the firmware version.  The first
2378                         character refers to Target 0, the second to Target 1,
2379                         and so on; if the sequence of "Y", "N", and "X"
2380                         characters does not cover all the Target Devices,
2381                         unspecified characters are assumed to be "X".
2382 
2383   Note that explicitly requesting Tagged Queuing may lead to problems; this
2384   facility is provided primarily to allow disabling Tagged Queuing on Target
2385   Devices that do not implement it correctly.
2386 
2387   The Error Recovery specification begins with "ER:" and allows for explicitly
2388   specifying the Error Recovery action to be performed when ResetCommand is
2389   called due to a SCSI Command failing to complete successfully.  The following
2390   specification options are available:
2391 
2392   ER:Default            Error Recovery will select between the Hard Reset and
2393                         Bus Device Reset options based on the recommendation
2394                         of the SCSI Subsystem.
2395 
2396   ER:HardReset          Error Recovery will initiate a Host Adapter Hard Reset
2397                         which also causes a SCSI Bus Reset.
2398 
2399   ER:BusDeviceReset     Error Recovery will send a Bus Device Reset message to
2400                         the individual Target Device causing the error.  If
2401                         Error Recovery is again initiated for this Target
2402                         Device and no SCSI Command to this Target Device has
2403                         completed successfully since the Bus Device Reset
2404                         message was sent, then a Hard Reset will be attempted.
2405 
2406   ER:None               Error Recovery will be suppressed.  This option should
2407                         only be selected if a SCSI Bus Reset or Bus Device
2408                         Reset will cause the Target Device to fail completely
2409                         and unrecoverably.
2410 
2411   ER:<Per-Target-Spec>  Error Recovery will be controlled individually for each
2412                         Target Device.  <Per-Target-Spec> is a sequence of "D",
2413                         "H", "B", and "N" characters.  "D" selects Default, "H"
2414                         selects Hard Reset, "B" selects Bus Device Reset, and
2415                         "N" selects None.  The first character refers to Target
2416                         0, the second to Target 1, and so on; if the sequence
2417                         of "D", "H", "B", and "N" characters does not cover all
2418                         the Target Devices, unspecified characters are assumed
2419                         to be "D".
2420 */
2421 
2422 void BusLogic_Setup(char *Strings, int *Integers)
     /* [previous][next][first][last][top][bottom][index][help] */
2423 {
2424   BusLogic_CommandLineEntry_T *CommandLineEntry =
2425     &BusLogic_CommandLineEntries[BusLogic_CommandLineEntryCount++];
2426   static int ProbeListIndex = 0;
2427   int IntegerCount = Integers[0], TargetID, i;
2428   CommandLineEntry->IO_Address = 0;
2429   CommandLineEntry->Concurrency = 0;
2430   CommandLineEntry->BusSettleTime = 0;
2431   CommandLineEntry->TaggedQueuingPermitted = 0;
2432   CommandLineEntry->TaggedQueuingPermittedMask = 0;
2433   memset(CommandLineEntry->ErrorRecoveryOption,
2434          BusLogic_ErrorRecoveryDefault,
2435          sizeof(CommandLineEntry->ErrorRecoveryOption));
2436   if (IntegerCount > 4)
2437     printk("BusLogic: Unexpected Command Line Integers ignored\n");
2438   if (IntegerCount >= 1)
2439     {
2440       unsigned short IO_Address = Integers[1];
2441       if (IO_Address > 0)
2442         {
2443           for (i = 0; ; i++)
2444             if (BusLogic_IO_StandardAddresses[i] == 0)
2445               {
2446                 printk("BusLogic: Invalid Command Line Entry "
2447                        "(illegal I/O Address 0x%X)\n", IO_Address);
2448                 return;
2449               }
2450             else if (i < ProbeListIndex &&
2451                      IO_Address == BusLogic_IO_AddressProbeList[i])
2452               {
2453                 printk("BusLogic: Invalid Command Line Entry "
2454                        "(duplicate I/O Address 0x%X)\n", IO_Address);
2455                 return;
2456               }
2457             else if (IO_Address == BusLogic_IO_StandardAddresses[i]) break;
2458           BusLogic_IO_AddressProbeList[ProbeListIndex++] = IO_Address;
2459           BusLogic_IO_AddressProbeList[ProbeListIndex] = 0;
2460         }
2461       CommandLineEntry->IO_Address = IO_Address;
2462     }
2463   if (IntegerCount >= 2)
2464     {
2465       unsigned short Concurrency = Integers[2];
2466       if (Concurrency > BusLogic_MailboxCount)
2467         {
2468           printk("BusLogic: Invalid Command Line Entry "
2469                  "(illegal Concurrency %d)\n", Concurrency);
2470           return;
2471         }
2472       CommandLineEntry->Concurrency = Concurrency;
2473     }
2474   if (IntegerCount >= 3)
2475     CommandLineEntry->BusSettleTime = Integers[3];
2476   if (IntegerCount >= 4)
2477     BusLogic_TracingOptions |= Integers[4];
2478   if (!(BusLogic_CommandLineEntryCount == 0 || ProbeListIndex == 0 ||
2479         BusLogic_CommandLineEntryCount == ProbeListIndex))
2480     {
2481       printk("BusLogic: Invalid Command Line Entry "
2482              "(all or no I/O Addresses must be specified)\n");
2483       return;
2484     }
2485   if (Strings == NULL) return;
2486   if (strncmp(Strings, "TQ:", 3) == 0)
2487     {
2488       Strings += 3;
2489       if (strncmp(Strings, "Default", 7) == 0)
2490         Strings += 7;
2491       else if (strncmp(Strings, "Enable", 6) == 0)
2492         {
2493           Strings += 6;
2494           CommandLineEntry->TaggedQueuingPermitted = 0xFFFF;
2495           CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
2496         }
2497       else if (strncmp(Strings, "Disable", 7) == 0)
2498         {
2499           Strings += 7;
2500           CommandLineEntry->TaggedQueuingPermitted = 0x0000;
2501           CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
2502         }
2503       else
2504         for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++)
2505           switch (*Strings++)
2506             {
2507             case 'Y':
2508               CommandLineEntry->TaggedQueuingPermitted |= 1 << TargetID;
2509               CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
2510               break;
2511             case 'N':
2512               CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
2513               break;
2514             case 'X':
2515               break;
2516             default:
2517               Strings--;
2518               TargetID = BusLogic_MaxTargetIDs;
2519               break;
2520             }
2521     }
2522   if (*Strings == ',') Strings++;
2523   if (strncmp(Strings, "ER:", 3) == 0)
2524     {
2525       Strings += 3;
2526       if (strncmp(Strings, "Default", 7) == 0)
2527         Strings += 7;
2528       else if (strncmp(Strings, "HardReset", 9) == 0)
2529         {
2530           Strings += 9;
2531           memset(CommandLineEntry->ErrorRecoveryOption,
2532                  BusLogic_ErrorRecoveryHardReset,
2533                  sizeof(CommandLineEntry->ErrorRecoveryOption));
2534         }
2535       else if (strncmp(Strings, "BusDeviceReset", 14) == 0)
2536         {
2537           Strings += 14;
2538           memset(CommandLineEntry->ErrorRecoveryOption,
2539                  BusLogic_ErrorRecoveryBusDeviceReset,
2540                  sizeof(CommandLineEntry->ErrorRecoveryOption));
2541         }
2542       else if (strncmp(Strings, "None", 4) == 0)
2543         {
2544           Strings += 4;
2545           memset(CommandLineEntry->ErrorRecoveryOption,
2546                  BusLogic_ErrorRecoveryNone,
2547                  sizeof(CommandLineEntry->ErrorRecoveryOption));
2548         }
2549       else
2550         for (TargetID = 0; TargetID < BusLogic_MaxTargetIDs; TargetID++)
2551           switch (*Strings++)
2552             {
2553             case 'D':
2554               CommandLineEntry->ErrorRecoveryOption[TargetID] =
2555                 BusLogic_ErrorRecoveryDefault;
2556               break;
2557             case 'H':
2558               CommandLineEntry->ErrorRecoveryOption[TargetID] =
2559                 BusLogic_ErrorRecoveryHardReset;
2560               break;
2561             case 'B':
2562               CommandLineEntry->ErrorRecoveryOption[TargetID] =
2563                 BusLogic_ErrorRecoveryBusDeviceReset;
2564               break;
2565             case 'N':
2566               CommandLineEntry->ErrorRecoveryOption[TargetID] =
2567                 BusLogic_ErrorRecoveryNone;
2568               break;
2569             default:
2570               Strings--;
2571               TargetID = BusLogic_MaxTargetIDs;
2572               break;
2573             }
2574     }
2575   if (*Strings != '\0')
2576     printk("BusLogic: Unexpected Command Line String '%s' ignored\n", Strings);
2577 }

/* [previous][next][first][last][top][bottom][index][help] */