Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/BusLogic.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.