Annotation of Gnu-Mach/linux/src/drivers/scsi/BusLogic.c, revision 1.1

1.1     ! root        1: /*
        !             2: 
        !             3:   Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
        !             4: 
        !             5:   Copyright 1995-1998 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.
        !            10: 
        !            11:   This program is distributed in the hope that it will be useful, but
        !            12:   WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
        !            13:   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:   for complete details.
        !            15: 
        !            16:   The author respectfully requests that any modifications to this software be
        !            17:   sent directly to him for evaluation and testing.
        !            18: 
        !            19:   Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
        !            20:   advice has been invaluable, to David Gentzel, for writing the original Linux
        !            21:   BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
        !            22: 
        !            23:   Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
        !            24:   Manager available as freely redistributable source code.
        !            25: 
        !            26: */
        !            27: 
        !            28: 
        !            29: #define BusLogic_DriverVersion         "2.0.15"
        !            30: #define BusLogic_DriverDate            "17 August 1998"
        !            31: 
        !            32: 
        !            33: #include <linux/version.h>
        !            34: #include <linux/module.h>
        !            35: #include <linux/config.h>
        !            36: #include <linux/types.h>
        !            37: #include <linux/blkdev.h>
        !            38: #include <linux/delay.h>
        !            39: #include <linux/ioport.h>
        !            40: #include <linux/mm.h>
        !            41: #include <linux/sched.h>
        !            42: #include <linux/stat.h>
        !            43: #include <linux/pci.h>
        !            44: #include <linux/bios32.h>
        !            45: #include <asm/dma.h>
        !            46: #include <asm/io.h>
        !            47: #include <asm/irq.h>
        !            48: #include <asm/system.h>
        !            49: #include "scsi.h"
        !            50: #include "hosts.h"
        !            51: #include "sd.h"
        !            52: #include "BusLogic.h"
        !            53: #include "FlashPoint.c"
        !            54: 
        !            55: 
        !            56: /*
        !            57:   BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
        !            58:   Options specifications provided via the Linux Kernel Command Line or via
        !            59:   the Loadable Kernel Module Installation Facility.
        !            60: */
        !            61: 
        !            62: static int
        !            63:   BusLogic_DriverOptionsCount =                        0;
        !            64: 
        !            65: 
        !            66: /*
        !            67:   BusLogic_DriverOptions is an array of Driver Options structures representing
        !            68:   BusLogic Driver Options specifications provided via the Linux Kernel Command
        !            69:   Line or via the Loadable Kernel Module Installation Facility.
        !            70: */
        !            71: 
        !            72: static BusLogic_DriverOptions_T
        !            73:   BusLogic_DriverOptions[BusLogic_MaxHostAdapters];
        !            74: 
        !            75: 
        !            76: /*
        !            77:   BusLogic_Options can be assigned a string by the Loadable Kernel Module
        !            78:   Installation Facility to be parsed for BusLogic Driver Options
        !            79:   specifications.
        !            80: */
        !            81: 
        !            82: static char
        !            83:   *BusLogic_Options =                          NULL;
        !            84: 
        !            85: 
        !            86: /*
        !            87:   BusLogic_ProbeOptions is a set of Probe Options to be applied across
        !            88:   all BusLogic Host Adapters.
        !            89: */
        !            90: 
        !            91: static BusLogic_ProbeOptions_T
        !            92:   BusLogic_ProbeOptions =                      { 0 };
        !            93: 
        !            94: 
        !            95: /*
        !            96:   BusLogic_GlobalOptions is a set of Global Options to be applied across
        !            97:   all BusLogic Host Adapters.
        !            98: */
        !            99: 
        !           100: static BusLogic_GlobalOptions_T
        !           101:   BusLogic_GlobalOptions =                     { 0 };
        !           102: 
        !           103: 
        !           104: /*
        !           105:   BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter
        !           106:   are pointers to the first and last registered BusLogic Host Adapters.
        !           107: */
        !           108: 
        !           109: static BusLogic_HostAdapter_T
        !           110:   *BusLogic_FirstRegisteredHostAdapter =       NULL,
        !           111:   *BusLogic_LastRegisteredHostAdapter =                NULL;
        !           112: 
        !           113: 
        !           114: /*
        !           115:   BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
        !           116: */
        !           117: 
        !           118: static int
        !           119:   BusLogic_ProbeInfoCount =                    0;
        !           120: 
        !           121: 
        !           122: /*
        !           123:   BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information
        !           124:   to be checked for potential BusLogic Host Adapters.  It is initialized by
        !           125:   interrogating the PCI Configuration Space on PCI machines as well as from the
        !           126:   list of standard BusLogic I/O Addresses.
        !           127: */
        !           128: 
        !           129: static BusLogic_ProbeInfo_T
        !           130:   *BusLogic_ProbeInfoList =                    NULL;
        !           131: 
        !           132: 
        !           133: /*
        !           134:   BusLogic_CommandFailureReason holds a string identifying the reason why a
        !           135:   call to BusLogic_Command failed.  It is only non-NULL when BusLogic_Command
        !           136:   returns a failure code.
        !           137: */
        !           138: 
        !           139: static char
        !           140:   *BusLogic_CommandFailureReason;
        !           141: 
        !           142: 
        !           143: /*
        !           144:   BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
        !           145: */
        !           146: 
        !           147: PROC_DirectoryEntry_T
        !           148:   BusLogic_ProcDirectoryEntry =
        !           149:     { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
        !           150: 
        !           151: 
        !           152: /*
        !           153:   BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
        !           154:   Name, Copyright Notice, and Electronic Mail Address.
        !           155: */
        !           156: 
        !           157: static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter)
        !           158: {
        !           159:   BusLogic_Announce("***** BusLogic SCSI Driver Version "
        !           160:                    BusLogic_DriverVersion " of "
        !           161:                    BusLogic_DriverDate " *****\n", HostAdapter);
        !           162:   BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
        !           163:                    "<[email protected]>\n", HostAdapter);
        !           164: }
        !           165: 
        !           166: 
        !           167: /*
        !           168:   BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI
        !           169:   Driver and Host Adapter.
        !           170: */
        !           171: 
        !           172: const char *BusLogic_DriverInfo(SCSI_Host_T *Host)
        !           173: {
        !           174:   BusLogic_HostAdapter_T *HostAdapter =
        !           175:     (BusLogic_HostAdapter_T *) Host->hostdata;
        !           176:   return HostAdapter->FullModelName;
        !           177: }
        !           178: 
        !           179: 
        !           180: /*
        !           181:   BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
        !           182:   BusLogic Host Adapters.
        !           183: */
        !           184: 
        !           185: static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
        !           186: {
        !           187:   HostAdapter->Next = NULL;
        !           188:   if (BusLogic_FirstRegisteredHostAdapter == NULL)
        !           189:     {
        !           190:       BusLogic_FirstRegisteredHostAdapter = HostAdapter;
        !           191:       BusLogic_LastRegisteredHostAdapter = HostAdapter;
        !           192:     }
        !           193:   else
        !           194:     {
        !           195:       BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
        !           196:       BusLogic_LastRegisteredHostAdapter = HostAdapter;
        !           197:     }
        !           198: }
        !           199: 
        !           200: 
        !           201: /*
        !           202:   BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
        !           203:   registered BusLogic Host Adapters.
        !           204: */
        !           205: 
        !           206: static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
        !           207: {
        !           208:   if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
        !           209:     {
        !           210:       BusLogic_FirstRegisteredHostAdapter =
        !           211:        BusLogic_FirstRegisteredHostAdapter->Next;
        !           212:       if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
        !           213:        BusLogic_LastRegisteredHostAdapter = NULL;
        !           214:     }
        !           215:   else
        !           216:     {
        !           217:       BusLogic_HostAdapter_T *PreviousHostAdapter =
        !           218:        BusLogic_FirstRegisteredHostAdapter;
        !           219:       while (PreviousHostAdapter != NULL &&
        !           220:             PreviousHostAdapter->Next != HostAdapter)
        !           221:        PreviousHostAdapter = PreviousHostAdapter->Next;
        !           222:       if (PreviousHostAdapter != NULL)
        !           223:        PreviousHostAdapter->Next = HostAdapter->Next;
        !           224:     }
        !           225:   HostAdapter->Next = NULL;
        !           226: }
        !           227: 
        !           228: 
        !           229: /*
        !           230:   BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
        !           231:   for Host Adapter from the BlockSize bytes located at BlockPointer.  The newly
        !           232:   created CCBs are added to Host Adapter's free list.
        !           233: */
        !           234: 
        !           235: static void BusLogic_InitializeCCBs(BusLogic_HostAdapter_T *HostAdapter,
        !           236:                                    void *BlockPointer, int BlockSize)
        !           237: {
        !           238:   BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) BlockPointer;
        !           239:   memset(BlockPointer, 0, BlockSize);
        !           240:   CCB->AllocationGroupHead = true;
        !           241:   while ((BlockSize -= sizeof(BusLogic_CCB_T)) >= 0)
        !           242:     {
        !           243:       CCB->Status = BusLogic_CCB_Free;
        !           244:       CCB->HostAdapter = HostAdapter;
        !           245:       if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !           246:        {
        !           247:          CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
        !           248:          CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
        !           249:        }
        !           250:       CCB->Next = HostAdapter->Free_CCBs;
        !           251:       CCB->NextAll = HostAdapter->All_CCBs;
        !           252:       HostAdapter->Free_CCBs = CCB;
        !           253:       HostAdapter->All_CCBs = CCB;
        !           254:       HostAdapter->AllocatedCCBs++;
        !           255:       CCB++;
        !           256:     }
        !           257: }
        !           258: 
        !           259: 
        !           260: /*
        !           261:   BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
        !           262: */
        !           263: 
        !           264: static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter)
        !           265: {
        !           266:   int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
        !           267:   while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs)
        !           268:     {
        !           269:       void *BlockPointer = kmalloc(BlockSize,
        !           270:                                   (HostAdapter->BounceBuffersRequired
        !           271:                                    ? GFP_ATOMIC | GFP_DMA
        !           272:                                    : GFP_ATOMIC));
        !           273:       if (BlockPointer == NULL)
        !           274:        {
        !           275:          BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
        !           276:                         HostAdapter);
        !           277:          return false;
        !           278:        }
        !           279:       BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
        !           280:     }
        !           281:   return true;
        !           282: }
        !           283: 
        !           284: 
        !           285: /*
        !           286:   BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
        !           287: */
        !           288: 
        !           289: static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter)
        !           290: {
        !           291:   BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB;
        !           292:   HostAdapter->All_CCBs = NULL;
        !           293:   HostAdapter->Free_CCBs = NULL;
        !           294:   while ((CCB = NextCCB) != NULL)
        !           295:     {
        !           296:       NextCCB = CCB->NextAll;
        !           297:       if (CCB->AllocationGroupHead)
        !           298:        kfree(CCB);
        !           299:     }
        !           300: }
        !           301: 
        !           302: 
        !           303: /*
        !           304:   BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter.  If
        !           305:   allocation fails and there are no remaining CCBs available, the Driver Queue
        !           306:   Depth is decreased to a known safe value to avoid potential deadlocks when
        !           307:   multiple host adapters share the same IRQ Channel.
        !           308: */
        !           309: 
        !           310: static void BusLogic_CreateAdditionalCCBs(BusLogic_HostAdapter_T *HostAdapter,
        !           311:                                          int AdditionalCCBs,
        !           312:                                          boolean SuccessMessageP)
        !           313: {
        !           314:   int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
        !           315:   int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
        !           316:   if (AdditionalCCBs <= 0) return;
        !           317:   while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs)
        !           318:     {
        !           319:       void *BlockPointer = kmalloc(BlockSize,
        !           320:                                   (HostAdapter->BounceBuffersRequired
        !           321:                                    ? GFP_ATOMIC | GFP_DMA
        !           322:                                    : GFP_ATOMIC));
        !           323:       if (BlockPointer == NULL) break;
        !           324:       BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
        !           325:     }
        !           326:   if (HostAdapter->AllocatedCCBs > PreviouslyAllocated)
        !           327:     {
        !           328:       if (SuccessMessageP)
        !           329:        BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n",
        !           330:                        HostAdapter,
        !           331:                        HostAdapter->AllocatedCCBs - PreviouslyAllocated,
        !           332:                        HostAdapter->AllocatedCCBs);
        !           333:       return;
        !           334:     }
        !           335:   BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
        !           336:   if (HostAdapter->DriverQueueDepth >
        !           337:       HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount)
        !           338:     {
        !           339:       HostAdapter->DriverQueueDepth =
        !           340:        HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
        !           341:       HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
        !           342:     }
        !           343: }
        !           344: 
        !           345: 
        !           346: /*
        !           347:   BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,
        !           348:   allocating more memory from the Kernel if necessary.  The Host Adapter's
        !           349:   Lock should already have been acquired by the caller.
        !           350: */
        !           351: 
        !           352: static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T
        !           353:                                            *HostAdapter)
        !           354: {
        !           355:   static unsigned long SerialNumber = 0;
        !           356:   BusLogic_CCB_T *CCB;
        !           357:   CCB = HostAdapter->Free_CCBs;
        !           358:   if (CCB != NULL)
        !           359:     {
        !           360:       CCB->SerialNumber = ++SerialNumber;
        !           361:       HostAdapter->Free_CCBs = CCB->Next;
        !           362:       CCB->Next = NULL;
        !           363:       if (HostAdapter->Free_CCBs == NULL)
        !           364:        BusLogic_CreateAdditionalCCBs(HostAdapter,
        !           365:                                      HostAdapter->IncrementalCCBs,
        !           366:                                      true);
        !           367:       return CCB;
        !           368:     }
        !           369:   BusLogic_CreateAdditionalCCBs(HostAdapter,
        !           370:                                HostAdapter->IncrementalCCBs,
        !           371:                                true);
        !           372:   CCB = HostAdapter->Free_CCBs;
        !           373:   if (CCB == NULL) return NULL;
        !           374:   CCB->SerialNumber = ++SerialNumber;
        !           375:   HostAdapter->Free_CCBs = CCB->Next;
        !           376:   CCB->Next = NULL;
        !           377:   return CCB;
        !           378: }
        !           379: 
        !           380: 
        !           381: /*
        !           382:   BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
        !           383:   free list.  The Host Adapter's Lock should already have been acquired by the
        !           384:   caller.
        !           385: */
        !           386: 
        !           387: static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB)
        !           388: {
        !           389:   BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
        !           390:   CCB->Command = NULL;
        !           391:   CCB->Status = BusLogic_CCB_Free;
        !           392:   CCB->Next = HostAdapter->Free_CCBs;
        !           393:   HostAdapter->Free_CCBs = CCB;
        !           394: }
        !           395: 
        !           396: 
        !           397: /*
        !           398:   BusLogic_Command sends the command OperationCode to HostAdapter, optionally
        !           399:   providing ParameterLength bytes of ParameterData and receiving at most
        !           400:   ReplyLength bytes of ReplyData; any excess reply data is received but
        !           401:   discarded.
        !           402: 
        !           403:   On success, this function returns the number of reply bytes read from
        !           404:   the Host Adapter (including any discarded data); on failure, it returns
        !           405:   -1 if the command was invalid, or -2 if a timeout occurred.
        !           406: 
        !           407:   BusLogic_Command is called exclusively during host adapter detection and
        !           408:   initialization, so performance and latency are not critical, and exclusive
        !           409:   access to the Host Adapter hardware is assumed.  Once the host adapter and
        !           410:   driver are initialized, the only Host Adapter command that is issued is the
        !           411:   single byte Execute Mailbox Command operation code, which does not require
        !           412:   waiting for the Host Adapter Ready bit to be set in the Status Register.
        !           413: */
        !           414: 
        !           415: static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
        !           416:                            BusLogic_OperationCode_T OperationCode,
        !           417:                            void *ParameterData,
        !           418:                            int ParameterLength,
        !           419:                            void *ReplyData,
        !           420:                            int ReplyLength)
        !           421: {
        !           422:   unsigned char *ParameterPointer = (unsigned char *) ParameterData;
        !           423:   unsigned char *ReplyPointer = (unsigned char *) ReplyData;
        !           424:   BusLogic_StatusRegister_T StatusRegister;
        !           425:   BusLogic_InterruptRegister_T InterruptRegister;
        !           426:   ProcessorFlags_T ProcessorFlags = 0;
        !           427:   int ReplyBytes = 0, Result;
        !           428:   long TimeoutCounter;
        !           429:   /*
        !           430:     Clear out the Reply Data if provided.
        !           431:   */
        !           432:   if (ReplyLength > 0)
        !           433:     memset(ReplyData, 0, ReplyLength);
        !           434:   /*
        !           435:     If the IRQ Channel has not yet been acquired, then interrupts must be
        !           436:     disabled while issuing host adapter commands since a Command Complete
        !           437:     interrupt could occur if the IRQ Channel was previously enabled by another
        !           438:     BusLogic Host Adapter or another driver sharing the same IRQ Channel.
        !           439:   */
        !           440:   if (!HostAdapter->IRQ_ChannelAcquired)
        !           441:     {
        !           442:       save_flags(ProcessorFlags);
        !           443:       cli();
        !           444:     }
        !           445:   /*
        !           446:     Wait for the Host Adapter Ready bit to be set and the Command/Parameter
        !           447:     Register Busy bit to be reset in the Status Register.
        !           448:   */
        !           449:   TimeoutCounter = 10000;
        !           450:   while (--TimeoutCounter >= 0)
        !           451:     {
        !           452:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !           453:       if (StatusRegister.Bits.HostAdapterReady &&
        !           454:          !StatusRegister.Bits.CommandParameterRegisterBusy)
        !           455:        break;
        !           456:       udelay(100);
        !           457:     }
        !           458:   if (TimeoutCounter < 0)
        !           459:     {
        !           460:       BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
        !           461:       Result = -2;
        !           462:       goto Done;
        !           463:     }
        !           464:   /*
        !           465:     Write the OperationCode to the Command/Parameter Register.
        !           466:   */
        !           467:   HostAdapter->HostAdapterCommandCompleted = false;
        !           468:   BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
        !           469:   /*
        !           470:     Write any additional Parameter Bytes.
        !           471:   */
        !           472:   TimeoutCounter = 10000;
        !           473:   while (ParameterLength > 0 && --TimeoutCounter >= 0)
        !           474:     {
        !           475:       /*
        !           476:        Wait 100 microseconds to give the Host Adapter enough time to determine
        !           477:        whether the last value written to the Command/Parameter Register was
        !           478:        valid or not.  If the Command Complete bit is set in the Interrupt
        !           479:        Register, then the Command Invalid bit in the Status Register will be
        !           480:        reset if the Operation Code or Parameter was valid and the command
        !           481:        has completed, or set if the Operation Code or Parameter was invalid.
        !           482:        If the Data In Register Ready bit is set in the Status Register, then
        !           483:        the Operation Code was valid, and data is waiting to be read back
        !           484:        from the Host Adapter.  Otherwise, wait for the Command/Parameter
        !           485:        Register Busy bit in the Status Register to be reset.
        !           486:       */
        !           487:       udelay(100);
        !           488:       InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
        !           489:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !           490:       if (InterruptRegister.Bits.CommandComplete) break;
        !           491:       if (HostAdapter->HostAdapterCommandCompleted) break;
        !           492:       if (StatusRegister.Bits.DataInRegisterReady) break;
        !           493:       if (StatusRegister.Bits.CommandParameterRegisterBusy) continue;
        !           494:       BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
        !           495:       ParameterLength--;
        !           496:     }
        !           497:   if (TimeoutCounter < 0)
        !           498:     {
        !           499:       BusLogic_CommandFailureReason =
        !           500:        "Timeout waiting for Parameter Acceptance";
        !           501:       Result = -2;
        !           502:       goto Done;
        !           503:     }
        !           504:   /*
        !           505:     The Modify I/O Address command does not cause a Command Complete Interrupt.
        !           506:   */
        !           507:   if (OperationCode == BusLogic_ModifyIOAddress)
        !           508:     {
        !           509:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !           510:       if (StatusRegister.Bits.CommandInvalid)
        !           511:        {
        !           512:          BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
        !           513:          Result = -1;
        !           514:          goto Done;
        !           515:        }
        !           516:       if (BusLogic_GlobalOptions.TraceConfiguration)
        !           517:        BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
        !           518:                        "(Modify I/O Address)\n", HostAdapter,
        !           519:                        OperationCode, StatusRegister.All);
        !           520:       Result = 0;
        !           521:       goto Done;
        !           522:     }
        !           523:   /*
        !           524:     Select an appropriate timeout value for awaiting command completion.
        !           525:   */
        !           526:   switch (OperationCode)
        !           527:     {
        !           528:     case BusLogic_InquireInstalledDevicesID0to7:
        !           529:     case BusLogic_InquireInstalledDevicesID8to15:
        !           530:     case BusLogic_InquireTargetDevices:
        !           531:       /* Approximately 60 seconds. */
        !           532:       TimeoutCounter = 60*10000;
        !           533:       break;
        !           534:     default:
        !           535:       /* Approximately 1 second. */
        !           536:       TimeoutCounter = 10000;
        !           537:       break;
        !           538:     }
        !           539:   /*
        !           540:     Receive any Reply Bytes, waiting for either the Command Complete bit to
        !           541:     be set in the Interrupt Register, or for the Interrupt Handler to set the
        !           542:     Host Adapter Command Completed bit in the Host Adapter structure.
        !           543:   */
        !           544:   while (--TimeoutCounter >= 0)
        !           545:     {
        !           546:       InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
        !           547:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !           548:       if (InterruptRegister.Bits.CommandComplete) break;
        !           549:       if (HostAdapter->HostAdapterCommandCompleted) break;
        !           550:       if (StatusRegister.Bits.DataInRegisterReady)
        !           551:        {
        !           552:          if (++ReplyBytes <= ReplyLength)
        !           553:            *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
        !           554:          else BusLogic_ReadDataInRegister(HostAdapter);
        !           555:        }
        !           556:       if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
        !           557:          StatusRegister.Bits.HostAdapterReady) break;
        !           558:       udelay(100);
        !           559:     }
        !           560:   if (TimeoutCounter < 0)
        !           561:     {
        !           562:       BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
        !           563:       Result = -2;
        !           564:       goto Done;
        !           565:     }
        !           566:   /*
        !           567:     Clear any pending Command Complete Interrupt.
        !           568:   */
        !           569:   BusLogic_InterruptReset(HostAdapter);
        !           570:   /*
        !           571:     Provide tracing information if requested.
        !           572:   */
        !           573:   if (BusLogic_GlobalOptions.TraceConfiguration)
        !           574:     {
        !           575:       int i;
        !           576:       BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
        !           577:                      HostAdapter, OperationCode,
        !           578:                      StatusRegister.All, ReplyLength, ReplyBytes);
        !           579:       if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes;
        !           580:       for (i = 0; i < ReplyLength; i++)
        !           581:        BusLogic_Notice(" %02X", HostAdapter,
        !           582:                        ((unsigned char *) ReplyData)[i]);
        !           583:       BusLogic_Notice("\n", HostAdapter);
        !           584:     }
        !           585:   /*
        !           586:     Process Command Invalid conditions.
        !           587:   */
        !           588:   if (StatusRegister.Bits.CommandInvalid)
        !           589:     {
        !           590:       /*
        !           591:        Some early BusLogic Host Adapters may not recover properly from
        !           592:        a Command Invalid condition, so if this appears to be the case,
        !           593:        a Soft Reset is issued to the Host Adapter.  Potentially invalid
        !           594:        commands are never attempted after Mailbox Initialization is
        !           595:        performed, so there should be no Host Adapter state lost by a
        !           596:        Soft Reset in response to a Command Invalid condition.
        !           597:       */
        !           598:       udelay(1000);
        !           599:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !           600:       if (StatusRegister.Bits.CommandInvalid ||
        !           601:          StatusRegister.Bits.Reserved ||
        !           602:          StatusRegister.Bits.DataInRegisterReady ||
        !           603:          StatusRegister.Bits.CommandParameterRegisterBusy ||
        !           604:          !StatusRegister.Bits.HostAdapterReady ||
        !           605:          !StatusRegister.Bits.InitializationRequired ||
        !           606:          StatusRegister.Bits.DiagnosticActive ||
        !           607:          StatusRegister.Bits.DiagnosticFailure)
        !           608:        {
        !           609:          BusLogic_SoftReset(HostAdapter);
        !           610:          udelay(1000);
        !           611:        }
        !           612:       BusLogic_CommandFailureReason = "Command Invalid";
        !           613:       Result = -1;
        !           614:       goto Done;
        !           615:     }
        !           616:   /*
        !           617:     Handle Excess Parameters Supplied conditions.
        !           618:   */
        !           619:   if (ParameterLength > 0)
        !           620:     {
        !           621:       BusLogic_CommandFailureReason = "Excess Parameters Supplied";
        !           622:       Result = -1;
        !           623:       goto Done;
        !           624:     }
        !           625:   /*
        !           626:     Indicate the command completed successfully.
        !           627:   */
        !           628:   BusLogic_CommandFailureReason = NULL;
        !           629:   Result = ReplyBytes;
        !           630:   /*
        !           631:     Restore the interrupt status if necessary and return.
        !           632:   */
        !           633: Done:
        !           634:   if (!HostAdapter->IRQ_ChannelAcquired)
        !           635:     restore_flags(ProcessorFlags);
        !           636:   return Result;
        !           637: }
        !           638: 
        !           639: 
        !           640: /*
        !           641:   BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list
        !           642:   of I/O Address and Bus Probe Information to be checked for potential BusLogic
        !           643:   Host Adapters.
        !           644: */
        !           645: 
        !           646: static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address)
        !           647: {
        !           648:   BusLogic_ProbeInfo_T *ProbeInfo;
        !           649:   if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return;
        !           650:   ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
        !           651:   ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
        !           652:   ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
        !           653:   ProbeInfo->IO_Address = IO_Address;
        !           654: }
        !           655: 
        !           656: 
        !           657: /*
        !           658:   BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and
        !           659:   Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
        !           660:   only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
        !           661: */
        !           662: 
        !           663: static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T
        !           664:                                                *PrototypeHostAdapter)
        !           665: {
        !           666:   /*
        !           667:     If BusLogic Driver Options specifications requested that ISA Bus Probes
        !           668:     be inhibited, do not proceed further.
        !           669:   */
        !           670:   if (BusLogic_ProbeOptions.NoProbeISA) return;
        !           671:   /*
        !           672:     Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
        !           673:   */
        !           674:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           675:       ? BusLogic_ProbeOptions.Probe330
        !           676:       : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
        !           677:     BusLogic_AppendProbeAddressISA(0x330);
        !           678:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           679:       ? BusLogic_ProbeOptions.Probe334
        !           680:       : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
        !           681:     BusLogic_AppendProbeAddressISA(0x334);
        !           682:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           683:       ? BusLogic_ProbeOptions.Probe230
        !           684:       : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
        !           685:     BusLogic_AppendProbeAddressISA(0x230);
        !           686:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           687:       ? BusLogic_ProbeOptions.Probe234
        !           688:       : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
        !           689:     BusLogic_AppendProbeAddressISA(0x234);
        !           690:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           691:       ? BusLogic_ProbeOptions.Probe130
        !           692:       : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
        !           693:     BusLogic_AppendProbeAddressISA(0x130);
        !           694:   if (BusLogic_ProbeOptions.LimitedProbeISA
        !           695:       ? BusLogic_ProbeOptions.Probe134
        !           696:       : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
        !           697:     BusLogic_AppendProbeAddressISA(0x134);
        !           698: }
        !           699: 
        !           700: 
        !           701: #ifdef CONFIG_PCI
        !           702: 
        !           703: 
        !           704: /*
        !           705:   BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order
        !           706:   of increasing PCI Bus and Device Number.
        !           707: */
        !           708: 
        !           709: static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList,
        !           710:                                   int ProbeInfoCount)
        !           711: {
        !           712:   int LastInterchange = ProbeInfoCount-1, Bound, j;
        !           713:   while (LastInterchange > 0)
        !           714:     {
        !           715:       Bound = LastInterchange;
        !           716:       LastInterchange = 0;
        !           717:       for (j = 0; j < Bound; j++)
        !           718:        {
        !           719:          BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j];
        !           720:          BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1];
        !           721:          if (ProbeInfo1->Bus > ProbeInfo2->Bus ||
        !           722:              (ProbeInfo1->Bus == ProbeInfo2->Bus &&
        !           723:               (ProbeInfo1->Device > ProbeInfo2->Device)))
        !           724:            {
        !           725:              BusLogic_ProbeInfo_T TempProbeInfo;
        !           726:              memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T));
        !           727:              memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T));
        !           728:              memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T));
        !           729:              LastInterchange = j;
        !           730:            }
        !           731:        }
        !           732:     }
        !           733: }
        !           734: 
        !           735: 
        !           736: /*
        !           737:   BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address
        !           738:   and Bus Probe Information to be checked for potential BusLogic MultiMaster
        !           739:   SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
        !           740:   machines as well as from the list of standard BusLogic MultiMaster ISA
        !           741:   I/O Addresses.  It returns the number of PCI MultiMaster Host Adapters found.
        !           742: */
        !           743: 
        !           744: static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T
        !           745:                                                   *PrototypeHostAdapter)
        !           746: {
        !           747:   BusLogic_ProbeInfo_T *PrimaryProbeInfo =
        !           748:     &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
        !           749:   int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
        !           750:   int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
        !           751:   boolean ForceBusDeviceScanningOrder = false;
        !           752:   boolean ForceBusDeviceScanningOrderChecked = false;
        !           753:   boolean StandardAddressSeen[6];
        !           754:   unsigned char Bus, DeviceFunction;
        !           755:   unsigned int BaseAddress0, BaseAddress1;
        !           756:   unsigned char IRQ_Channel;
        !           757:   BusLogic_IO_Address_T IO_Address;
        !           758:   BusLogic_PCI_Address_T PCI_Address;
        !           759:   unsigned short Index = 0;
        !           760:   int i;
        !           761:   if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0;
        !           762:   BusLogic_ProbeInfoCount++;
        !           763:   for (i = 0; i < 6; i++)
        !           764:     StandardAddressSeen[i] = false;
        !           765:   /*
        !           766:     Iterate over the MultiMaster PCI Host Adapters.  For each enumerated host
        !           767:     adapter, determine whether its ISA Compatible I/O Port is enabled and if
        !           768:     so, whether it is assigned the Primary I/O Address.  A host adapter that is
        !           769:     assigned the Primary I/O Address will always be the preferred boot device.
        !           770:     The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
        !           771:     Address, then any other PCI host adapters, and finally any host adapters
        !           772:     located at the remaining standard ISA I/O Addresses.  When a PCI host
        !           773:     adapter is found with its ISA Compatible I/O Port enabled, a command is
        !           774:     issued to disable the ISA Compatible I/O Port, and it is noted that the
        !           775:     particular standard ISA I/O Address need not be probed.
        !           776:   */
        !           777:   PrimaryProbeInfo->IO_Address = 0;
        !           778:   while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
        !           779:                             PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
        !           780:                             Index++, &Bus, &DeviceFunction) == 0)
        !           781:     if (pcibios_read_config_dword(Bus, DeviceFunction,
        !           782:                                  PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
        !           783:        pcibios_read_config_dword(Bus, DeviceFunction,
        !           784:                                  PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 &&
        !           785:        pcibios_read_config_byte(Bus, DeviceFunction,
        !           786:                                 PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
        !           787:       {
        !           788:        BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
        !           789:        BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
        !           790:        BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest;
        !           791:        unsigned char Device = DeviceFunction >> 3;
        !           792:        IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
        !           793:        PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
        !           794:        if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
        !           795:            != PCI_BASE_ADDRESS_SPACE_IO)
        !           796:          {
        !           797:            BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
        !           798:                           "MultiMaster Host Adapter\n", NULL, BaseAddress0);
        !           799:            BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
        !           800:                           NULL, Bus, Device, IO_Address);
        !           801:            continue;
        !           802:          }
        !           803:        if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
        !           804:            != PCI_BASE_ADDRESS_SPACE_MEMORY)
        !           805:          {
        !           806:            BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
        !           807:                           "MultiMaster Host Adapter\n", NULL, BaseAddress1);
        !           808:            BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
        !           809:                           NULL, Bus, Device, PCI_Address);
        !           810:            continue;
        !           811:          }
        !           812:        if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
        !           813:          {
        !           814:            BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
        !           815:                           "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
        !           816:            BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
        !           817:                           NULL, Bus, Device, IO_Address);
        !           818:            continue;
        !           819:          }
        !           820:        if (BusLogic_GlobalOptions.TraceProbe)
        !           821:          {
        !           822:            BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter "
        !           823:                            "detected at\n", NULL);
        !           824:            BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
        !           825:                            "0x%X PCI Address 0x%X\n", NULL,
        !           826:                            Bus, Device, IO_Address, PCI_Address);
        !           827:          }
        !           828:        /*
        !           829:          Issue the Inquire PCI Host Adapter Information command to determine
        !           830:          the ISA Compatible I/O Port.  If the ISA Compatible I/O Port is
        !           831:          known and enabled, note that the particular Standard ISA I/O
        !           832:          Address should not be probed.
        !           833:        */
        !           834:        HostAdapter->IO_Address = IO_Address;
        !           835:        BusLogic_InterruptReset(HostAdapter);
        !           836:        if (BusLogic_Command(HostAdapter,
        !           837:                             BusLogic_InquirePCIHostAdapterInformation,
        !           838:                             NULL, 0, &PCIHostAdapterInformation,
        !           839:                             sizeof(PCIHostAdapterInformation))
        !           840:            == sizeof(PCIHostAdapterInformation))
        !           841:          {
        !           842:            if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
        !           843:              StandardAddressSeen[PCIHostAdapterInformation
        !           844:                                  .ISACompatibleIOPort] = true;
        !           845:          }
        !           846:        else PCIHostAdapterInformation.ISACompatibleIOPort =
        !           847:               BusLogic_IO_Disable;
        !           848:        /*
        !           849:          Issue the Modify I/O Address command to disable the ISA Compatible
        !           850:          I/O Port.
        !           851:        */
        !           852:        ModifyIOAddressRequest = BusLogic_IO_Disable;
        !           853:        BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
        !           854:                         &ModifyIOAddressRequest,
        !           855:                         sizeof(ModifyIOAddressRequest), NULL, 0);
        !           856:        /*
        !           857:          For the first MultiMaster Host Adapter enumerated, issue the Fetch
        !           858:          Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
        !           859:          for the setting of the "Use Bus And Device # For PCI Scanning Seq."
        !           860:          option.  Issue the Inquire Board ID command since this option is
        !           861:          only valid for the BT-948/958/958D.
        !           862:        */
        !           863:        if (!ForceBusDeviceScanningOrderChecked)
        !           864:          {
        !           865:            BusLogic_FetchHostAdapterLocalRAMRequest_T
        !           866:              FetchHostAdapterLocalRAMRequest;
        !           867:            BusLogic_AutoSCSIByte45_T AutoSCSIByte45;
        !           868:            BusLogic_BoardID_T BoardID;
        !           869:            FetchHostAdapterLocalRAMRequest.ByteOffset =
        !           870:              BusLogic_AutoSCSI_BaseOffset + 45;
        !           871:            FetchHostAdapterLocalRAMRequest.ByteCount =
        !           872:              sizeof(AutoSCSIByte45);
        !           873:            BusLogic_Command(HostAdapter,
        !           874:                             BusLogic_FetchHostAdapterLocalRAM,
        !           875:                             &FetchHostAdapterLocalRAMRequest,
        !           876:                             sizeof(FetchHostAdapterLocalRAMRequest),
        !           877:                             &AutoSCSIByte45, sizeof(AutoSCSIByte45));
        !           878:            BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
        !           879:                             NULL, 0, &BoardID, sizeof(BoardID));
        !           880:            if (BoardID.FirmwareVersion1stDigit == '5')
        !           881:              ForceBusDeviceScanningOrder =
        !           882:                AutoSCSIByte45.ForceBusDeviceScanningOrder;
        !           883:            ForceBusDeviceScanningOrderChecked = true;
        !           884:          }
        !           885:        /*
        !           886:          Determine whether this MultiMaster Host Adapter has its ISA
        !           887:          Compatible I/O Port enabled and is assigned the Primary I/O Address.
        !           888:          If it does, then it is the Primary MultiMaster Host Adapter and must
        !           889:          be recognized first.  If it does not, then it is added to the list
        !           890:          for probing after any Primary MultiMaster Host Adapter is probed.
        !           891:        */
        !           892:        if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330)
        !           893:          {
        !           894:            PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
        !           895:            PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
        !           896:            PrimaryProbeInfo->IO_Address = IO_Address;
        !           897:            PrimaryProbeInfo->PCI_Address = PCI_Address;
        !           898:            PrimaryProbeInfo->Bus = Bus;
        !           899:            PrimaryProbeInfo->Device = Device;
        !           900:            PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
        !           901:            PCIMultiMasterCount++;
        !           902:          }
        !           903:        else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
        !           904:          {
        !           905:            BusLogic_ProbeInfo_T *ProbeInfo =
        !           906:              &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
        !           907:            ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
        !           908:            ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
        !           909:            ProbeInfo->IO_Address = IO_Address;
        !           910:            ProbeInfo->PCI_Address = PCI_Address;
        !           911:            ProbeInfo->Bus = Bus;
        !           912:            ProbeInfo->Device = Device;
        !           913:            ProbeInfo->IRQ_Channel = IRQ_Channel;
        !           914:            NonPrimaryPCIMultiMasterCount++;
        !           915:            PCIMultiMasterCount++;
        !           916:          }
        !           917:        else BusLogic_Warning("BusLogic: Too many Host Adapters "
        !           918:                              "detected\n", NULL);
        !           919:       }
        !           920:   /*
        !           921:     If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
        !           922:     for the first enumerated MultiMaster Host Adapter, and if that host adapter
        !           923:     is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
        !           924:     Host Adapters in the order of increasing PCI Bus and Device Number.  In
        !           925:     that case, sort the probe information into the same order the BIOS uses.
        !           926:     If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
        !           927:     Host Adapters in the order they are enumerated by the PCI BIOS, and hence
        !           928:     no sorting is necessary.
        !           929:   */
        !           930:   if (ForceBusDeviceScanningOrder)
        !           931:     BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[
        !           932:                              NonPrimaryPCIMultiMasterIndex],
        !           933:                           NonPrimaryPCIMultiMasterCount);
        !           934:   /*
        !           935:     If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
        !           936:     then the Primary I/O Address must be probed explicitly before any PCI
        !           937:     host adapters are probed.
        !           938:   */
        !           939:   if (!BusLogic_ProbeOptions.NoProbeISA)
        !           940:     if (PrimaryProbeInfo->IO_Address == 0 &&
        !           941:        (BusLogic_ProbeOptions.LimitedProbeISA
        !           942:         ? BusLogic_ProbeOptions.Probe330
        !           943:         : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0))
        !           944:       {
        !           945:        PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
        !           946:        PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
        !           947:        PrimaryProbeInfo->IO_Address = 0x330;
        !           948:       }
        !           949:   /*
        !           950:     Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
        !           951:     omitting the Primary I/O Address which has already been handled.
        !           952:   */
        !           953:   if (!BusLogic_ProbeOptions.NoProbeISA)
        !           954:     {
        !           955:       if (!StandardAddressSeen[1] &&
        !           956:          (BusLogic_ProbeOptions.LimitedProbeISA
        !           957:           ? BusLogic_ProbeOptions.Probe334
        !           958:           : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
        !           959:        BusLogic_AppendProbeAddressISA(0x334);
        !           960:       if (!StandardAddressSeen[2] &&
        !           961:          (BusLogic_ProbeOptions.LimitedProbeISA
        !           962:           ? BusLogic_ProbeOptions.Probe230
        !           963:           : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
        !           964:        BusLogic_AppendProbeAddressISA(0x230);
        !           965:       if (!StandardAddressSeen[3] &&
        !           966:          (BusLogic_ProbeOptions.LimitedProbeISA
        !           967:           ? BusLogic_ProbeOptions.Probe234
        !           968:           : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
        !           969:        BusLogic_AppendProbeAddressISA(0x234);
        !           970:       if (!StandardAddressSeen[4] &&
        !           971:          (BusLogic_ProbeOptions.LimitedProbeISA
        !           972:           ? BusLogic_ProbeOptions.Probe130
        !           973:           : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
        !           974:        BusLogic_AppendProbeAddressISA(0x130);
        !           975:       if (!StandardAddressSeen[5] &&
        !           976:          (BusLogic_ProbeOptions.LimitedProbeISA
        !           977:           ? BusLogic_ProbeOptions.Probe134
        !           978:           : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
        !           979:        BusLogic_AppendProbeAddressISA(0x134);
        !           980:     }
        !           981:   /*
        !           982:     Iterate over the older non-compliant MultiMaster PCI Host Adapters,
        !           983:     noting the PCI bus location and assigned IRQ Channel.
        !           984:   */
        !           985:   Index = 0;
        !           986:   while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
        !           987:                             PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
        !           988:                             Index++, &Bus, &DeviceFunction) == 0)
        !           989:     if (pcibios_read_config_dword(Bus, DeviceFunction,
        !           990:                                  PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
        !           991:        pcibios_read_config_byte(Bus, DeviceFunction,
        !           992:                                 PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
        !           993:       {
        !           994:        unsigned char Device = DeviceFunction >> 3;
        !           995:        IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
        !           996:        if (IO_Address == 0 || IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
        !           997:          continue;
        !           998:        for (i = 0; i < BusLogic_ProbeInfoCount; i++)
        !           999:          {
        !          1000:            BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[i];
        !          1001:            if (ProbeInfo->IO_Address == IO_Address &&
        !          1002:                ProbeInfo->HostAdapterType == BusLogic_MultiMaster)
        !          1003:              {
        !          1004:                ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
        !          1005:                ProbeInfo->PCI_Address = 0;
        !          1006:                ProbeInfo->Bus = Bus;
        !          1007:                ProbeInfo->Device = Device;
        !          1008:                ProbeInfo->IRQ_Channel = IRQ_Channel;
        !          1009:                break;
        !          1010:              }
        !          1011:          }
        !          1012:       }
        !          1013:   return PCIMultiMasterCount;
        !          1014: }
        !          1015: 
        !          1016: 
        !          1017: /*
        !          1018:   BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address
        !          1019:   and Bus Probe Information to be checked for potential BusLogic FlashPoint
        !          1020:   Host Adapters by interrogating the PCI Configuration Space.  It returns the
        !          1021:   number of FlashPoint Host Adapters found.
        !          1022: */
        !          1023: 
        !          1024: static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T
        !          1025:                                                  *PrototypeHostAdapter)
        !          1026: {
        !          1027:   int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
        !          1028:   unsigned char Bus, DeviceFunction;
        !          1029:   unsigned int BaseAddress0, BaseAddress1;
        !          1030:   unsigned char IRQ_Channel;
        !          1031:   BusLogic_IO_Address_T IO_Address;
        !          1032:   BusLogic_PCI_Address_T PCI_Address;
        !          1033:   unsigned short Index = 0;
        !          1034:   /*
        !          1035:     Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
        !          1036:   */
        !          1037:   while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
        !          1038:                             PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
        !          1039:                             Index++, &Bus, &DeviceFunction) == 0)
        !          1040:     if (pcibios_read_config_dword(Bus, DeviceFunction,
        !          1041:                                  PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
        !          1042:        pcibios_read_config_dword(Bus, DeviceFunction,
        !          1043:                                  PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 &&
        !          1044:        pcibios_read_config_byte(Bus, DeviceFunction,
        !          1045:                                 PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
        !          1046:       {
        !          1047:        unsigned char Device = DeviceFunction >> 3;
        !          1048:        IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
        !          1049:        PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
        !          1050: #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
        !          1051:        if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
        !          1052:            != PCI_BASE_ADDRESS_SPACE_IO)
        !          1053:          {
        !          1054:            BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
        !          1055:                           "FlashPoint Host Adapter\n", NULL, BaseAddress0);
        !          1056:            BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
        !          1057:                           NULL, Bus, Device, IO_Address);
        !          1058:            continue;
        !          1059:          }
        !          1060:        if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
        !          1061:            != PCI_BASE_ADDRESS_SPACE_MEMORY)
        !          1062:          {
        !          1063:            BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
        !          1064:                           "FlashPoint Host Adapter\n", NULL, BaseAddress1);
        !          1065:            BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
        !          1066:                           NULL, Bus, Device, PCI_Address);
        !          1067:            continue;
        !          1068:          }
        !          1069:        if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
        !          1070:          {
        !          1071:            BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
        !          1072:                           "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
        !          1073:            BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
        !          1074:                           NULL, Bus, Device, IO_Address);
        !          1075:            continue;
        !          1076:          }
        !          1077:        if (BusLogic_GlobalOptions.TraceProbe)
        !          1078:          {
        !          1079:            BusLogic_Notice("BusLogic: FlashPoint Host Adapter "
        !          1080:                            "detected at\n", NULL);
        !          1081:            BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
        !          1082:                            "0x%X PCI Address 0x%X\n", NULL,
        !          1083:                            Bus, Device, IO_Address, PCI_Address);
        !          1084:          }
        !          1085:        if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
        !          1086:          {
        !          1087:            BusLogic_ProbeInfo_T *ProbeInfo =
        !          1088:              &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
        !          1089:            ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
        !          1090:            ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
        !          1091:            ProbeInfo->IO_Address = IO_Address;
        !          1092:            ProbeInfo->PCI_Address = PCI_Address;
        !          1093:            ProbeInfo->Bus = Bus;
        !          1094:            ProbeInfo->Device = Device;
        !          1095:            ProbeInfo->IRQ_Channel = IRQ_Channel;
        !          1096:            FlashPointCount++;
        !          1097:          }
        !          1098:        else BusLogic_Warning("BusLogic: Too many Host Adapters "
        !          1099:                              "detected\n", NULL);
        !          1100: #else
        !          1101:        BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
        !          1102:                       "PCI Bus %d Device %d\n", NULL, Bus, Device);
        !          1103:        BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
        !          1104:                       "but FlashPoint\n", NULL, IO_Address, PCI_Address);
        !          1105:        BusLogic_Error("BusLogic: support was omitted in this kernel "
        !          1106:                       "configuration.\n", NULL);
        !          1107: #endif
        !          1108:       }
        !          1109:   /*
        !          1110:     The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
        !          1111:     increasing PCI Bus and Device Number, so sort the probe information into
        !          1112:     the same order the BIOS uses.
        !          1113:   */
        !          1114:   BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex],
        !          1115:                         FlashPointCount);
        !          1116:   return FlashPointCount;
        !          1117: }
        !          1118: 
        !          1119: 
        !          1120: /*
        !          1121:   BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus
        !          1122:   Probe Information to be checked for potential BusLogic SCSI Host Adapters by
        !          1123:   interrogating the PCI Configuration Space on PCI machines as well as from the
        !          1124:   list of standard BusLogic MultiMaster ISA I/O Addresses.  By default, if both
        !          1125:   FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
        !          1126:   probe for FlashPoint Host Adapters first unless the BIOS primary disk is
        !          1127:   controlled by the first PCI MultiMaster Host Adapter, in which case
        !          1128:   MultiMaster Host Adapters will be probed first.  The BusLogic Driver Options
        !          1129:   specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
        !          1130:   a particular probe order.
        !          1131: */
        !          1132: 
        !          1133: static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T
        !          1134:                                             *PrototypeHostAdapter)
        !          1135: {
        !          1136:   /*
        !          1137:     If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
        !          1138:     Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
        !          1139:   */
        !          1140:   if (!BusLogic_ProbeOptions.NoProbePCI && pcibios_present())
        !          1141:     {
        !          1142:       if (BusLogic_ProbeOptions.MultiMasterFirst)
        !          1143:        {
        !          1144:          BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
        !          1145:          BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
        !          1146:        }
        !          1147:       else if (BusLogic_ProbeOptions.FlashPointFirst)
        !          1148:        {
        !          1149:          BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
        !          1150:          BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
        !          1151:        }
        !          1152:       else
        !          1153:        {
        !          1154:          int FlashPointCount =
        !          1155:            BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
        !          1156:          int PCIMultiMasterCount =
        !          1157:            BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
        !          1158:          if (FlashPointCount > 0 && PCIMultiMasterCount > 0)
        !          1159:            {
        !          1160:              BusLogic_ProbeInfo_T *ProbeInfo =
        !          1161:                &BusLogic_ProbeInfoList[FlashPointCount];
        !          1162:              BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
        !          1163:              BusLogic_FetchHostAdapterLocalRAMRequest_T
        !          1164:                FetchHostAdapterLocalRAMRequest;
        !          1165:              BusLogic_BIOSDriveMapByte_T Drive0MapByte;
        !          1166:              while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
        !          1167:                ProbeInfo++;
        !          1168:              HostAdapter->IO_Address = ProbeInfo->IO_Address;
        !          1169:              FetchHostAdapterLocalRAMRequest.ByteOffset =
        !          1170:                BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
        !          1171:              FetchHostAdapterLocalRAMRequest.ByteCount =
        !          1172:                sizeof(Drive0MapByte);
        !          1173:              BusLogic_Command(HostAdapter,
        !          1174:                               BusLogic_FetchHostAdapterLocalRAM,
        !          1175:                               &FetchHostAdapterLocalRAMRequest,
        !          1176:                               sizeof(FetchHostAdapterLocalRAMRequest),
        !          1177:                               &Drive0MapByte, sizeof(Drive0MapByte));
        !          1178:              /*
        !          1179:                If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
        !          1180:                is controlled by this PCI MultiMaster Host Adapter, then
        !          1181:                reverse the probe order so that MultiMaster Host Adapters are
        !          1182:                probed before FlashPoint Host Adapters.
        !          1183:              */
        !          1184:              if (Drive0MapByte.DiskGeometry !=
        !          1185:                  BusLogic_BIOS_Disk_Not_Installed)
        !          1186:                {
        !          1187:                  BusLogic_ProbeInfo_T
        !          1188:                    SavedProbeInfo[BusLogic_MaxHostAdapters];
        !          1189:                  int MultiMasterCount =
        !          1190:                    BusLogic_ProbeInfoCount - FlashPointCount;
        !          1191:                  memcpy(SavedProbeInfo,
        !          1192:                         BusLogic_ProbeInfoList,
        !          1193:                         BusLogic_ProbeInfoCount
        !          1194:                         * sizeof(BusLogic_ProbeInfo_T));
        !          1195:                  memcpy(&BusLogic_ProbeInfoList[0],
        !          1196:                         &SavedProbeInfo[FlashPointCount],
        !          1197:                         MultiMasterCount * sizeof(BusLogic_ProbeInfo_T));
        !          1198:                  memcpy(&BusLogic_ProbeInfoList[MultiMasterCount],
        !          1199:                         &SavedProbeInfo[0],
        !          1200:                         FlashPointCount * sizeof(BusLogic_ProbeInfo_T));
        !          1201:                }
        !          1202:            }
        !          1203:        }
        !          1204:     }
        !          1205:   else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
        !          1206: }
        !          1207: 
        !          1208: 
        !          1209: #endif  /* CONFIG_PCI */
        !          1210: 
        !          1211: 
        !          1212: /*
        !          1213:   BusLogic_Failure prints a standardized error message, and then returns false.
        !          1214: */
        !          1215: 
        !          1216: static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter,
        !          1217:                                char *ErrorMessage)
        !          1218: {
        !          1219:   BusLogic_AnnounceDriver(HostAdapter);
        !          1220:   if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus)
        !          1221:     {
        !          1222:       BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n",
        !          1223:                     HostAdapter);
        !          1224:       BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n",
        !          1225:                     HostAdapter, HostAdapter->Bus, HostAdapter->Device,
        !          1226:                     HostAdapter->IO_Address, HostAdapter->PCI_Address);
        !          1227:     }
        !          1228:   else BusLogic_Error("While configuring BusLogic Host Adapter at "
        !          1229:                      "I/O Address 0x%X:\n", HostAdapter,
        !          1230:                      HostAdapter->IO_Address);
        !          1231:   BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
        !          1232:   if (BusLogic_CommandFailureReason != NULL)
        !          1233:     BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter,
        !          1234:                   BusLogic_CommandFailureReason);
        !          1235:   return false;
        !          1236: }
        !          1237: 
        !          1238: 
        !          1239: /*
        !          1240:   BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
        !          1241: */
        !          1242: 
        !          1243: static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
        !          1244: {
        !          1245:   BusLogic_StatusRegister_T StatusRegister;
        !          1246:   BusLogic_InterruptRegister_T InterruptRegister;
        !          1247:   BusLogic_GeometryRegister_T GeometryRegister;
        !          1248:   /*
        !          1249:     FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
        !          1250:   */
        !          1251:   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          1252:     {
        !          1253:       FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
        !          1254:       FlashPointInfo->BaseAddress =
        !          1255:        (BusLogic_Base_Address_T) HostAdapter->IO_Address;
        !          1256:       FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
        !          1257:       FlashPointInfo->Present = false;
        !          1258:       if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 &&
        !          1259:            FlashPointInfo->Present))
        !          1260:        {
        !          1261:          BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
        !          1262:                         "PCI Bus %d Device %d\n", HostAdapter,
        !          1263:                         HostAdapter->Bus, HostAdapter->Device);
        !          1264:          BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
        !          1265:                         "but FlashPoint\n", HostAdapter,
        !          1266:                         HostAdapter->IO_Address, HostAdapter->PCI_Address);
        !          1267:          BusLogic_Error("BusLogic: Probe Function failed to validate it.\n",
        !          1268:                         HostAdapter);
        !          1269:          return false;
        !          1270:        }
        !          1271:       if (BusLogic_GlobalOptions.TraceProbe)
        !          1272:        BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n",
        !          1273:                        HostAdapter, HostAdapter->IO_Address);
        !          1274:       /*
        !          1275:        Indicate the Host Adapter Probe completed successfully.
        !          1276:       */
        !          1277:       return true;
        !          1278:     }
        !          1279:   /*
        !          1280:     Read the Status, Interrupt, and Geometry Registers to test if there are I/O
        !          1281:     ports that respond, and to check the values to determine if they are from a
        !          1282:     BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
        !          1283:     case there is definitely no BusLogic Host Adapter at this base I/O Address.
        !          1284:     The test here is a subset of that used by the BusLogic Host Adapter BIOS.
        !          1285:   */
        !          1286:   StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !          1287:   InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
        !          1288:   GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
        !          1289:   if (BusLogic_GlobalOptions.TraceProbe)
        !          1290:     BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, "
        !          1291:                    "Geometry 0x%02X\n", HostAdapter,
        !          1292:                    HostAdapter->IO_Address, StatusRegister.All,
        !          1293:                    InterruptRegister.All, GeometryRegister.All);
        !          1294:   if (StatusRegister.All == 0 ||
        !          1295:       StatusRegister.Bits.DiagnosticActive ||
        !          1296:       StatusRegister.Bits.CommandParameterRegisterBusy ||
        !          1297:       StatusRegister.Bits.Reserved ||
        !          1298:       StatusRegister.Bits.CommandInvalid ||
        !          1299:       InterruptRegister.Bits.Reserved != 0)
        !          1300:     return false;
        !          1301:   /*
        !          1302:     Check the undocumented Geometry Register to test if there is an I/O port
        !          1303:     that responded.  Adaptec Host Adapters do not implement the Geometry
        !          1304:     Register, so this test helps serve to avoid incorrectly recognizing an
        !          1305:     Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
        !          1306:     series does respond to the Geometry Register I/O port, but it will be
        !          1307:     rejected later when the Inquire Extended Setup Information command is
        !          1308:     issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
        !          1309:     BusLogic clone that implements the same interface as earlier BusLogic
        !          1310:     Host Adapters, including the undocumented commands, and is therefore
        !          1311:     supported by this driver.  However, the AMI FastDisk always returns 0x00
        !          1312:     upon reading the Geometry Register, so the extended translation option
        !          1313:     should always be left disabled on the AMI FastDisk.
        !          1314:   */
        !          1315:   if (GeometryRegister.All == 0xFF) return false;
        !          1316:   /*
        !          1317:     Indicate the Host Adapter Probe completed successfully.
        !          1318:   */
        !          1319:   return true;
        !          1320: }
        !          1321: 
        !          1322: 
        !          1323: /*
        !          1324:   BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter
        !          1325:   and waits for Host Adapter Diagnostics to complete.  If HardReset is true, a
        !          1326:   Hard Reset is performed which also initiates a SCSI Bus Reset.  Otherwise, a
        !          1327:   Soft Reset is performed which only resets the Host Adapter without forcing a
        !          1328:   SCSI Bus Reset.
        !          1329: */
        !          1330: 
        !          1331: static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T
        !          1332:                                                   *HostAdapter,
        !          1333:                                                 boolean HardReset)
        !          1334: {
        !          1335:   BusLogic_StatusRegister_T StatusRegister;
        !          1336:   int TimeoutCounter;
        !          1337:   /*
        !          1338:     FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
        !          1339:   */
        !          1340:   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          1341:     {
        !          1342:       FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
        !          1343:       FlashPointInfo->HostSoftReset = !HardReset;
        !          1344:       FlashPointInfo->ReportDataUnderrun = true;
        !          1345:       HostAdapter->CardHandle =
        !          1346:        FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
        !          1347:       if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false;
        !          1348:       /*
        !          1349:        Indicate the Host Adapter Hard Reset completed successfully.
        !          1350:       */
        !          1351:       return true;
        !          1352:     }
        !          1353:   /*
        !          1354:     Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
        !          1355:     Adapter should respond by setting Diagnostic Active in the Status Register.
        !          1356:   */
        !          1357:   if (HardReset)
        !          1358:     BusLogic_HardReset(HostAdapter);
        !          1359:   else BusLogic_SoftReset(HostAdapter);
        !          1360:   /*
        !          1361:     Wait until Diagnostic Active is set in the Status Register.
        !          1362:   */
        !          1363:   TimeoutCounter = 5*10000;
        !          1364:   while (--TimeoutCounter >= 0)
        !          1365:     {
        !          1366:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !          1367:       if (StatusRegister.Bits.DiagnosticActive) break;
        !          1368:       udelay(100);
        !          1369:     }
        !          1370:   if (BusLogic_GlobalOptions.TraceHardwareReset)
        !          1371:     BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, "
        !          1372:                    "Status 0x%02X\n", HostAdapter,
        !          1373:                    HostAdapter->IO_Address, StatusRegister.All);
        !          1374:   if (TimeoutCounter < 0) return false;
        !          1375:   /*
        !          1376:     Wait 100 microseconds to allow completion of any initial diagnostic
        !          1377:     activity which might leave the contents of the Status Register
        !          1378:     unpredictable.
        !          1379:   */
        !          1380:   udelay(100);
        !          1381:   /*
        !          1382:     Wait until Diagnostic Active is reset in the Status Register.
        !          1383:   */
        !          1384:   TimeoutCounter = 10*10000;
        !          1385:   while (--TimeoutCounter >= 0)
        !          1386:     {
        !          1387:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !          1388:       if (!StatusRegister.Bits.DiagnosticActive) break;
        !          1389:       udelay(100);
        !          1390:     }
        !          1391:   if (BusLogic_GlobalOptions.TraceHardwareReset)
        !          1392:     BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, "
        !          1393:                    "Status 0x%02X\n", HostAdapter,
        !          1394:                    HostAdapter->IO_Address, StatusRegister.All);
        !          1395:   if (TimeoutCounter < 0) return false;
        !          1396:   /*
        !          1397:     Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
        !          1398:     or Data In Register Ready bits is set in the Status Register.
        !          1399:   */
        !          1400:   TimeoutCounter = 10000;
        !          1401:   while (--TimeoutCounter >= 0)
        !          1402:     {
        !          1403:       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
        !          1404:       if (StatusRegister.Bits.DiagnosticFailure ||
        !          1405:          StatusRegister.Bits.HostAdapterReady ||
        !          1406:          StatusRegister.Bits.DataInRegisterReady)
        !          1407:        break;
        !          1408:       udelay(100);
        !          1409:     }
        !          1410:   if (BusLogic_GlobalOptions.TraceHardwareReset)
        !          1411:     BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, "
        !          1412:                    "Status 0x%02X\n", HostAdapter,
        !          1413:                    HostAdapter->IO_Address, StatusRegister.All);
        !          1414:   if (TimeoutCounter < 0) return false;
        !          1415:   /*
        !          1416:     If Diagnostic Failure is set or Host Adapter Ready is reset, then an
        !          1417:     error occurred during the Host Adapter diagnostics.  If Data In Register
        !          1418:     Ready is set, then there is an Error Code available.
        !          1419:   */
        !          1420:   if (StatusRegister.Bits.DiagnosticFailure ||
        !          1421:       !StatusRegister.Bits.HostAdapterReady)
        !          1422:     {
        !          1423:       BusLogic_CommandFailureReason = NULL;
        !          1424:       BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
        !          1425:       BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n",
        !          1426:                     HostAdapter, StatusRegister.All);
        !          1427:       if (StatusRegister.Bits.DataInRegisterReady)
        !          1428:        {
        !          1429:          unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
        !          1430:          BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n",
        !          1431:                         HostAdapter, ErrorCode);
        !          1432:        }
        !          1433:       return false;
        !          1434:     }
        !          1435:   /*
        !          1436:     Indicate the Host Adapter Hard Reset completed successfully.
        !          1437:   */
        !          1438:   return true;
        !          1439: }
        !          1440: 
        !          1441: 
        !          1442: /*
        !          1443:   BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
        !          1444:   Host Adapter.
        !          1445: */
        !          1446: 
        !          1447: static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
        !          1448: {
        !          1449:   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
        !          1450:   BusLogic_RequestedReplyLength_T RequestedReplyLength;
        !          1451:   boolean Result = true;
        !          1452:   /*
        !          1453:     FlashPoint Host Adapters do not require this protection.
        !          1454:   */
        !          1455:   if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
        !          1456:   /*
        !          1457:     Issue the Inquire Extended Setup Information command.  Only genuine
        !          1458:     BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
        !          1459:     series Host Adapters that respond to the Geometry Register I/O port will
        !          1460:     fail this command.
        !          1461:   */
        !          1462:   RequestedReplyLength = sizeof(ExtendedSetupInformation);
        !          1463:   if (BusLogic_Command(HostAdapter,
        !          1464:                       BusLogic_InquireExtendedSetupInformation,
        !          1465:                       &RequestedReplyLength,
        !          1466:                       sizeof(RequestedReplyLength),
        !          1467:                       &ExtendedSetupInformation,
        !          1468:                       sizeof(ExtendedSetupInformation))
        !          1469:       != sizeof(ExtendedSetupInformation))
        !          1470:     Result = false;
        !          1471:   /*
        !          1472:     Provide tracing information if requested and return.
        !          1473:   */
        !          1474:   if (BusLogic_GlobalOptions.TraceProbe)
        !          1475:     BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter,
        !          1476:                    HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
        !          1477:   return Result;
        !          1478: }
        !          1479: 
        !          1480: 
        !          1481: /*
        !          1482:   BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
        !          1483:   from Host Adapter and initializes the Host Adapter structure.
        !          1484: */
        !          1485: 
        !          1486: static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
        !          1487:                                                     *HostAdapter)
        !          1488: {
        !          1489:   BusLogic_BoardID_T BoardID;
        !          1490:   BusLogic_Configuration_T Configuration;
        !          1491:   BusLogic_SetupInformation_T SetupInformation;
        !          1492:   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
        !          1493:   BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber;
        !          1494:   BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
        !          1495:   BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
        !          1496:   BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
        !          1497:   BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest;
        !          1498:   BusLogic_AutoSCSIData_T AutoSCSIData;
        !          1499:   BusLogic_GeometryRegister_T GeometryRegister;
        !          1500:   BusLogic_RequestedReplyLength_T RequestedReplyLength;
        !          1501:   unsigned char *TargetPointer, Character;
        !          1502:   int TargetID, i;
        !          1503:   /*
        !          1504:     Configuration Information for FlashPoint Host Adapters is provided in the
        !          1505:     FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
        !          1506:     Initialize fields in the Host Adapter structure from the FlashPoint_Info
        !          1507:     structure.
        !          1508:   */
        !          1509:   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          1510:     {
        !          1511:       FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
        !          1512:       TargetPointer = HostAdapter->ModelName;
        !          1513:       *TargetPointer++ = 'B';
        !          1514:       *TargetPointer++ = 'T';
        !          1515:       *TargetPointer++ = '-';
        !          1516:       for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
        !          1517:        *TargetPointer++ = FlashPointInfo->ModelNumber[i];
        !          1518:       *TargetPointer++ = '\0';
        !          1519:       strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
        !          1520:       HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
        !          1521:       HostAdapter->ExtendedTranslationEnabled =
        !          1522:        FlashPointInfo->ExtendedTranslationEnabled;
        !          1523:       HostAdapter->ParityCheckingEnabled =
        !          1524:        FlashPointInfo->ParityCheckingEnabled;
        !          1525:       HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
        !          1526:       HostAdapter->LevelSensitiveInterrupt = true;
        !          1527:       HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
        !          1528:       HostAdapter->HostDifferentialSCSI = false;
        !          1529:       HostAdapter->HostSupportsSCAM = true;
        !          1530:       HostAdapter->HostUltraSCSI = true;
        !          1531:       HostAdapter->ExtendedLUNSupport = true;
        !          1532:       HostAdapter->TerminationInfoValid = true;
        !          1533:       HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
        !          1534:       HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
        !          1535:       HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
        !          1536:       HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
        !          1537:       HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
        !          1538:       HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
        !          1539:       HostAdapter->MaxLogicalUnits = 32;
        !          1540:       HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
        !          1541:       HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
        !          1542:       HostAdapter->DriverQueueDepth = 255;
        !          1543:       HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
        !          1544:       HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
        !          1545:       HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
        !          1546:       HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
        !          1547:       HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
        !          1548:       HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
        !          1549:       HostAdapter->TaggedQueuingPermitted = 0xFFFF;
        !          1550:       goto Common;
        !          1551:     }
        !          1552:   /*
        !          1553:     Issue the Inquire Board ID command.
        !          1554:   */
        !          1555:   if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
        !          1556:                       &BoardID, sizeof(BoardID)) != sizeof(BoardID))
        !          1557:     return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
        !          1558:   /*
        !          1559:     Issue the Inquire Configuration command.
        !          1560:   */
        !          1561:   if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
        !          1562:                       &Configuration, sizeof(Configuration))
        !          1563:       != sizeof(Configuration))
        !          1564:     return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
        !          1565:   /*
        !          1566:     Issue the Inquire Setup Information command.
        !          1567:   */
        !          1568:   RequestedReplyLength = sizeof(SetupInformation);
        !          1569:   if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
        !          1570:                       &RequestedReplyLength, sizeof(RequestedReplyLength),
        !          1571:                       &SetupInformation, sizeof(SetupInformation))
        !          1572:       != sizeof(SetupInformation))
        !          1573:     return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
        !          1574:   /*
        !          1575:     Issue the Inquire Extended Setup Information command.
        !          1576:   */
        !          1577:   RequestedReplyLength = sizeof(ExtendedSetupInformation);
        !          1578:   if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
        !          1579:                       &RequestedReplyLength, sizeof(RequestedReplyLength),
        !          1580:                       &ExtendedSetupInformation,
        !          1581:                       sizeof(ExtendedSetupInformation))
        !          1582:       != sizeof(ExtendedSetupInformation))
        !          1583:     return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
        !          1584:   /*
        !          1585:     Issue the Inquire Firmware Version 3rd Digit command.
        !          1586:   */
        !          1587:   FirmwareVersion3rdDigit = '\0';
        !          1588:   if (BoardID.FirmwareVersion1stDigit > '0')
        !          1589:     if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
        !          1590:                         NULL, 0, &FirmwareVersion3rdDigit,
        !          1591:                         sizeof(FirmwareVersion3rdDigit))
        !          1592:        != sizeof(FirmwareVersion3rdDigit))
        !          1593:       return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
        !          1594:   /*
        !          1595:     Issue the Inquire Host Adapter Model Number command.
        !          1596:   */
        !          1597:   if (ExtendedSetupInformation.BusType == 'A' &&
        !          1598:       BoardID.FirmwareVersion1stDigit == '2')
        !          1599:     /* BusLogic BT-542B ISA 2.xx */
        !          1600:     strcpy(HostAdapterModelNumber, "542B");
        !          1601:   else if (ExtendedSetupInformation.BusType == 'E' &&
        !          1602:           BoardID.FirmwareVersion1stDigit == '2' &&
        !          1603:           (BoardID.FirmwareVersion2ndDigit <= '1' ||
        !          1604:            (BoardID.FirmwareVersion2ndDigit == '2' &&
        !          1605:             FirmwareVersion3rdDigit == '0')))
        !          1606:     /* BusLogic BT-742A EISA 2.1x or 2.20 */
        !          1607:     strcpy(HostAdapterModelNumber, "742A");
        !          1608:   else if (ExtendedSetupInformation.BusType == 'E' &&
        !          1609:           BoardID.FirmwareVersion1stDigit == '0')
        !          1610:     /* AMI FastDisk EISA Series 441 0.x */
        !          1611:     strcpy(HostAdapterModelNumber, "747A");
        !          1612:   else
        !          1613:     {
        !          1614:       RequestedReplyLength = sizeof(HostAdapterModelNumber);
        !          1615:       if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber,
        !          1616:                           &RequestedReplyLength, sizeof(RequestedReplyLength),
        !          1617:                           &HostAdapterModelNumber,
        !          1618:                           sizeof(HostAdapterModelNumber))
        !          1619:          != sizeof(HostAdapterModelNumber))
        !          1620:        return BusLogic_Failure(HostAdapter,
        !          1621:                                "INQUIRE HOST ADAPTER MODEL NUMBER");
        !          1622:     }
        !          1623:   /*
        !          1624:     BusLogic MultiMaster Host Adapters can be identified by their model number
        !          1625:     and the major version number of their firmware as follows:
        !          1626: 
        !          1627:     5.xx       BusLogic "W" Series Host Adapters:
        !          1628:                  BT-948/958/958D
        !          1629:     4.xx       BusLogic "C" Series Host Adapters:
        !          1630:                  BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
        !          1631:     3.xx       BusLogic "S" Series Host Adapters:
        !          1632:                  BT-747S/747D/757S/757D/445S/545S/542D
        !          1633:                  BT-542B/742A (revision H)
        !          1634:     2.xx       BusLogic "A" Series Host Adapters:
        !          1635:                  BT-542B/742A (revision G and below)
        !          1636:     0.xx       AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
        !          1637:   */
        !          1638:   /*
        !          1639:     Save the Model Name and Host Adapter Name in the Host Adapter structure.
        !          1640:   */
        !          1641:   TargetPointer = HostAdapter->ModelName;
        !          1642:   *TargetPointer++ = 'B';
        !          1643:   *TargetPointer++ = 'T';
        !          1644:   *TargetPointer++ = '-';
        !          1645:   for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
        !          1646:     {
        !          1647:       Character = HostAdapterModelNumber[i];
        !          1648:       if (Character == ' ' || Character == '\0') break;
        !          1649:       *TargetPointer++ = Character;
        !          1650:     }
        !          1651:   *TargetPointer++ = '\0';
        !          1652:   /*
        !          1653:     Save the Firmware Version in the Host Adapter structure.
        !          1654:   */
        !          1655:   TargetPointer = HostAdapter->FirmwareVersion;
        !          1656:   *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
        !          1657:   *TargetPointer++ = '.';
        !          1658:   *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
        !          1659:   if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
        !          1660:     *TargetPointer++ = FirmwareVersion3rdDigit;
        !          1661:   *TargetPointer = '\0';
        !          1662:   /*
        !          1663:     Issue the Inquire Firmware Version Letter command.
        !          1664:   */
        !          1665:   if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0)
        !          1666:     {
        !          1667:       if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
        !          1668:                           NULL, 0, &FirmwareVersionLetter,
        !          1669:                           sizeof(FirmwareVersionLetter))
        !          1670:          != sizeof(FirmwareVersionLetter))
        !          1671:        return BusLogic_Failure(HostAdapter,
        !          1672:                                "INQUIRE FIRMWARE VERSION LETTER");
        !          1673:       if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
        !          1674:        *TargetPointer++ = FirmwareVersionLetter;
        !          1675:       *TargetPointer = '\0';
        !          1676:     }
        !          1677:   /*
        !          1678:     Save the Host Adapter SCSI ID in the Host Adapter structure.
        !          1679:   */
        !          1680:   HostAdapter->SCSI_ID = Configuration.HostAdapterID;
        !          1681:   /*
        !          1682:     Determine the Bus Type and save it in the Host Adapter structure, determine
        !          1683:     and save the IRQ Channel if necessary, and determine and save the DMA
        !          1684:     Channel for ISA Host Adapters.
        !          1685:   */
        !          1686:   HostAdapter->HostAdapterBusType =
        !          1687:     BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
        !          1688:   if (HostAdapter->IRQ_Channel == 0)
        !          1689:     {
        !          1690:       if (Configuration.IRQ_Channel9)
        !          1691:        HostAdapter->IRQ_Channel = 9;
        !          1692:       else if (Configuration.IRQ_Channel10)
        !          1693:        HostAdapter->IRQ_Channel = 10;
        !          1694:       else if (Configuration.IRQ_Channel11)
        !          1695:        HostAdapter->IRQ_Channel = 11;
        !          1696:       else if (Configuration.IRQ_Channel12)
        !          1697:        HostAdapter->IRQ_Channel = 12;
        !          1698:       else if (Configuration.IRQ_Channel14)
        !          1699:        HostAdapter->IRQ_Channel = 14;
        !          1700:       else if (Configuration.IRQ_Channel15)
        !          1701:        HostAdapter->IRQ_Channel = 15;
        !          1702:     }
        !          1703:   if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
        !          1704:     {
        !          1705:       if (Configuration.DMA_Channel5)
        !          1706:        HostAdapter->DMA_Channel = 5;
        !          1707:       else if (Configuration.DMA_Channel6)
        !          1708:        HostAdapter->DMA_Channel = 6;
        !          1709:       else if (Configuration.DMA_Channel7)
        !          1710:        HostAdapter->DMA_Channel = 7;
        !          1711:     }
        !          1712:   /*
        !          1713:     Determine whether Extended Translation is enabled and save it in
        !          1714:     the Host Adapter structure.
        !          1715:   */
        !          1716:   GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
        !          1717:   HostAdapter->ExtendedTranslationEnabled =
        !          1718:     GeometryRegister.Bits.ExtendedTranslationEnabled;
        !          1719:   /*
        !          1720:     Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
        !          1721:     SCSI flag, Differential SCSI flag, SCAM Supported flag, and
        !          1722:     Ultra SCSI flag in the Host Adapter structure.
        !          1723:   */
        !          1724:   HostAdapter->HostAdapterScatterGatherLimit =
        !          1725:     ExtendedSetupInformation.ScatterGatherLimit;
        !          1726:   HostAdapter->DriverScatterGatherLimit =
        !          1727:     HostAdapter->HostAdapterScatterGatherLimit;
        !          1728:   if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
        !          1729:     HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
        !          1730:   if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
        !          1731:     HostAdapter->LevelSensitiveInterrupt = true;
        !          1732:   HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
        !          1733:   HostAdapter->HostDifferentialSCSI =
        !          1734:     ExtendedSetupInformation.HostDifferentialSCSI;
        !          1735:   HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
        !          1736:   HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
        !          1737:   /*
        !          1738:     Determine whether Extended LUN Format CCBs are supported and save the
        !          1739:     information in the Host Adapter structure.
        !          1740:   */
        !          1741:   if (HostAdapter->FirmwareVersion[0] == '5' ||
        !          1742:       (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
        !          1743:     HostAdapter->ExtendedLUNSupport = true;
        !          1744:   /*
        !          1745:     Issue the Inquire PCI Host Adapter Information command to read the
        !          1746:     Termination Information from "W" series MultiMaster Host Adapters.
        !          1747:   */
        !          1748:   if (HostAdapter->FirmwareVersion[0] == '5')
        !          1749:     {
        !          1750:       if (BusLogic_Command(HostAdapter,
        !          1751:                           BusLogic_InquirePCIHostAdapterInformation,
        !          1752:                           NULL, 0, &PCIHostAdapterInformation,
        !          1753:                           sizeof(PCIHostAdapterInformation))
        !          1754:          != sizeof(PCIHostAdapterInformation))
        !          1755:        return BusLogic_Failure(HostAdapter,
        !          1756:                                "INQUIRE PCI HOST ADAPTER INFORMATION");
        !          1757:       /*
        !          1758:        Save the Termination Information in the Host Adapter structure.
        !          1759:       */
        !          1760:       if (PCIHostAdapterInformation.GenericInfoValid)
        !          1761:        {
        !          1762:          HostAdapter->TerminationInfoValid = true;
        !          1763:          HostAdapter->LowByteTerminated =
        !          1764:            PCIHostAdapterInformation.LowByteTerminated;
        !          1765:          HostAdapter->HighByteTerminated =
        !          1766:            PCIHostAdapterInformation.HighByteTerminated;
        !          1767:        }
        !          1768:     }
        !          1769:   /*
        !          1770:     Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
        !          1771:     from "W" and "C" series MultiMaster Host Adapters.
        !          1772:   */
        !          1773:   if (HostAdapter->FirmwareVersion[0] >= '4')
        !          1774:     {
        !          1775:       FetchHostAdapterLocalRAMRequest.ByteOffset =
        !          1776:        BusLogic_AutoSCSI_BaseOffset;
        !          1777:       FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
        !          1778:       if (BusLogic_Command(HostAdapter,
        !          1779:                           BusLogic_FetchHostAdapterLocalRAM,
        !          1780:                           &FetchHostAdapterLocalRAMRequest,
        !          1781:                           sizeof(FetchHostAdapterLocalRAMRequest),
        !          1782:                           &AutoSCSIData, sizeof(AutoSCSIData))
        !          1783:          != sizeof(AutoSCSIData))
        !          1784:        return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
        !          1785:       /*
        !          1786:        Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
        !          1787:        Information in the Host Adapter structure.
        !          1788:       */
        !          1789:       HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
        !          1790:       HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
        !          1791:       if (HostAdapter->FirmwareVersion[0] == '4')
        !          1792:        {
        !          1793:          HostAdapter->TerminationInfoValid = true;
        !          1794:          HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
        !          1795:          HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
        !          1796:        }
        !          1797:       /*
        !          1798:        Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
        !          1799:        Disconnect Permitted, Ultra Permitted, and SCAM Information in the
        !          1800:        Host Adapter structure.
        !          1801:       */
        !          1802:       HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
        !          1803:       HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
        !          1804:       HostAdapter->SynchronousPermitted =
        !          1805:        AutoSCSIData.SynchronousPermitted;
        !          1806:       HostAdapter->DisconnectPermitted =
        !          1807:        AutoSCSIData.DisconnectPermitted;
        !          1808:       if (HostAdapter->HostUltraSCSI)
        !          1809:        HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
        !          1810:       if (HostAdapter->HostSupportsSCAM)
        !          1811:        {
        !          1812:          HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
        !          1813:          HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
        !          1814:        }
        !          1815:     }
        !          1816:   /*
        !          1817:     Initialize fields in the Host Adapter structure for "S" and "A" series
        !          1818:     MultiMaster Host Adapters.
        !          1819:   */
        !          1820:   if (HostAdapter->FirmwareVersion[0] < '4')
        !          1821:     {
        !          1822:       if (SetupInformation.SynchronousInitiationEnabled)
        !          1823:        {
        !          1824:          HostAdapter->SynchronousPermitted = 0xFF;
        !          1825:          if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)
        !          1826:            {
        !          1827:              if (ExtendedSetupInformation.Misc.FastOnEISA)
        !          1828:                HostAdapter->FastPermitted = 0xFF;
        !          1829:              if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
        !          1830:                HostAdapter->WidePermitted = 0xFF;
        !          1831:            }
        !          1832:        }
        !          1833:       HostAdapter->DisconnectPermitted = 0xFF;
        !          1834:       HostAdapter->ParityCheckingEnabled =
        !          1835:        SetupInformation.ParityCheckingEnabled;
        !          1836:       HostAdapter->BusResetEnabled = true;
        !          1837:     }
        !          1838:   /*
        !          1839:     Determine the maximum number of Target IDs and Logical Units supported by
        !          1840:     this driver for Wide and Narrow Host Adapters.
        !          1841:   */
        !          1842:   HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
        !          1843:   HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
        !          1844:   /*
        !          1845:     Select appropriate values for the Mailbox Count, Driver Queue Depth,
        !          1846:     Initial CCBs, and Incremental CCBs variables based on whether or not Strict
        !          1847:     Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
        !          1848:     then there is no performance degradation in using the maximum possible
        !          1849:     number of Outgoing and Incoming Mailboxes and allowing the Tagged and
        !          1850:     Untagged Queue Depths to determine the actual utilization.  If Strict Round
        !          1851:     Robin Mode is not supported, then the Host Adapter must scan all the
        !          1852:     Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
        !          1853:     cause a substantial performance penalty.  The host adapters actually have
        !          1854:     room to store the following number of CCBs internally; that is, they can
        !          1855:     internally queue and manage this many active commands on the SCSI bus
        !          1856:     simultaneously.  Performance measurements demonstrate that the Driver Queue
        !          1857:     Depth should be set to the Mailbox Count, rather than the Host Adapter
        !          1858:     Queue Depth (internal CCB capacity), as it is more efficient to have the
        !          1859:     queued commands waiting in Outgoing Mailboxes if necessary than to block
        !          1860:     the process in the higher levels of the SCSI Subsystem.
        !          1861: 
        !          1862:        192       BT-948/958/958D
        !          1863:        100       BT-946C/956C/956CD/747C/757C/757CD/445C
        !          1864:         50       BT-545C/540CF
        !          1865:         30       BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
        !          1866:   */
        !          1867:   if (HostAdapter->FirmwareVersion[0] == '5')
        !          1868:     HostAdapter->HostAdapterQueueDepth = 192;
        !          1869:   else if (HostAdapter->FirmwareVersion[0] == '4')
        !          1870:     HostAdapter->HostAdapterQueueDepth =
        !          1871:       (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
        !          1872:   else HostAdapter->HostAdapterQueueDepth = 30;
        !          1873:   if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0)
        !          1874:     {
        !          1875:       HostAdapter->StrictRoundRobinModeSupport = true;
        !          1876:       HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
        !          1877:     }
        !          1878:   else
        !          1879:     {
        !          1880:       HostAdapter->StrictRoundRobinModeSupport = false;
        !          1881:       HostAdapter->MailboxCount = 32;
        !          1882:     }
        !          1883:   HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
        !          1884:   HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
        !          1885:   HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
        !          1886:   /*
        !          1887:     Tagged Queuing support is available and operates properly on all "W" series
        !          1888:     MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
        !          1889:     firmware version 4.22 and above, and on "S" series MultiMaster Host
        !          1890:     Adapters with firmware version 3.35 and above.
        !          1891:   */
        !          1892:   HostAdapter->TaggedQueuingPermitted = 0;
        !          1893:   switch (HostAdapter->FirmwareVersion[0])
        !          1894:     {
        !          1895:     case '5':
        !          1896:       HostAdapter->TaggedQueuingPermitted = 0xFFFF;
        !          1897:       break;
        !          1898:     case '4':
        !          1899:       if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
        !          1900:        HostAdapter->TaggedQueuingPermitted = 0xFFFF;
        !          1901:       break;
        !          1902:     case '3':
        !          1903:       if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
        !          1904:        HostAdapter->TaggedQueuingPermitted = 0xFFFF;
        !          1905:       break;
        !          1906:     }
        !          1907:   /*
        !          1908:     Determine the Host Adapter BIOS Address if the BIOS is enabled and
        !          1909:     save it in the Host Adapter structure.  The BIOS is disabled if the
        !          1910:     BIOS_Address is 0.
        !          1911:   */
        !          1912:   HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
        !          1913:   /*
        !          1914:     ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
        !          1915:   */
        !          1916:   if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus &&
        !          1917:       (void *) high_memory > (void *) MAX_DMA_ADDRESS)
        !          1918:     HostAdapter->BounceBuffersRequired = true;
        !          1919:   /*
        !          1920:     BusLogic BT-445S Host Adapters prior to board revision E have a hardware
        !          1921:     bug whereby when the BIOS is enabled, transfers to/from the same address
        !          1922:     range the BIOS occupies modulo 16MB are handled incorrectly.  Only properly
        !          1923:     functioning BT-445S Host Adapters have firmware version 3.37, so require
        !          1924:     that ISA Bounce Buffers be used for the buggy BT-445S models if there is
        !          1925:     more than 16MB memory.
        !          1926:   */
        !          1927:   if (HostAdapter->BIOS_Address > 0 &&
        !          1928:       strcmp(HostAdapter->ModelName, "BT-445S") == 0 &&
        !          1929:       strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 &&
        !          1930:       (void *) high_memory > (void *) MAX_DMA_ADDRESS)
        !          1931:     HostAdapter->BounceBuffersRequired = true;
        !          1932:   /*
        !          1933:     Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
        !          1934:   */
        !          1935: Common:
        !          1936:   /*
        !          1937:     Initialize the Host Adapter Full Model Name from the Model Name.
        !          1938:   */
        !          1939:   strcpy(HostAdapter->FullModelName, "BusLogic ");
        !          1940:   strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
        !          1941:   /*
        !          1942:     Select an appropriate value for the Tagged Queue Depth either from a
        !          1943:     BusLogic Driver Options specification, or based on whether this Host
        !          1944:     Adapter requires that ISA Bounce Buffers be used.  The Tagged Queue Depth
        !          1945:     is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
        !          1946:     Initialize the Untagged Queue Depth.
        !          1947:   */
        !          1948:   for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
        !          1949:     {
        !          1950:       unsigned char QueueDepth = 0;
        !          1951:       if (HostAdapter->DriverOptions != NULL &&
        !          1952:          HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
        !          1953:        QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
        !          1954:       else if (HostAdapter->BounceBuffersRequired)
        !          1955:        QueueDepth = BusLogic_TaggedQueueDepthBB;
        !          1956:       HostAdapter->QueueDepth[TargetID] = QueueDepth;
        !          1957:     }
        !          1958:   if (HostAdapter->BounceBuffersRequired)
        !          1959:     HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
        !          1960:   else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
        !          1961:   if (HostAdapter->DriverOptions != NULL)
        !          1962:     HostAdapter->CommonQueueDepth =
        !          1963:       HostAdapter->DriverOptions->CommonQueueDepth;
        !          1964:   if (HostAdapter->CommonQueueDepth > 0 &&
        !          1965:       HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
        !          1966:     HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
        !          1967:   /*
        !          1968:     Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
        !          1969:     Therefore, mask the Tagged Queuing Permitted Default bits with the
        !          1970:     Disconnect/Reconnect Permitted bits.
        !          1971:   */
        !          1972:   HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
        !          1973:   /*
        !          1974:     Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
        !          1975:     Options Tagged Queuing specification.
        !          1976:   */
        !          1977:   if (HostAdapter->DriverOptions != NULL)
        !          1978:     HostAdapter->TaggedQueuingPermitted =
        !          1979:       (HostAdapter->DriverOptions->TaggedQueuingPermitted &
        !          1980:        HostAdapter->DriverOptions->TaggedQueuingPermittedMask) |
        !          1981:       (HostAdapter->TaggedQueuingPermitted &
        !          1982:        ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
        !          1983:   /*
        !          1984:     Select appropriate values for the Error Recovery Strategy array
        !          1985:     either from a BusLogic Driver Options specification, or using
        !          1986:     BusLogic_ErrorRecovery_Default.
        !          1987:   */
        !          1988:   for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
        !          1989:     if (HostAdapter->DriverOptions != NULL)
        !          1990:       HostAdapter->ErrorRecoveryStrategy[TargetID] =
        !          1991:        HostAdapter->DriverOptions->ErrorRecoveryStrategy[TargetID];
        !          1992:     else HostAdapter->ErrorRecoveryStrategy[TargetID] =
        !          1993:           BusLogic_ErrorRecovery_Default;
        !          1994:   /*
        !          1995:     Select an appropriate value for Bus Settle Time either from a BusLogic
        !          1996:     Driver Options specification, or from BusLogic_DefaultBusSettleTime.
        !          1997:   */
        !          1998:   if (HostAdapter->DriverOptions != NULL &&
        !          1999:       HostAdapter->DriverOptions->BusSettleTime > 0)
        !          2000:     HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
        !          2001:   else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
        !          2002:   /*
        !          2003:     Indicate reading the Host Adapter Configuration completed successfully.
        !          2004:   */
        !          2005:   return true;
        !          2006: }
        !          2007: 
        !          2008: 
        !          2009: /*
        !          2010:   BusLogic_ReportHostAdapterConfiguration reports the configuration of
        !          2011:   Host Adapter.
        !          2012: */
        !          2013: 
        !          2014: static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T
        !          2015:                                                       *HostAdapter)
        !          2016: {
        !          2017:   unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
        !          2018:   unsigned short SynchronousPermitted, FastPermitted;
        !          2019:   unsigned short UltraPermitted, WidePermitted;
        !          2020:   unsigned short DisconnectPermitted, TaggedQueuingPermitted;
        !          2021:   boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
        !          2022:   boolean CommonErrorRecovery;
        !          2023:   char SynchronousString[BusLogic_MaxTargetDevices+1];
        !          2024:   char WideString[BusLogic_MaxTargetDevices+1];
        !          2025:   char DisconnectString[BusLogic_MaxTargetDevices+1];
        !          2026:   char TaggedQueuingString[BusLogic_MaxTargetDevices+1];
        !          2027:   char ErrorRecoveryString[BusLogic_MaxTargetDevices+1];
        !          2028:   char *SynchronousMessage = SynchronousString;
        !          2029:   char *WideMessage = WideString;
        !          2030:   char *DisconnectMessage = DisconnectString;
        !          2031:   char *TaggedQueuingMessage = TaggedQueuingString;
        !          2032:   char *ErrorRecoveryMessage = ErrorRecoveryString;
        !          2033:   int TargetID;
        !          2034:   BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
        !          2035:                HostAdapter, HostAdapter->ModelName,
        !          2036:                BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType],
        !          2037:                (HostAdapter->HostWideSCSI ? " Wide" : ""),
        !          2038:                (HostAdapter->HostDifferentialSCSI ? " Differential" : ""),
        !          2039:                (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
        !          2040:   BusLogic_Info("  Firmware Version: %s, I/O Address: 0x%X, "
        !          2041:                "IRQ Channel: %d/%s\n", HostAdapter,
        !          2042:                HostAdapter->FirmwareVersion,
        !          2043:                HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
        !          2044:                (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
        !          2045:   if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus)
        !          2046:     {
        !          2047:       BusLogic_Info("  DMA Channel: ", HostAdapter);
        !          2048:       if (HostAdapter->DMA_Channel > 0)
        !          2049:        BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
        !          2050:       else BusLogic_Info("None, ", HostAdapter);
        !          2051:       if (HostAdapter->BIOS_Address > 0)
        !          2052:        BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter,
        !          2053:                      HostAdapter->BIOS_Address);
        !          2054:       else BusLogic_Info("BIOS Address: None, ", HostAdapter);
        !          2055:     }
        !          2056:   else
        !          2057:     {
        !          2058:       BusLogic_Info("  PCI Bus: %d, Device: %d, Address: ",
        !          2059:                    HostAdapter, HostAdapter->Bus, HostAdapter->Device);
        !          2060:       if (HostAdapter->PCI_Address > 0)
        !          2061:        BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
        !          2062:       else BusLogic_Info("Unassigned, ", HostAdapter);
        !          2063:     }
        !          2064:   BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter,
        !          2065:                HostAdapter->SCSI_ID);
        !          2066:   BusLogic_Info("  Parity Checking: %s, Extended Translation: %s\n",
        !          2067:                HostAdapter,
        !          2068:                (HostAdapter->ParityCheckingEnabled
        !          2069:                 ? "Enabled" : "Disabled"),
        !          2070:                (HostAdapter->ExtendedTranslationEnabled
        !          2071:                 ? "Enabled" : "Disabled"));
        !          2072:   AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
        !          2073:   SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
        !          2074:   FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
        !          2075:   UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
        !          2076:   if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
        !          2077:        (HostAdapter->FirmwareVersion[0] >= '4' ||
        !          2078:        HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) ||
        !          2079:       BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          2080:     {
        !          2081:       CommonSynchronousNegotiation = false;
        !          2082:       if (SynchronousPermitted == 0)
        !          2083:        {
        !          2084:          SynchronousMessage = "Disabled";
        !          2085:          CommonSynchronousNegotiation = true;
        !          2086:        }
        !          2087:       else if (SynchronousPermitted == AllTargetsMask)
        !          2088:        {
        !          2089:          if (FastPermitted == 0)
        !          2090:            {
        !          2091:              SynchronousMessage = "Slow";
        !          2092:              CommonSynchronousNegotiation = true;
        !          2093:            }
        !          2094:          else if (FastPermitted == AllTargetsMask)
        !          2095:            {
        !          2096:              if (UltraPermitted == 0)
        !          2097:                {
        !          2098:                  SynchronousMessage = "Fast";
        !          2099:                  CommonSynchronousNegotiation = true;
        !          2100:                }
        !          2101:              else if (UltraPermitted == AllTargetsMask)
        !          2102:                {
        !          2103:                  SynchronousMessage = "Ultra";
        !          2104:                  CommonSynchronousNegotiation = true;
        !          2105:                }
        !          2106:            }
        !          2107:        }
        !          2108:       if (!CommonSynchronousNegotiation)
        !          2109:        {
        !          2110:          for (TargetID = 0;
        !          2111:               TargetID < HostAdapter->MaxTargetDevices;
        !          2112:               TargetID++)
        !          2113:            SynchronousString[TargetID] =
        !          2114:              ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' :
        !          2115:               (!(FastPermitted & (1 << TargetID)) ? 'S' :
        !          2116:                (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
        !          2117:          SynchronousString[HostAdapter->SCSI_ID] = '#';
        !          2118:          SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
        !          2119:        }
        !          2120:     }
        !          2121:   else SynchronousMessage =
        !          2122:         (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
        !          2123:   WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
        !          2124:   if (WidePermitted == 0)
        !          2125:     WideMessage = "Disabled";
        !          2126:   else if (WidePermitted == AllTargetsMask)
        !          2127:     WideMessage = "Enabled";
        !          2128:   else
        !          2129:     {
        !          2130:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2131:         WideString[TargetID] =
        !          2132:           ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
        !          2133:       WideString[HostAdapter->SCSI_ID] = '#';
        !          2134:       WideString[HostAdapter->MaxTargetDevices] = '\0';
        !          2135:     }
        !          2136:   DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
        !          2137:   if (DisconnectPermitted == 0)
        !          2138:     DisconnectMessage = "Disabled";
        !          2139:   else if (DisconnectPermitted == AllTargetsMask)
        !          2140:     DisconnectMessage = "Enabled";
        !          2141:   else
        !          2142:     {
        !          2143:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2144:        DisconnectString[TargetID] =
        !          2145:          ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
        !          2146:       DisconnectString[HostAdapter->SCSI_ID] = '#';
        !          2147:       DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
        !          2148:     }
        !          2149:   TaggedQueuingPermitted =
        !          2150:     HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
        !          2151:   if (TaggedQueuingPermitted == 0)
        !          2152:     TaggedQueuingMessage = "Disabled";
        !          2153:   else if (TaggedQueuingPermitted == AllTargetsMask)
        !          2154:     TaggedQueuingMessage = "Enabled";
        !          2155:   else
        !          2156:     {
        !          2157:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2158:        TaggedQueuingString[TargetID] =
        !          2159:          ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
        !          2160:       TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
        !          2161:       TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
        !          2162:     }
        !          2163:   BusLogic_Info("  Synchronous Negotiation: %s, Wide Negotiation: %s\n",
        !          2164:                HostAdapter, SynchronousMessage, WideMessage);
        !          2165:   BusLogic_Info("  Disconnect/Reconnect: %s, Tagged Queuing: %s\n",
        !          2166:                HostAdapter, DisconnectMessage, TaggedQueuingMessage);
        !          2167:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          2168:     {
        !          2169:       BusLogic_Info("  Scatter/Gather Limit: %d of %d segments, "
        !          2170:                    "Mailboxes: %d\n", HostAdapter,
        !          2171:                    HostAdapter->DriverScatterGatherLimit,
        !          2172:                    HostAdapter->HostAdapterScatterGatherLimit,
        !          2173:                    HostAdapter->MailboxCount);
        !          2174:       BusLogic_Info("  Driver Queue Depth: %d, "
        !          2175:                    "Host Adapter Queue Depth: %d\n",
        !          2176:                    HostAdapter, HostAdapter->DriverQueueDepth,
        !          2177:                    HostAdapter->HostAdapterQueueDepth);
        !          2178:     }
        !          2179:   else BusLogic_Info("  Driver Queue Depth: %d, "
        !          2180:                     "Scatter/Gather Limit: %d segments\n",
        !          2181:                     HostAdapter, HostAdapter->DriverQueueDepth,
        !          2182:                     HostAdapter->DriverScatterGatherLimit);
        !          2183:   BusLogic_Info("  Tagged Queue Depth: ", HostAdapter);
        !          2184:   CommonTaggedQueueDepth = true;
        !          2185:   for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2186:     if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0])
        !          2187:       {
        !          2188:        CommonTaggedQueueDepth = false;
        !          2189:        break;
        !          2190:       }
        !          2191:   if (CommonTaggedQueueDepth)
        !          2192:     {
        !          2193:       if (HostAdapter->QueueDepth[0] > 0)
        !          2194:        BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
        !          2195:       else BusLogic_Info("Automatic", HostAdapter);
        !          2196:     }
        !          2197:   else BusLogic_Info("Individual", HostAdapter);
        !          2198:   BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter,
        !          2199:                HostAdapter->UntaggedQueueDepth);
        !          2200:   CommonErrorRecovery = true;
        !          2201:   for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2202:     if (HostAdapter->ErrorRecoveryStrategy[TargetID] !=
        !          2203:        HostAdapter->ErrorRecoveryStrategy[0])
        !          2204:       {
        !          2205:        CommonErrorRecovery = false;
        !          2206:        break;
        !          2207:       }
        !          2208:   if (CommonErrorRecovery)
        !          2209:     ErrorRecoveryMessage =
        !          2210:       BusLogic_ErrorRecoveryStrategyNames[
        !          2211:        HostAdapter->ErrorRecoveryStrategy[0]];
        !          2212:   else
        !          2213:     {
        !          2214:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2215:        ErrorRecoveryString[TargetID] =
        !          2216:          BusLogic_ErrorRecoveryStrategyLetters[
        !          2217:            HostAdapter->ErrorRecoveryStrategy[TargetID]];
        !          2218:       ErrorRecoveryString[HostAdapter->SCSI_ID] = '#';
        !          2219:       ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0';
        !          2220:     }
        !          2221:   BusLogic_Info("  Error Recovery Strategy: %s, SCSI Bus Reset: %s\n",
        !          2222:                HostAdapter, ErrorRecoveryMessage,
        !          2223:                (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled"));
        !          2224:   if (HostAdapter->TerminationInfoValid)
        !          2225:     {
        !          2226:       if (HostAdapter->HostWideSCSI)
        !          2227:        BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
        !          2228:                      (HostAdapter->LowByteTerminated
        !          2229:                       ? (HostAdapter->HighByteTerminated
        !          2230:                          ? "Both Enabled" : "Low Enabled")
        !          2231:                       : (HostAdapter->HighByteTerminated
        !          2232:                          ? "High Enabled" : "Both Disabled")));
        !          2233:       else BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
        !          2234:                         (HostAdapter->LowByteTerminated ?
        !          2235:                          "Enabled" : "Disabled"));
        !          2236:       if (HostAdapter->HostSupportsSCAM)
        !          2237:        BusLogic_Info(", SCAM: %s", HostAdapter,
        !          2238:                      (HostAdapter->SCAM_Enabled
        !          2239:                       ? (HostAdapter->SCAM_Level2
        !          2240:                          ? "Enabled, Level 2" : "Enabled, Level 1")
        !          2241:                       : "Disabled"));
        !          2242:       BusLogic_Info("\n", HostAdapter);
        !          2243:     }
        !          2244:   /*
        !          2245:     Indicate reporting the Host Adapter configuration completed successfully.
        !          2246:   */
        !          2247:   return true;
        !          2248: }
        !          2249: 
        !          2250: 
        !          2251: /*
        !          2252:   BusLogic_AcquireResources acquires the system resources necessary to use
        !          2253:   Host Adapter.
        !          2254: */
        !          2255: 
        !          2256: static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
        !          2257: {
        !          2258:   if (HostAdapter->IRQ_Channel == 0)
        !          2259:     {
        !          2260:       BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
        !          2261:                     HostAdapter);
        !          2262:       return false;
        !          2263:     }
        !          2264:   /*
        !          2265:     Acquire shared access to the IRQ Channel.
        !          2266:   */
        !          2267:   if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
        !          2268:                  SA_INTERRUPT | SA_SHIRQ,
        !          2269:                  HostAdapter->FullModelName, HostAdapter) < 0)
        !          2270:     {
        !          2271:       BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
        !          2272:                     HostAdapter, HostAdapter->IRQ_Channel);
        !          2273:       return false;
        !          2274:     }
        !          2275:   HostAdapter->IRQ_ChannelAcquired = true;
        !          2276:   /*
        !          2277:     Acquire exclusive access to the DMA Channel.
        !          2278:   */
        !          2279:   if (HostAdapter->DMA_Channel > 0)
        !          2280:     {
        !          2281:       if (request_dma(HostAdapter->DMA_Channel,
        !          2282:                      HostAdapter->FullModelName) < 0)
        !          2283:        {
        !          2284:          BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
        !          2285:                         HostAdapter, HostAdapter->DMA_Channel);
        !          2286:          return false;
        !          2287:        }
        !          2288:       set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
        !          2289:       enable_dma(HostAdapter->DMA_Channel);
        !          2290:       HostAdapter->DMA_ChannelAcquired = true;
        !          2291:     }
        !          2292:   /*
        !          2293:     Indicate the System Resource Acquisition completed successfully,
        !          2294:   */
        !          2295:   return true;
        !          2296: }
        !          2297: 
        !          2298: 
        !          2299: /*
        !          2300:   BusLogic_ReleaseResources releases any system resources previously acquired
        !          2301:   by BusLogic_AcquireResources.
        !          2302: */
        !          2303: 
        !          2304: static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter)
        !          2305: {
        !          2306:   /*
        !          2307:     Release shared access to the IRQ Channel.
        !          2308:   */
        !          2309:   if (HostAdapter->IRQ_ChannelAcquired)
        !          2310:     free_irq(HostAdapter->IRQ_Channel, HostAdapter);
        !          2311:   /*
        !          2312:     Release exclusive access to the DMA Channel.
        !          2313:   */
        !          2314:   if (HostAdapter->DMA_ChannelAcquired)
        !          2315:     free_dma(HostAdapter->DMA_Channel);
        !          2316: }
        !          2317: 
        !          2318: 
        !          2319: /*
        !          2320:   BusLogic_InitializeHostAdapter initializes Host Adapter.  This is the only
        !          2321:   function called during SCSI Host Adapter detection which modifies the state
        !          2322:   of the Host Adapter from its initial power on or hard reset state.
        !          2323: */
        !          2324: 
        !          2325: static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T
        !          2326:                                              *HostAdapter)
        !          2327: {
        !          2328:   BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
        !          2329:   BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest;
        !          2330:   BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest;
        !          2331:   int TargetID;
        !          2332:   /*
        !          2333:     Initialize the pointers to the first and last CCBs that are queued for
        !          2334:     completion processing.
        !          2335:   */
        !          2336:   HostAdapter->FirstCompletedCCB = NULL;
        !          2337:   HostAdapter->LastCompletedCCB = NULL;
        !          2338:   /*
        !          2339:     Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
        !          2340:     Command Successful Flag, Active Commands, and Commands Since Reset
        !          2341:     for each Target Device.
        !          2342:   */
        !          2343:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2344:     {
        !          2345:       HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
        !          2346:       HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
        !          2347:       HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
        !          2348:       HostAdapter->ActiveCommands[TargetID] = 0;
        !          2349:       HostAdapter->CommandsSinceReset[TargetID] = 0;
        !          2350:     }
        !          2351:   /*
        !          2352:     FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
        !          2353:   */
        !          2354:   if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done;
        !          2355:   /*
        !          2356:     Initialize the Outgoing and Incoming Mailbox pointers.
        !          2357:   */
        !          2358:   HostAdapter->FirstOutgoingMailbox =
        !          2359:     (BusLogic_OutgoingMailbox_T *) HostAdapter->MailboxSpace;
        !          2360:   HostAdapter->LastOutgoingMailbox =
        !          2361:     HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
        !          2362:   HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
        !          2363:   HostAdapter->FirstIncomingMailbox =
        !          2364:     (BusLogic_IncomingMailbox_T *) (HostAdapter->LastOutgoingMailbox + 1);
        !          2365:   HostAdapter->LastIncomingMailbox =
        !          2366:     HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
        !          2367:   HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
        !          2368:   /*
        !          2369:     Initialize the Outgoing and Incoming Mailbox structures.
        !          2370:   */
        !          2371:   memset(HostAdapter->FirstOutgoingMailbox, 0,
        !          2372:         HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T));
        !          2373:   memset(HostAdapter->FirstIncomingMailbox, 0,
        !          2374:         HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T));
        !          2375:   /*
        !          2376:     Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
        !          2377:   */
        !          2378:   ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
        !          2379:   ExtendedMailboxRequest.BaseMailboxAddress =
        !          2380:     Virtual_to_Bus(HostAdapter->FirstOutgoingMailbox);
        !          2381:   if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
        !          2382:                       &ExtendedMailboxRequest,
        !          2383:                       sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
        !          2384:     return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
        !          2385:   /*
        !          2386:     Enable Strict Round Robin Mode if supported by the Host Adapter.  In
        !          2387:     Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
        !          2388:     Mailbox for each new command, rather than scanning through all the
        !          2389:     Outgoing Mailboxes to find any that have new commands in them.  Strict
        !          2390:     Round Robin Mode is significantly more efficient.
        !          2391:   */
        !          2392:   if (HostAdapter->StrictRoundRobinModeSupport)
        !          2393:     {
        !          2394:       RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
        !          2395:       if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
        !          2396:                           &RoundRobinModeRequest,
        !          2397:                           sizeof(RoundRobinModeRequest), NULL, 0) < 0)
        !          2398:        return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
        !          2399:     }
        !          2400:   /*
        !          2401:     For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
        !          2402:     Format command to allow 32 Logical Units per Target Device.
        !          2403:   */
        !          2404:   if (HostAdapter->ExtendedLUNSupport)
        !          2405:     {
        !          2406:       SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
        !          2407:       if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat,
        !          2408:                           &SetCCBFormatRequest, sizeof(SetCCBFormatRequest),
        !          2409:                           NULL, 0) < 0)
        !          2410:        return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
        !          2411:     }
        !          2412:   /*
        !          2413:     Announce Successful Initialization.
        !          2414:   */
        !          2415: Done:
        !          2416:   if (!HostAdapter->HostAdapterInitialized)
        !          2417:     {
        !          2418:       BusLogic_Info("*** %s Initialized Successfully ***\n",
        !          2419:                    HostAdapter, HostAdapter->FullModelName);
        !          2420:       BusLogic_Info("\n", HostAdapter);
        !          2421:     }
        !          2422:   else BusLogic_Warning("*** %s Initialized Successfully ***\n",
        !          2423:                        HostAdapter, HostAdapter->FullModelName);
        !          2424:   HostAdapter->HostAdapterInitialized = true;
        !          2425:   /*
        !          2426:     Indicate the Host Adapter Initialization completed successfully.
        !          2427:   */
        !          2428:   return true;
        !          2429: }
        !          2430: 
        !          2431: 
        !          2432: /*
        !          2433:   BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
        !          2434:   through Host Adapter.
        !          2435: */
        !          2436: 
        !          2437: static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T
        !          2438:                                            *HostAdapter)
        !          2439: {
        !          2440:   BusLogic_InstalledDevices_T InstalledDevices;
        !          2441:   BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
        !          2442:   BusLogic_SetupInformation_T SetupInformation;
        !          2443:   BusLogic_SynchronousPeriod_T SynchronousPeriod;
        !          2444:   BusLogic_RequestedReplyLength_T RequestedReplyLength;
        !          2445:   int TargetID;
        !          2446:   /*
        !          2447:     Wait a few seconds between the Host Adapter Hard Reset which initiates
        !          2448:     a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
        !          2449:     confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
        !          2450:   */
        !          2451:   BusLogic_Delay(HostAdapter->BusSettleTime);
        !          2452:   /*
        !          2453:     FlashPoint Host Adapters do not provide for Target Device Inquiry.
        !          2454:   */
        !          2455:   if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
        !          2456:   /*
        !          2457:     Inhibit the Target Device Inquiry if requested.
        !          2458:   */
        !          2459:   if (HostAdapter->DriverOptions != NULL &&
        !          2460:       HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
        !          2461:     return true;
        !          2462:   /*
        !          2463:     Issue the Inquire Target Devices command for host adapters with firmware
        !          2464:     version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
        !          2465:     for older host adapters.  This is necessary to force Synchronous Transfer
        !          2466:     Negotiation so that the Inquire Setup Information and Inquire Synchronous
        !          2467:     Period commands will return valid data.  The Inquire Target Devices command
        !          2468:     is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
        !          2469:     Logical Unit 0 of each Target Device.
        !          2470:   */
        !          2471:   if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
        !          2472:     {
        !          2473:       if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0,
        !          2474:                           &InstalledDevices, sizeof(InstalledDevices))
        !          2475:          != sizeof(InstalledDevices))
        !          2476:        return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
        !          2477:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2478:        HostAdapter->TargetFlags[TargetID].TargetExists =
        !          2479:          (InstalledDevices & (1 << TargetID) ? true : false);
        !          2480:     }
        !          2481:   else
        !          2482:     {
        !          2483:       if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
        !          2484:                           NULL, 0, &InstalledDevicesID0to7,
        !          2485:                           sizeof(InstalledDevicesID0to7))
        !          2486:          != sizeof(InstalledDevicesID0to7))
        !          2487:        return BusLogic_Failure(HostAdapter,
        !          2488:                                "INQUIRE INSTALLED DEVICES ID 0 TO 7");
        !          2489:       for (TargetID = 0; TargetID < 8; TargetID++)
        !          2490:        HostAdapter->TargetFlags[TargetID].TargetExists =
        !          2491:          (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
        !          2492:     }
        !          2493:   /*
        !          2494:     Issue the Inquire Setup Information command.
        !          2495:   */
        !          2496:   RequestedReplyLength = sizeof(SetupInformation);
        !          2497:   if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
        !          2498:                       &RequestedReplyLength, sizeof(RequestedReplyLength),
        !          2499:                       &SetupInformation, sizeof(SetupInformation))
        !          2500:       != sizeof(SetupInformation))
        !          2501:     return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
        !          2502:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2503:       HostAdapter->SynchronousOffset[TargetID] =
        !          2504:        (TargetID < 8
        !          2505:         ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
        !          2506:         : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
        !          2507:   if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
        !          2508:     for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2509:       HostAdapter->TargetFlags[TargetID].WideTransfersActive =
        !          2510:        (TargetID < 8
        !          2511:         ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
        !          2512:            ? true : false)
        !          2513:         : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
        !          2514:            ? true : false));
        !          2515:   /*
        !          2516:     Issue the Inquire Synchronous Period command.
        !          2517:   */
        !          2518:   if (HostAdapter->FirmwareVersion[0] >= '3')
        !          2519:     {
        !          2520:       RequestedReplyLength = sizeof(SynchronousPeriod);
        !          2521:       if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
        !          2522:                           &RequestedReplyLength, sizeof(RequestedReplyLength),
        !          2523:                           &SynchronousPeriod, sizeof(SynchronousPeriod))
        !          2524:          != sizeof(SynchronousPeriod))
        !          2525:        return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
        !          2526:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2527:        HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
        !          2528:     }
        !          2529:   else
        !          2530:     for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2531:       if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
        !          2532:        HostAdapter->SynchronousPeriod[TargetID] =
        !          2533:          20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
        !          2534:                                   .TransferPeriod;
        !          2535:   /*
        !          2536:     Indicate the Target Device Inquiry completed successfully.
        !          2537:   */
        !          2538:   return true;
        !          2539: }
        !          2540: 
        !          2541: 
        !          2542: /*
        !          2543:   BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible
        !          2544:   through Host Adapter.
        !          2545: */
        !          2546: 
        !          2547: static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T
        !          2548:                                            *HostAdapter)
        !          2549: {
        !          2550:   int TargetID;
        !          2551:   /*
        !          2552:     Inhibit the Target Device Inquiry and Reporting if requested.
        !          2553:   */
        !          2554:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
        !          2555:       HostAdapter->DriverOptions != NULL &&
        !          2556:       HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
        !          2557:     return;
        !          2558:   /*
        !          2559:     Report on the Target Devices found.
        !          2560:   */
        !          2561:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2562:     {
        !          2563:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          2564:       if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported)
        !          2565:        {
        !          2566:          int SynchronousTransferRate = 0;
        !          2567:          if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          2568:            {
        !          2569:              boolean WideTransfersActive;
        !          2570:              FlashPoint_InquireTargetInfo(
        !          2571:                HostAdapter->CardHandle, TargetID,
        !          2572:                &HostAdapter->SynchronousPeriod[TargetID],
        !          2573:                &HostAdapter->SynchronousOffset[TargetID],
        !          2574:                &WideTransfersActive);
        !          2575:              TargetFlags->WideTransfersActive = WideTransfersActive;
        !          2576:            }
        !          2577:          else if (TargetFlags->WideTransfersSupported &&
        !          2578:                   (HostAdapter->WidePermitted & (1 << TargetID)) &&
        !          2579:                   strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0)
        !          2580:            TargetFlags->WideTransfersActive = true;
        !          2581:          if (HostAdapter->SynchronousPeriod[TargetID] > 0)
        !          2582:            SynchronousTransferRate =
        !          2583:              100000 / HostAdapter->SynchronousPeriod[TargetID];
        !          2584:          if (TargetFlags->WideTransfersActive)
        !          2585:            SynchronousTransferRate <<= 1;
        !          2586:          if (SynchronousTransferRate >= 9950)
        !          2587:            {
        !          2588:              SynchronousTransferRate = (SynchronousTransferRate + 50) / 100;
        !          2589:              BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
        !          2590:                            "%d.%01d MB/sec, offset %d\n",
        !          2591:                            HostAdapter, TargetID,
        !          2592:                            HostAdapter->QueueDepth[TargetID],
        !          2593:                            (TargetFlags->WideTransfersActive ? "Wide " : ""),
        !          2594:                            SynchronousTransferRate / 10,
        !          2595:                            SynchronousTransferRate % 10,
        !          2596:                            HostAdapter->SynchronousOffset[TargetID]);
        !          2597:            }
        !          2598:          else if (SynchronousTransferRate > 0)
        !          2599:            {
        !          2600:              SynchronousTransferRate = (SynchronousTransferRate + 5) / 10;
        !          2601:              BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
        !          2602:                            "%d.%02d MB/sec, offset %d\n",
        !          2603:                            HostAdapter, TargetID,
        !          2604:                            HostAdapter->QueueDepth[TargetID],
        !          2605:                            (TargetFlags->WideTransfersActive ? "Wide " : ""),
        !          2606:                            SynchronousTransferRate / 100,
        !          2607:                            SynchronousTransferRate % 100,
        !          2608:                            HostAdapter->SynchronousOffset[TargetID]);
        !          2609:            }
        !          2610:          else BusLogic_Info("Target %d: Queue Depth %d, Asynchronous\n",
        !          2611:                             HostAdapter, TargetID,
        !          2612:                             HostAdapter->QueueDepth[TargetID]);
        !          2613:          TargetFlags->TargetInfoReported = true;
        !          2614:        }
        !          2615:     }
        !          2616: }
        !          2617: 
        !          2618: 
        !          2619: /*
        !          2620:   BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
        !          2621:   structure.  The base, io_port, n_io_ports, irq, and dma_channel fields in the
        !          2622:   SCSI Host structure are intentionally left uninitialized, as this driver
        !          2623:   handles acquisition and release of these resources explicitly, as well as
        !          2624:   ensuring exclusive access to the Host Adapter hardware and data structures
        !          2625:   through explicit acquisition and release of the Host Adapter's Lock.
        !          2626: */
        !          2627: 
        !          2628: static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
        !          2629:                                               *HostAdapter,
        !          2630:                                             SCSI_Host_T *Host)
        !          2631: {
        !          2632:   Host->max_id = HostAdapter->MaxTargetDevices;
        !          2633:   Host->max_lun = HostAdapter->MaxLogicalUnits;
        !          2634:   Host->max_channel = 0;
        !          2635:   Host->unique_id = HostAdapter->IO_Address;
        !          2636:   Host->this_id = HostAdapter->SCSI_ID;
        !          2637:   Host->can_queue = HostAdapter->DriverQueueDepth;
        !          2638:   Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
        !          2639:   Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
        !          2640:   Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
        !          2641: }
        !          2642: 
        !          2643: 
        !          2644: /*
        !          2645:   BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based
        !          2646:   on the Host Adapter's Total Queue Depth and the number, type, speed, and
        !          2647:   capabilities of the Target Devices.  When called for the last Host Adapter,
        !          2648:   it reports on the Target Device Information for all BusLogic Host Adapters
        !          2649:   since all the Target Devices have now been probed.
        !          2650: */
        !          2651: 
        !          2652: static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host,
        !          2653:                                       SCSI_Device_T *DeviceList)
        !          2654: {
        !          2655:   BusLogic_HostAdapter_T *HostAdapter =
        !          2656:     (BusLogic_HostAdapter_T *) Host->hostdata;
        !          2657:   int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0;
        !          2658:   int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0;
        !          2659:   int AllocatedQueueDepth = 0;
        !          2660:   SCSI_Device_T *Device;
        !          2661:   int TargetID;
        !          2662:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2663:     if (HostAdapter->TargetFlags[TargetID].TargetExists)
        !          2664:       {
        !          2665:        int QueueDepth = HostAdapter->QueueDepth[TargetID];
        !          2666:        if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
        !          2667:            (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
        !          2668:          {
        !          2669:            TaggedDeviceCount++;
        !          2670:            if (QueueDepth == 0) AutomaticTaggedDeviceCount++;
        !          2671:          }
        !          2672:        else
        !          2673:          {
        !          2674:            UntaggedDeviceCount++;
        !          2675:            if (QueueDepth == 0 ||
        !          2676:                QueueDepth > HostAdapter->UntaggedQueueDepth)
        !          2677:              {
        !          2678:                QueueDepth = HostAdapter->UntaggedQueueDepth;
        !          2679:                HostAdapter->QueueDepth[TargetID] = QueueDepth;
        !          2680:              }
        !          2681:          }
        !          2682:        AllocatedQueueDepth += QueueDepth;
        !          2683:        if (QueueDepth == 1)
        !          2684:          HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
        !          2685:       }
        !          2686:   HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount;
        !          2687:   if (AutomaticTaggedDeviceCount > 0)
        !          2688:     {
        !          2689:       AutomaticTaggedQueueDepth =
        !          2690:        (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth)
        !          2691:        / AutomaticTaggedDeviceCount;
        !          2692:       if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth)
        !          2693:        AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
        !          2694:       if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth)
        !          2695:        AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth;
        !          2696:       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          2697:        if (HostAdapter->TargetFlags[TargetID].TargetExists &&
        !          2698:            HostAdapter->QueueDepth[TargetID] == 0)
        !          2699:          {
        !          2700:            AllocatedQueueDepth += AutomaticTaggedQueueDepth;
        !          2701:            HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth;
        !          2702:          }
        !          2703:     }
        !          2704:   for (Device = DeviceList; Device != NULL; Device = Device->next)
        !          2705:     if (Device->host == Host)
        !          2706:       Device->queue_depth = HostAdapter->QueueDepth[Device->id];
        !          2707:   /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */
        !          2708:   AllocatedQueueDepth += HostAdapter->TargetDeviceCount;
        !          2709:   if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth)
        !          2710:     AllocatedQueueDepth = HostAdapter->DriverQueueDepth;
        !          2711:   BusLogic_CreateAdditionalCCBs(HostAdapter,
        !          2712:                                AllocatedQueueDepth
        !          2713:                                - HostAdapter->AllocatedCCBs,
        !          2714:                                false);
        !          2715:   if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
        !          2716:     for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
        !          2717:         HostAdapter != NULL;
        !          2718:         HostAdapter = HostAdapter->Next)
        !          2719:       BusLogic_ReportTargetDeviceInfo(HostAdapter);
        !          2720: }
        !          2721: 
        !          2722: 
        !          2723: /*
        !          2724:   BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
        !          2725:   I/O Addresses where they may be located, initializing, registering, and
        !          2726:   reporting the configuration of each BusLogic Host Adapter it finds.  It
        !          2727:   returns the number of BusLogic Host Adapters successfully initialized and
        !          2728:   registered.
        !          2729: */
        !          2730: 
        !          2731: int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
        !          2732: {
        !          2733:   int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
        !          2734:   BusLogic_HostAdapter_T *PrototypeHostAdapter;
        !          2735:   if (BusLogic_ProbeOptions.NoProbe) return 0;
        !          2736:   BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *)
        !          2737:     kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T),
        !          2738:            GFP_ATOMIC);
        !          2739:   if (BusLogic_ProbeInfoList == NULL)
        !          2740:     {
        !          2741:       BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
        !          2742:       return 0;
        !          2743:     }
        !          2744:   memset(BusLogic_ProbeInfoList, 0,
        !          2745:         BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T));
        !          2746:   PrototypeHostAdapter = (BusLogic_HostAdapter_T *)
        !          2747:     kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC);
        !          2748:   if (PrototypeHostAdapter == NULL)
        !          2749:     {
        !          2750:       kfree(BusLogic_ProbeInfoList);
        !          2751:       BusLogic_Error("BusLogic: Unable to allocate Prototype "
        !          2752:                     "Host Adapter\n", NULL);
        !          2753:       return 0;
        !          2754:     }
        !          2755:   memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
        !          2756:   if (BusLogic_Options != NULL)
        !          2757:     BusLogic_ParseDriverOptions(BusLogic_Options);
        !          2758:   BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
        !          2759:   for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
        !          2760:     {
        !          2761:       BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
        !          2762:       BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
        !          2763:       SCSI_Host_T *Host;
        !          2764:       if (ProbeInfo->IO_Address == 0) continue;
        !          2765:       memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
        !          2766:       HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
        !          2767:       HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
        !          2768:       HostAdapter->IO_Address = ProbeInfo->IO_Address;
        !          2769:       HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
        !          2770:       HostAdapter->Bus = ProbeInfo->Bus;
        !          2771:       HostAdapter->Device = ProbeInfo->Device;
        !          2772:       HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
        !          2773:       HostAdapter->AddressCount =
        !          2774:        BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
        !          2775:       /*
        !          2776:        Probe the Host Adapter.  If unsuccessful, abort further initialization.
        !          2777:       */
        !          2778:       if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
        !          2779:       /*
        !          2780:        Hard Reset the Host Adapter.  If unsuccessful, abort further
        !          2781:        initialization.
        !          2782:       */
        !          2783:       if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
        !          2784:       /*
        !          2785:        Check the Host Adapter.  If unsuccessful, abort further initialization.
        !          2786:       */
        !          2787:       if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
        !          2788:       /*
        !          2789:        Initialize the Driver Options field if provided.
        !          2790:       */
        !          2791:       if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
        !          2792:        HostAdapter->DriverOptions =
        !          2793:          &BusLogic_DriverOptions[DriverOptionsIndex++];
        !          2794:       /*
        !          2795:        Announce the Driver Version and Date, Author's Name, Copyright Notice,
        !          2796:        and Electronic Mail Address.
        !          2797:       */
        !          2798:       BusLogic_AnnounceDriver(HostAdapter);
        !          2799:       /*
        !          2800:        Register usage of the I/O Address range.  From this point onward, any
        !          2801:        failure will be assumed to be due to a problem with the Host Adapter,
        !          2802:        rather than due to having mistakenly identified this port as belonging
        !          2803:        to a BusLogic Host Adapter.  The I/O Address range will not be
        !          2804:        released, thereby preventing it from being incorrectly identified as
        !          2805:        any other type of Host Adapter.
        !          2806:       */
        !          2807:       request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
        !          2808:                     "BusLogic");
        !          2809:       /*
        !          2810:        Register the SCSI Host structure.
        !          2811:       */
        !          2812:       Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T));
        !          2813:       HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata;
        !          2814:       memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T));
        !          2815:       HostAdapter->SCSI_Host = Host;
        !          2816:       HostAdapter->HostNumber = Host->host_no;
        !          2817:       Host->select_queue_depths = BusLogic_SelectQueueDepths;
        !          2818:       /*
        !          2819:        Add Host Adapter to the end of the list of registered BusLogic
        !          2820:        Host Adapters.
        !          2821:       */
        !          2822:       BusLogic_RegisterHostAdapter(HostAdapter);
        !          2823:       /*
        !          2824:        Read the Host Adapter Configuration, Configure the Host Adapter,
        !          2825:        Acquire the System Resources necessary to use the Host Adapter, then
        !          2826:        Create the Initial CCBs, Initialize the Host Adapter, and finally
        !          2827:        perform Target Device Inquiry.
        !          2828:       */
        !          2829:       if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
        !          2830:          BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
        !          2831:          BusLogic_AcquireResources(HostAdapter) &&
        !          2832:          BusLogic_CreateInitialCCBs(HostAdapter) &&
        !          2833:          BusLogic_InitializeHostAdapter(HostAdapter) &&
        !          2834:          BusLogic_TargetDeviceInquiry(HostAdapter))
        !          2835:        {
        !          2836:          /*
        !          2837:            Initialization has been completed successfully.  Release and
        !          2838:            re-register usage of the I/O Address range so that the Model
        !          2839:            Name of the Host Adapter will appear, and initialize the SCSI
        !          2840:            Host structure.
        !          2841:          */
        !          2842:          release_region(HostAdapter->IO_Address,
        !          2843:                         HostAdapter->AddressCount);
        !          2844:          request_region(HostAdapter->IO_Address,
        !          2845:                         HostAdapter->AddressCount,
        !          2846:                         HostAdapter->FullModelName);
        !          2847:          BusLogic_InitializeHostStructure(HostAdapter, Host);
        !          2848:          BusLogicHostAdapterCount++;
        !          2849:        }
        !          2850:       else
        !          2851:        {
        !          2852:          /*
        !          2853:            An error occurred during Host Adapter Configuration Querying, Host
        !          2854:            Adapter Configuration, Resource Acquisition, CCB Creation, Host
        !          2855:            Adapter Initialization, or Target Device Inquiry, so remove Host
        !          2856:            Adapter from the list of registered BusLogic Host Adapters, destroy
        !          2857:            the CCBs, Release the System Resources, and Unregister the SCSI
        !          2858:            Host.
        !          2859:          */
        !          2860:          BusLogic_DestroyCCBs(HostAdapter);
        !          2861:          BusLogic_ReleaseResources(HostAdapter);
        !          2862:          BusLogic_UnregisterHostAdapter(HostAdapter);
        !          2863:          scsi_unregister(Host);
        !          2864:        }
        !          2865:     }
        !          2866:   kfree(PrototypeHostAdapter);
        !          2867:   kfree(BusLogic_ProbeInfoList);
        !          2868:   BusLogic_ProbeInfoList = NULL;
        !          2869:   return BusLogicHostAdapterCount;
        !          2870: }
        !          2871: 
        !          2872: 
        !          2873: /*
        !          2874:   BusLogic_ReleaseHostAdapter releases all resources previously acquired to
        !          2875:   support a specific Host Adapter, including the I/O Address range, and
        !          2876:   unregisters the BusLogic Host Adapter.
        !          2877: */
        !          2878: 
        !          2879: int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
        !          2880: {
        !          2881:   BusLogic_HostAdapter_T *HostAdapter =
        !          2882:     (BusLogic_HostAdapter_T *) Host->hostdata;
        !          2883:   /*
        !          2884:     FlashPoint Host Adapters must first be released by the FlashPoint
        !          2885:     SCCB Manager.
        !          2886:   */
        !          2887:   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          2888:     FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
        !          2889:   /*
        !          2890:     Destroy the CCBs and release any system resources acquired to
        !          2891:     support Host Adapter.
        !          2892:   */
        !          2893:   BusLogic_DestroyCCBs(HostAdapter);
        !          2894:   BusLogic_ReleaseResources(HostAdapter);
        !          2895:   /*
        !          2896:     Release usage of the I/O Address range.
        !          2897:   */
        !          2898:   release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
        !          2899:   /*
        !          2900:     Remove Host Adapter from the list of registered BusLogic Host Adapters.
        !          2901:   */
        !          2902:   BusLogic_UnregisterHostAdapter(HostAdapter);
        !          2903:   return 0;
        !          2904: }
        !          2905: 
        !          2906: 
        !          2907: /*
        !          2908:   BusLogic_QueueCompletedCCB queues CCB for completion processing.
        !          2909: */
        !          2910: 
        !          2911: static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB)
        !          2912: {
        !          2913:   BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
        !          2914:   CCB->Status = BusLogic_CCB_Completed;
        !          2915:   CCB->Next = NULL;
        !          2916:   if (HostAdapter->FirstCompletedCCB == NULL)
        !          2917:     {
        !          2918:       HostAdapter->FirstCompletedCCB = CCB;
        !          2919:       HostAdapter->LastCompletedCCB = CCB;
        !          2920:     }
        !          2921:   else
        !          2922:     {
        !          2923:       HostAdapter->LastCompletedCCB->Next = CCB;
        !          2924:       HostAdapter->LastCompletedCCB = CCB;
        !          2925:     }
        !          2926:   HostAdapter->ActiveCommands[CCB->TargetID]--;
        !          2927: }
        !          2928: 
        !          2929: 
        !          2930: /*
        !          2931:   BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
        !          2932:   the Host Adapter Status and Target Device Status.
        !          2933: */
        !          2934: 
        !          2935: static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
        !          2936:                                      BusLogic_HostAdapterStatus_T
        !          2937:                                        HostAdapterStatus,
        !          2938:                                      BusLogic_TargetDeviceStatus_T
        !          2939:                                        TargetDeviceStatus)
        !          2940: {
        !          2941:   int HostStatus;
        !          2942:   switch (HostAdapterStatus)
        !          2943:     {
        !          2944:     case BusLogic_CommandCompletedNormally:
        !          2945:     case BusLogic_LinkedCommandCompleted:
        !          2946:     case BusLogic_LinkedCommandCompletedWithFlag:
        !          2947:       HostStatus = DID_OK;
        !          2948:       break;
        !          2949:     case BusLogic_SCSISelectionTimeout:
        !          2950:       HostStatus = DID_TIME_OUT;
        !          2951:       break;
        !          2952:     case BusLogic_InvalidOutgoingMailboxActionCode:
        !          2953:     case BusLogic_InvalidCommandOperationCode:
        !          2954:     case BusLogic_InvalidCommandParameter:
        !          2955:       BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n",
        !          2956:                       HostAdapter, HostAdapterStatus);
        !          2957:     case BusLogic_DataUnderRun:
        !          2958:     case BusLogic_DataOverRun:
        !          2959:     case BusLogic_UnexpectedBusFree:
        !          2960:     case BusLogic_LinkedCCBhasInvalidLUN:
        !          2961:     case BusLogic_AutoRequestSenseFailed:
        !          2962:     case BusLogic_TaggedQueuingMessageRejected:
        !          2963:     case BusLogic_UnsupportedMessageReceived:
        !          2964:     case BusLogic_HostAdapterHardwareFailed:
        !          2965:     case BusLogic_TargetDeviceReconnectedImproperly:
        !          2966:     case BusLogic_AbortQueueGenerated:
        !          2967:     case BusLogic_HostAdapterSoftwareError:
        !          2968:     case BusLogic_HostAdapterHardwareTimeoutError:
        !          2969:     case BusLogic_SCSIParityErrorDetected:
        !          2970:       HostStatus = DID_ERROR;
        !          2971:       break;
        !          2972:     case BusLogic_InvalidBusPhaseRequested:
        !          2973:     case BusLogic_TargetFailedResponseToATN:
        !          2974:     case BusLogic_HostAdapterAssertedRST:
        !          2975:     case BusLogic_OtherDeviceAssertedRST:
        !          2976:     case BusLogic_HostAdapterAssertedBusDeviceReset:
        !          2977:       HostStatus = DID_RESET;
        !          2978:       break;
        !          2979:     default:
        !          2980:       BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n",
        !          2981:                       HostAdapter, HostAdapterStatus);
        !          2982:       HostStatus = DID_ERROR;
        !          2983:       break;
        !          2984:     }
        !          2985:   return (HostStatus << 16) | TargetDeviceStatus;
        !          2986: }
        !          2987: 
        !          2988: 
        !          2989: /*
        !          2990:   BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
        !          2991:   Incoming Mailbox entries for completion processing.
        !          2992: */
        !          2993: 
        !          2994: static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter)
        !          2995: {
        !          2996:   /*
        !          2997:     Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
        !          2998:     any completed CCBs for further processing.  It is essential that for each
        !          2999:     CCB and SCSI Command issued, command completion processing is performed
        !          3000:     exactly once.  Therefore, only Incoming Mailboxes with completion code
        !          3001:     Command Completed Without Error, Command Completed With Error, or Command
        !          3002:     Aborted At Host Request are saved for completion processing.  When an
        !          3003:     Incoming Mailbox has a completion code of Aborted Command Not Found, the
        !          3004:     CCB had already completed or been aborted before the current Abort request
        !          3005:     was processed, and so completion processing has already occurred and no
        !          3006:     further action should be taken.
        !          3007:   */
        !          3008:   BusLogic_IncomingMailbox_T *NextIncomingMailbox =
        !          3009:     HostAdapter->NextIncomingMailbox;
        !          3010:   BusLogic_CompletionCode_T CompletionCode;
        !          3011:   while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
        !          3012:         BusLogic_IncomingMailboxFree)
        !          3013:     {
        !          3014:       BusLogic_CCB_T *CCB = (BusLogic_CCB_T *)
        !          3015:        Bus_to_Virtual(NextIncomingMailbox->CCB);
        !          3016:       if (CompletionCode != BusLogic_AbortedCommandNotFound)
        !          3017:        {
        !          3018:          if (CCB->Status == BusLogic_CCB_Active ||
        !          3019:              CCB->Status == BusLogic_CCB_Reset)
        !          3020:            {
        !          3021:              /*
        !          3022:                Save the Completion Code for this CCB and queue the CCB
        !          3023:                for completion processing.
        !          3024:              */
        !          3025:              CCB->CompletionCode = CompletionCode;
        !          3026:              BusLogic_QueueCompletedCCB(CCB);
        !          3027:            }
        !          3028:          else
        !          3029:            {
        !          3030:              /*
        !          3031:                If a CCB ever appears in an Incoming Mailbox and is not marked
        !          3032:                as status Active or Reset, then there is most likely a bug in
        !          3033:                the Host Adapter firmware.
        !          3034:              */
        !          3035:              BusLogic_Warning("Illegal CCB #%ld status %d in "
        !          3036:                               "Incoming Mailbox\n", HostAdapter,
        !          3037:                               CCB->SerialNumber, CCB->Status);
        !          3038:            }
        !          3039:        }
        !          3040:       NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
        !          3041:       if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
        !          3042:        NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
        !          3043:     }
        !          3044:   HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
        !          3045: }
        !          3046: 
        !          3047: 
        !          3048: /*
        !          3049:   BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
        !          3050:   Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
        !          3051:   calling the SCSI Subsystem Completion Routines.  The Host Adapter's Lock
        !          3052:   should already have been acquired by the caller.
        !          3053: */
        !          3054: 
        !          3055: static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
        !          3056: {
        !          3057:   if (HostAdapter->ProcessCompletedCCBsActive) return;
        !          3058:   HostAdapter->ProcessCompletedCCBsActive = true;
        !          3059:   while (HostAdapter->FirstCompletedCCB != NULL)
        !          3060:     {
        !          3061:       BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
        !          3062:       SCSI_Command_T *Command = CCB->Command;
        !          3063:       HostAdapter->FirstCompletedCCB = CCB->Next;
        !          3064:       if (HostAdapter->FirstCompletedCCB == NULL)
        !          3065:        HostAdapter->LastCompletedCCB = NULL;
        !          3066:       /*
        !          3067:        Process the Completed CCB.
        !          3068:       */
        !          3069:       if (CCB->Opcode == BusLogic_BusDeviceReset)
        !          3070:        {
        !          3071:          int TargetID = CCB->TargetID;
        !          3072:          BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
        !          3073:                           "%d Completed\n", HostAdapter,
        !          3074:                           CCB->SerialNumber, TargetID);
        !          3075:          BusLogic_IncrementErrorCounter(
        !          3076:            &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
        !          3077:          HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
        !          3078:          HostAdapter->CommandsSinceReset[TargetID] = 0;
        !          3079:          HostAdapter->LastResetCompleted[TargetID] = jiffies;
        !          3080:          /*
        !          3081:            Place CCB back on the Host Adapter's free list.
        !          3082:          */
        !          3083:          BusLogic_DeallocateCCB(CCB);
        !          3084:          /*
        !          3085:            Bus Device Reset CCBs have the Command field non-NULL only when a
        !          3086:            Bus Device Reset was requested for a Command that did not have a
        !          3087:            currently active CCB in the Host Adapter (i.e., a Synchronous
        !          3088:            Bus Device Reset), and hence would not have its Completion Routine
        !          3089:            called otherwise.
        !          3090:          */
        !          3091:          while (Command != NULL)
        !          3092:            {
        !          3093:              SCSI_Command_T *NextCommand = Command->reset_chain;
        !          3094:              Command->reset_chain = NULL;
        !          3095:              Command->result = DID_RESET << 16;
        !          3096:              Command->scsi_done(Command);
        !          3097:              Command = NextCommand;
        !          3098:            }
        !          3099:          /*
        !          3100:            Iterate over the CCBs for this Host Adapter performing completion
        !          3101:            processing for any CCBs marked as Reset for this Target.
        !          3102:          */
        !          3103:          for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3104:            if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
        !          3105:              {
        !          3106:                Command = CCB->Command;
        !          3107:                BusLogic_DeallocateCCB(CCB);
        !          3108:                HostAdapter->ActiveCommands[TargetID]--;
        !          3109:                Command->result = DID_RESET << 16;
        !          3110:                Command->scsi_done(Command);
        !          3111:              }
        !          3112:          HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
        !          3113:        }
        !          3114:       else
        !          3115:        {
        !          3116:          /*
        !          3117:            Translate the Completion Code, Host Adapter Status, and Target
        !          3118:            Device Status into a SCSI Subsystem Result Code.
        !          3119:          */
        !          3120:          switch (CCB->CompletionCode)
        !          3121:            {
        !          3122:            case BusLogic_IncomingMailboxFree:
        !          3123:            case BusLogic_AbortedCommandNotFound:
        !          3124:            case BusLogic_InvalidCCB:
        !          3125:              BusLogic_Warning("CCB #%ld to Target %d Impossible State\n",
        !          3126:                               HostAdapter, CCB->SerialNumber, CCB->TargetID);
        !          3127:              break;
        !          3128:            case BusLogic_CommandCompletedWithoutError:
        !          3129:              HostAdapter->TargetStatistics[CCB->TargetID]
        !          3130:                           .CommandsCompleted++;
        !          3131:              HostAdapter->TargetFlags[CCB->TargetID]
        !          3132:                           .CommandSuccessfulFlag = true;
        !          3133:              Command->result = DID_OK << 16;
        !          3134:              break;
        !          3135:            case BusLogic_CommandAbortedAtHostRequest:
        !          3136:              BusLogic_Warning("CCB #%ld to Target %d Aborted\n",
        !          3137:                               HostAdapter, CCB->SerialNumber, CCB->TargetID);
        !          3138:              BusLogic_IncrementErrorCounter(
        !          3139:                &HostAdapter->TargetStatistics[CCB->TargetID]
        !          3140:                              .CommandAbortsCompleted);
        !          3141:              Command->result = DID_ABORT << 16;
        !          3142:              break;
        !          3143:            case BusLogic_CommandCompletedWithError:
        !          3144:              Command->result =
        !          3145:                BusLogic_ComputeResultCode(HostAdapter,
        !          3146:                                           CCB->HostAdapterStatus,
        !          3147:                                           CCB->TargetDeviceStatus);
        !          3148:              if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
        !          3149:                {
        !          3150:                  HostAdapter->TargetStatistics[CCB->TargetID]
        !          3151:                               .CommandsCompleted++;
        !          3152:                  if (BusLogic_GlobalOptions.TraceErrors)
        !          3153:                    {
        !          3154:                      int i;
        !          3155:                      BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
        !          3156:                                      "Adapter Status %02X "
        !          3157:                                      "Target Status %02X\n",
        !          3158:                                      HostAdapter, CCB->SerialNumber,
        !          3159:                                      CCB->TargetID, Command->result,
        !          3160:                                      CCB->HostAdapterStatus,
        !          3161:                                      CCB->TargetDeviceStatus);
        !          3162:                      BusLogic_Notice("CDB   ", HostAdapter);
        !          3163:                      for (i = 0; i < CCB->CDB_Length; i++)
        !          3164:                        BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
        !          3165:                      BusLogic_Notice("\n", HostAdapter);
        !          3166:                      BusLogic_Notice("Sense ", HostAdapter);
        !          3167:                      for (i = 0; i < CCB->SenseDataLength; i++)
        !          3168:                        BusLogic_Notice(" %02X", HostAdapter,
        !          3169:                                        Command->sense_buffer[i]);
        !          3170:                      BusLogic_Notice("\n", HostAdapter);
        !          3171:                    }
        !          3172:                }
        !          3173:              break;
        !          3174:            }
        !          3175:          /*
        !          3176:            When an INQUIRY command completes normally, save the
        !          3177:            CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
        !          3178:            Wide Data Transfers Supported) bits.
        !          3179:          */
        !          3180:          if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 &&
        !          3181:              CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
        !          3182:            {
        !          3183:              BusLogic_TargetFlags_T *TargetFlags =
        !          3184:                &HostAdapter->TargetFlags[CCB->TargetID];
        !          3185:              SCSI_Inquiry_T *InquiryResult =
        !          3186:                (SCSI_Inquiry_T *) Command->request_buffer;
        !          3187:              TargetFlags->TargetExists = true;
        !          3188:              TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
        !          3189:              TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
        !          3190:            }
        !          3191:          /*
        !          3192:            Place CCB back on the Host Adapter's free list.
        !          3193:          */
        !          3194:          BusLogic_DeallocateCCB(CCB);
        !          3195:          /*
        !          3196:            Call the SCSI Command Completion Routine.
        !          3197:          */
        !          3198:          Command->scsi_done(Command);
        !          3199:        }
        !          3200:     }
        !          3201:   HostAdapter->ProcessCompletedCCBsActive = false;
        !          3202: }
        !          3203: 
        !          3204: 
        !          3205: /*
        !          3206:   BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
        !          3207:   Adapters.
        !          3208: */
        !          3209: 
        !          3210: static void BusLogic_InterruptHandler(int IRQ_Channel,
        !          3211:                                      void *DeviceIdentifier,
        !          3212:                                      Registers_T *InterruptRegisters)
        !          3213: {
        !          3214:   BusLogic_HostAdapter_T *HostAdapter =
        !          3215:     (BusLogic_HostAdapter_T *) DeviceIdentifier;
        !          3216:   ProcessorFlags_T ProcessorFlags;
        !          3217:   /*
        !          3218:     Acquire exclusive access to Host Adapter.
        !          3219:   */
        !          3220:   BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
        !          3221:   /*
        !          3222:     Handle Interrupts appropriately for each Host Adapter type.
        !          3223:   */
        !          3224:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3225:     {
        !          3226:       BusLogic_InterruptRegister_T InterruptRegister;
        !          3227:       /*
        !          3228:        Read the Host Adapter Interrupt Register.
        !          3229:       */
        !          3230:       InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
        !          3231:       if (InterruptRegister.Bits.InterruptValid)
        !          3232:        {
        !          3233:          /*
        !          3234:            Acknowledge the interrupt and reset the Host Adapter
        !          3235:            Interrupt Register.
        !          3236:          */
        !          3237:          BusLogic_InterruptReset(HostAdapter);
        !          3238:          /*
        !          3239:            Process valid External SCSI Bus Reset and Incoming Mailbox
        !          3240:            Loaded Interrupts.  Command Complete Interrupts are noted,
        !          3241:            and Outgoing Mailbox Available Interrupts are ignored, as
        !          3242:            they are never enabled.
        !          3243:          */
        !          3244:          if (InterruptRegister.Bits.ExternalBusReset)
        !          3245:            HostAdapter->HostAdapterExternalReset = true;
        !          3246:          else if (InterruptRegister.Bits.IncomingMailboxLoaded)
        !          3247:            BusLogic_ScanIncomingMailboxes(HostAdapter);
        !          3248:          else if (InterruptRegister.Bits.CommandComplete)
        !          3249:            HostAdapter->HostAdapterCommandCompleted = true;
        !          3250:        }
        !          3251:     }
        !          3252:   else
        !          3253:     {
        !          3254:       /*
        !          3255:        Check if there is a pending interrupt for this Host Adapter.
        !          3256:       */
        !          3257:       if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
        !          3258:        switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
        !          3259:          {
        !          3260:          case FlashPoint_NormalInterrupt:
        !          3261:            break;
        !          3262:          case FlashPoint_ExternalBusReset:
        !          3263:            HostAdapter->HostAdapterExternalReset = true;
        !          3264:            break;
        !          3265:          case FlashPoint_InternalError:
        !          3266:            BusLogic_Warning("Internal FlashPoint Error detected"
        !          3267:                             " - Resetting Host Adapter\n", HostAdapter);
        !          3268:            HostAdapter->HostAdapterInternalError = true;
        !          3269:            break;
        !          3270:          }
        !          3271:     }
        !          3272:   /*
        !          3273:     Process any completed CCBs.
        !          3274:   */
        !          3275:   if (HostAdapter->FirstCompletedCCB != NULL)
        !          3276:     BusLogic_ProcessCompletedCCBs(HostAdapter);
        !          3277:   /*
        !          3278:     Reset the Host Adapter if requested.
        !          3279:   */
        !          3280:   if (HostAdapter->HostAdapterExternalReset ||
        !          3281:       HostAdapter->HostAdapterInternalError)
        !          3282:     {
        !          3283:       BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
        !          3284:       HostAdapter->HostAdapterExternalReset = false;
        !          3285:       HostAdapter->HostAdapterInternalError = false;
        !          3286:       scsi_mark_host_reset(HostAdapter->SCSI_Host);
        !          3287:     }
        !          3288:   /*
        !          3289:     Release exclusive access to Host Adapter.
        !          3290:   */
        !          3291:   BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
        !          3292: }
        !          3293: 
        !          3294: 
        !          3295: /*
        !          3296:   BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
        !          3297:   Mailbox for execution by Host Adapter.  The Host Adapter's Lock should
        !          3298:   already have been acquired by the caller.
        !          3299: */
        !          3300: 
        !          3301: static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T
        !          3302:                                               *HostAdapter,
        !          3303:                                             BusLogic_ActionCode_T ActionCode,
        !          3304:                                             BusLogic_CCB_T *CCB)
        !          3305: {
        !          3306:   BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
        !          3307:   NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
        !          3308:   if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
        !          3309:     {
        !          3310:       CCB->Status = BusLogic_CCB_Active;
        !          3311:       /*
        !          3312:        The CCB field must be written before the Action Code field since
        !          3313:        the Host Adapter is operating asynchronously and the locking code
        !          3314:        does not protect against simultaneous access by the Host Adapter.
        !          3315:       */
        !          3316:       NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB);
        !          3317:       NextOutgoingMailbox->ActionCode = ActionCode;
        !          3318:       BusLogic_StartMailboxCommand(HostAdapter);
        !          3319:       if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
        !          3320:        NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
        !          3321:       HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
        !          3322:       if (ActionCode == BusLogic_MailboxStartCommand)
        !          3323:        {
        !          3324:          HostAdapter->ActiveCommands[CCB->TargetID]++;
        !          3325:          if (CCB->Opcode != BusLogic_BusDeviceReset)
        !          3326:            HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
        !          3327:        }
        !          3328:       return true;
        !          3329:     }
        !          3330:   return false;
        !          3331: }
        !          3332: 
        !          3333: 
        !          3334: /*
        !          3335:   BusLogic_QueueCommand creates a CCB for Command and places it into an
        !          3336:   Outgoing Mailbox for execution by the associated Host Adapter.
        !          3337: */
        !          3338: 
        !          3339: int BusLogic_QueueCommand(SCSI_Command_T *Command,
        !          3340:                          void (*CompletionRoutine)(SCSI_Command_T *))
        !          3341: {
        !          3342:   BusLogic_HostAdapter_T *HostAdapter =
        !          3343:     (BusLogic_HostAdapter_T *) Command->host->hostdata;
        !          3344:   BusLogic_TargetFlags_T *TargetFlags =
        !          3345:     &HostAdapter->TargetFlags[Command->target];
        !          3346:   BusLogic_TargetStatistics_T *TargetStatistics =
        !          3347:     HostAdapter->TargetStatistics;
        !          3348:   unsigned char *CDB = Command->cmnd;
        !          3349:   int CDB_Length = Command->cmd_len;
        !          3350:   int TargetID = Command->target;
        !          3351:   int LogicalUnit = Command->lun;
        !          3352:   void *BufferPointer = Command->request_buffer;
        !          3353:   int BufferLength = Command->request_bufflen;
        !          3354:   int SegmentCount = Command->use_sg;
        !          3355:   ProcessorFlags_T ProcessorFlags;
        !          3356:   BusLogic_CCB_T *CCB;
        !          3357:   /*
        !          3358:     SCSI REQUEST_SENSE commands will be executed automatically by the Host
        !          3359:     Adapter for any errors, so they should not be executed explicitly unless
        !          3360:     the Sense Data is zero indicating that no error occurred.
        !          3361:   */
        !          3362:   if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
        !          3363:     {
        !          3364:       Command->result = DID_OK << 16;
        !          3365:       CompletionRoutine(Command);
        !          3366:       return 0;
        !          3367:     }
        !          3368:   /*
        !          3369:     Acquire exclusive access to Host Adapter.
        !          3370:   */
        !          3371:   BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3372:   /*
        !          3373:     Allocate a CCB from the Host Adapter's free list.  In the unlikely event
        !          3374:     that there are none available and memory allocation fails, wait 1 second
        !          3375:     and try again.  If that fails, the Host Adapter is probably hung so signal
        !          3376:     an error as a Host Adapter Hard Reset should be initiated soon.
        !          3377:   */
        !          3378:   CCB = BusLogic_AllocateCCB(HostAdapter);
        !          3379:   if (CCB == NULL)
        !          3380:     {
        !          3381:       BusLogic_Delay(1);
        !          3382:       CCB = BusLogic_AllocateCCB(HostAdapter);
        !          3383:       if (CCB == NULL)
        !          3384:        {
        !          3385:          Command->result = DID_ERROR << 16;
        !          3386:          CompletionRoutine(Command);
        !          3387:          goto Done;
        !          3388:        }
        !          3389:     }
        !          3390:   /*
        !          3391:     Initialize the fields in the BusLogic Command Control Block (CCB).
        !          3392:   */
        !          3393:   if (SegmentCount == 0)
        !          3394:     {
        !          3395:       CCB->Opcode = BusLogic_InitiatorCCB;
        !          3396:       CCB->DataLength = BufferLength;
        !          3397:       CCB->DataPointer = Virtual_to_Bus(BufferPointer);
        !          3398:     }
        !          3399:   else
        !          3400:     {
        !          3401:       SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer;
        !          3402:       int Segment;
        !          3403:       CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
        !          3404:       CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T);
        !          3405:       if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3406:        CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList);
        !          3407:       else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
        !          3408:       for (Segment = 0; Segment < SegmentCount; Segment++)
        !          3409:        {
        !          3410:          CCB->ScatterGatherList[Segment].SegmentByteCount =
        !          3411:            ScatterList[Segment].length;
        !          3412:          CCB->ScatterGatherList[Segment].SegmentDataPointer =
        !          3413:            Virtual_to_Bus(ScatterList[Segment].address);
        !          3414:        }
        !          3415:     }
        !          3416:   switch (CDB[0])
        !          3417:     {
        !          3418:     case READ_6:
        !          3419:     case READ_10:
        !          3420:       CCB->DataDirection = BusLogic_DataInLengthChecked;
        !          3421:       TargetStatistics[TargetID].ReadCommands++;
        !          3422:       BusLogic_IncrementByteCounter(
        !          3423:        &TargetStatistics[TargetID].TotalBytesRead, BufferLength);
        !          3424:       BusLogic_IncrementSizeBucket(
        !          3425:        TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
        !          3426:       break;
        !          3427:     case WRITE_6:
        !          3428:     case WRITE_10:
        !          3429:       CCB->DataDirection = BusLogic_DataOutLengthChecked;
        !          3430:       TargetStatistics[TargetID].WriteCommands++;
        !          3431:       BusLogic_IncrementByteCounter(
        !          3432:        &TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
        !          3433:       BusLogic_IncrementSizeBucket(
        !          3434:        TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
        !          3435:       break;
        !          3436:     default:
        !          3437:       CCB->DataDirection = BusLogic_UncheckedDataTransfer;
        !          3438:       break;
        !          3439:     }
        !          3440:   CCB->CDB_Length = CDB_Length;
        !          3441:   CCB->SenseDataLength = sizeof(Command->sense_buffer);
        !          3442:   CCB->HostAdapterStatus = 0;
        !          3443:   CCB->TargetDeviceStatus = 0;
        !          3444:   CCB->TargetID = TargetID;
        !          3445:   CCB->LogicalUnit = LogicalUnit;
        !          3446:   CCB->TagEnable = false;
        !          3447:   CCB->LegacyTagEnable = false;
        !          3448:   /*
        !          3449:     BusLogic recommends that after a Reset the first couple of commands that
        !          3450:     are sent to a Target Device be sent in a non Tagged Queue fashion so that
        !          3451:     the Host Adapter and Target Device can establish Synchronous and Wide
        !          3452:     Transfer before Queue Tag messages can interfere with the Synchronous and
        !          3453:     Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
        !          3454:     the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
        !          3455:     assured that after a Reset any pending commands are requeued before Tagged
        !          3456:     Queuing is enabled and that the Tagged Queuing message will not occur while
        !          3457:     the partition table is being printed.  In addition, some devices do not
        !          3458:     properly handle the transition from non-tagged to tagged commands, so it is
        !          3459:     necessary to wait until there are no pending commands for a target device
        !          3460:     before queuing tagged commands.
        !          3461:   */
        !          3462:   if (HostAdapter->CommandsSinceReset[TargetID]++ >=
        !          3463:        BusLogic_MaxTaggedQueueDepth &&
        !          3464:       !TargetFlags->TaggedQueuingActive &&
        !          3465:       HostAdapter->ActiveCommands[TargetID] == 0 &&
        !          3466:       TargetFlags->TaggedQueuingSupported &&
        !          3467:       (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
        !          3468:     {
        !          3469:       TargetFlags->TaggedQueuingActive = true;
        !          3470:       BusLogic_Notice("Tagged Queuing now active for Target %d\n",
        !          3471:                      HostAdapter, TargetID);
        !          3472:     }
        !          3473:   if (TargetFlags->TaggedQueuingActive)
        !          3474:     {
        !          3475:       BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
        !          3476:       /*
        !          3477:        When using Tagged Queuing with Simple Queue Tags, it appears that disk
        !          3478:        drive controllers do not guarantee that a queued command will not
        !          3479:        remain in a disconnected state indefinitely if commands that read or
        !          3480:        write nearer the head position continue to arrive without interruption.
        !          3481:        Therefore, for each Target Device this driver keeps track of the last
        !          3482:        time either the queue was empty or an Ordered Queue Tag was issued.  If
        !          3483:        more than 4 seconds (one fifth of the 20 second disk timeout) have
        !          3484:        elapsed since this last sequence point, this command will be issued
        !          3485:        with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
        !          3486:        the Target Device to complete all previously queued commands before
        !          3487:        this command may be executed.
        !          3488:       */
        !          3489:       if (HostAdapter->ActiveCommands[TargetID] == 0)
        !          3490:        HostAdapter->LastSequencePoint[TargetID] = jiffies;
        !          3491:       else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
        !          3492:        {
        !          3493:          HostAdapter->LastSequencePoint[TargetID] = jiffies;
        !          3494:          QueueTag = BusLogic_OrderedQueueTag;
        !          3495:        }
        !          3496:       if (HostAdapter->ExtendedLUNSupport)
        !          3497:        {
        !          3498:          CCB->TagEnable = true;
        !          3499:          CCB->QueueTag = QueueTag;
        !          3500:        }
        !          3501:       else
        !          3502:        {
        !          3503:          CCB->LegacyTagEnable = true;
        !          3504:          CCB->LegacyQueueTag = QueueTag;
        !          3505:        }
        !          3506:     }
        !          3507:   memcpy(CCB->CDB, CDB, CDB_Length);
        !          3508:   CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer);
        !          3509:   CCB->Command = Command;
        !          3510:   Command->scsi_done = CompletionRoutine;
        !          3511:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3512:     {
        !          3513:       /*
        !          3514:        Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
        !          3515:        Subsystem should not attempt to queue more commands than can be placed
        !          3516:        in Outgoing Mailboxes, so there should always be one free.  In the
        !          3517:        unlikely event that there are none available, wait 1 second and try
        !          3518:        again.  If that fails, the Host Adapter is probably hung so signal an
        !          3519:        error as a Host Adapter Hard Reset should be initiated soon.
        !          3520:       */
        !          3521:       if (!BusLogic_WriteOutgoingMailbox(
        !          3522:             HostAdapter, BusLogic_MailboxStartCommand, CCB))
        !          3523:        {
        !          3524:          BusLogic_Warning("Unable to write Outgoing Mailbox - "
        !          3525:                           "Pausing for 1 second\n", HostAdapter);
        !          3526:          BusLogic_Delay(1);
        !          3527:          if (!BusLogic_WriteOutgoingMailbox(
        !          3528:                 HostAdapter, BusLogic_MailboxStartCommand, CCB))
        !          3529:            {
        !          3530:              BusLogic_Warning("Still unable to write Outgoing Mailbox - "
        !          3531:                               "Host Adapter Dead?\n", HostAdapter);
        !          3532:              BusLogic_DeallocateCCB(CCB);
        !          3533:              Command->result = DID_ERROR << 16;
        !          3534:              Command->scsi_done(Command);
        !          3535:            }
        !          3536:        }
        !          3537:     }
        !          3538:   else
        !          3539:     {
        !          3540:       /*
        !          3541:        Call the FlashPoint SCCB Manager to start execution of the CCB.
        !          3542:       */
        !          3543:       CCB->Status = BusLogic_CCB_Active;
        !          3544:       HostAdapter->ActiveCommands[TargetID]++;
        !          3545:       TargetStatistics[TargetID].CommandsAttempted++;
        !          3546:       FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
        !          3547:       /*
        !          3548:        The Command may have already completed and BusLogic_QueueCompletedCCB
        !          3549:        been called, or it may still be pending.
        !          3550:       */
        !          3551:       if (CCB->Status == BusLogic_CCB_Completed)
        !          3552:        BusLogic_ProcessCompletedCCBs(HostAdapter);
        !          3553:     }
        !          3554:   /*
        !          3555:     Release exclusive access to Host Adapter.
        !          3556:   */
        !          3557: Done:
        !          3558:   BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3559:   return 0;
        !          3560: }
        !          3561: 
        !          3562: 
        !          3563: /*
        !          3564:   BusLogic_AbortCommand aborts Command if possible.
        !          3565: */
        !          3566: 
        !          3567: int BusLogic_AbortCommand(SCSI_Command_T *Command)
        !          3568: {
        !          3569:   BusLogic_HostAdapter_T *HostAdapter =
        !          3570:     (BusLogic_HostAdapter_T *) Command->host->hostdata;
        !          3571:   int TargetID = Command->target;
        !          3572:   ProcessorFlags_T ProcessorFlags;
        !          3573:   BusLogic_CCB_T *CCB;
        !          3574:   int Result;
        !          3575:   BusLogic_IncrementErrorCounter(
        !          3576:     &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
        !          3577:   /*
        !          3578:     Acquire exclusive access to Host Adapter.
        !          3579:   */
        !          3580:   BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3581:   /*
        !          3582:     If this Command has already completed, then no Abort is necessary.
        !          3583:   */
        !          3584:   if (Command->serial_number != Command->serial_number_at_timeout)
        !          3585:     {
        !          3586:       BusLogic_Warning("Unable to Abort Command to Target %d - "
        !          3587:                       "Already Completed\n", HostAdapter, TargetID);
        !          3588:       Result = SCSI_ABORT_NOT_RUNNING;
        !          3589:       goto Done;
        !          3590:     }
        !          3591:   /*
        !          3592:     Attempt to find an Active CCB for this Command.  If no Active CCB for this
        !          3593:     Command is found, then no Abort is necessary.
        !          3594:   */
        !          3595:   for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3596:     if (CCB->Command == Command) break;
        !          3597:   if (CCB == NULL)
        !          3598:     {
        !          3599:       BusLogic_Warning("Unable to Abort Command to Target %d - "
        !          3600:                       "No CCB Found\n", HostAdapter, TargetID);
        !          3601:       Result = SCSI_ABORT_NOT_RUNNING;
        !          3602:       goto Done;
        !          3603:     }
        !          3604:   else if (CCB->Status == BusLogic_CCB_Completed)
        !          3605:     {
        !          3606:       BusLogic_Warning("Unable to Abort Command to Target %d - "
        !          3607:                       "CCB Completed\n", HostAdapter, TargetID);
        !          3608:       Result = SCSI_ABORT_NOT_RUNNING;
        !          3609:       goto Done;
        !          3610:     }
        !          3611:   else if (CCB->Status == BusLogic_CCB_Reset)
        !          3612:     {
        !          3613:       BusLogic_Warning("Unable to Abort Command to Target %d - "
        !          3614:                       "CCB Reset\n", HostAdapter, TargetID);
        !          3615:       Result = SCSI_ABORT_PENDING;
        !          3616:       goto Done;
        !          3617:     }
        !          3618:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3619:     {
        !          3620:       /*
        !          3621:        Attempt to Abort this CCB.  MultiMaster Firmware versions prior to 5.xx
        !          3622:        do not generate Abort Tag messages, but only generate the non-tagged
        !          3623:        Abort message.  Since non-tagged commands are not sent by the Host
        !          3624:        Adapter until the queue of outstanding tagged commands has completed,
        !          3625:        and the Abort message is treated as a non-tagged command, it is
        !          3626:        effectively impossible to abort commands when Tagged Queuing is active.
        !          3627:        Firmware version 5.xx does generate Abort Tag messages, so it is
        !          3628:        possible to abort commands when Tagged Queuing is active.
        !          3629:       */
        !          3630:       if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
        !          3631:          HostAdapter->FirmwareVersion[0] < '5')
        !          3632:        {
        !          3633:          BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
        !          3634:                           "Abort Tag Not Supported\n",
        !          3635:                           HostAdapter, CCB->SerialNumber, TargetID);
        !          3636:          Result = SCSI_ABORT_SNOOZE;
        !          3637:        }
        !          3638:       else if (BusLogic_WriteOutgoingMailbox(
        !          3639:                 HostAdapter, BusLogic_MailboxAbortCommand, CCB))
        !          3640:        {
        !          3641:          BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
        !          3642:                           HostAdapter, CCB->SerialNumber, TargetID);
        !          3643:          BusLogic_IncrementErrorCounter(
        !          3644:            &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
        !          3645:          Result = SCSI_ABORT_PENDING;
        !          3646:        }
        !          3647:       else
        !          3648:        {
        !          3649:          BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
        !          3650:                           "No Outgoing Mailboxes\n",
        !          3651:                            HostAdapter, CCB->SerialNumber, TargetID);
        !          3652:          Result = SCSI_ABORT_BUSY;
        !          3653:        }
        !          3654:     }
        !          3655:   else
        !          3656:     {
        !          3657:       /*
        !          3658:        Call the FlashPoint SCCB Manager to abort execution of the CCB.
        !          3659:       */
        !          3660:       BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
        !          3661:                       HostAdapter, CCB->SerialNumber, TargetID);
        !          3662:       BusLogic_IncrementErrorCounter(
        !          3663:        &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
        !          3664:       FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
        !          3665:       /*
        !          3666:        The Abort may have already been completed and
        !          3667:        BusLogic_QueueCompletedCCB been called, or it
        !          3668:        may still be pending.
        !          3669:       */
        !          3670:       Result = SCSI_ABORT_PENDING;
        !          3671:       if (CCB->Status == BusLogic_CCB_Completed)
        !          3672:        {
        !          3673:          BusLogic_ProcessCompletedCCBs(HostAdapter);
        !          3674:          Result = SCSI_ABORT_SUCCESS;
        !          3675:        }
        !          3676:     }
        !          3677:   /*
        !          3678:     Release exclusive access to Host Adapter.
        !          3679:   */
        !          3680: Done:
        !          3681:   BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3682:   return Result;
        !          3683: }
        !          3684: 
        !          3685: 
        !          3686: /*
        !          3687:   BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
        !          3688:   currently executing SCSI Commands as having been Reset.
        !          3689: */
        !          3690: 
        !          3691: static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
        !          3692:                                     SCSI_Command_T *Command,
        !          3693:                                     unsigned int ResetFlags)
        !          3694: {
        !          3695:   ProcessorFlags_T ProcessorFlags;
        !          3696:   BusLogic_CCB_T *CCB;
        !          3697:   int TargetID, Result;
        !          3698:   boolean HardReset;
        !          3699:   if (HostAdapter->HostAdapterExternalReset)
        !          3700:     {
        !          3701:       BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
        !          3702:       HardReset = false;
        !          3703:     }
        !          3704:   else if (HostAdapter->HostAdapterInternalError)
        !          3705:     {
        !          3706:       BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
        !          3707:       HardReset = true;
        !          3708:     }
        !          3709:   else
        !          3710:     {
        !          3711:       BusLogic_IncrementErrorCounter(
        !          3712:        &HostAdapter->TargetStatistics[Command->target]
        !          3713:                      .HostAdapterResetsRequested);
        !          3714:       HardReset = true;
        !          3715:     }
        !          3716:   /*
        !          3717:     Acquire exclusive access to Host Adapter.
        !          3718:   */
        !          3719:   BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3720:   /*
        !          3721:     If this is an Asynchronous Reset and this Command has already completed,
        !          3722:     then no Reset is necessary.
        !          3723:   */
        !          3724:   if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
        !          3725:     {
        !          3726:       TargetID = Command->target;
        !          3727:       if (Command->serial_number != Command->serial_number_at_timeout)
        !          3728:        {
        !          3729:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3730:                           "Already Completed or Reset\n",
        !          3731:                           HostAdapter, TargetID);
        !          3732:          Result = SCSI_RESET_NOT_RUNNING;
        !          3733:          goto Done;
        !          3734:       }
        !          3735:       for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3736:        if (CCB->Command == Command) break;
        !          3737:       if (CCB == NULL)
        !          3738:        {
        !          3739:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3740:                           "No CCB Found\n", HostAdapter, TargetID);
        !          3741:          Result = SCSI_RESET_NOT_RUNNING;
        !          3742:          goto Done;
        !          3743:        }
        !          3744:       else if (CCB->Status == BusLogic_CCB_Completed)
        !          3745:        {
        !          3746:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3747:                           "CCB Completed\n", HostAdapter, TargetID);
        !          3748:          Result = SCSI_RESET_NOT_RUNNING;
        !          3749:          goto Done;
        !          3750:        }
        !          3751:       else if (CCB->Status == BusLogic_CCB_Reset &&
        !          3752:               HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL)
        !          3753:        {
        !          3754:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3755:                           "Reset Pending\n", HostAdapter, TargetID);
        !          3756:          Result = SCSI_RESET_PENDING;
        !          3757:          goto Done;
        !          3758:        }
        !          3759:     }
        !          3760:   if (Command == NULL)
        !          3761:     {
        !          3762:       if (HostAdapter->HostAdapterInternalError)
        !          3763:        BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n",
        !          3764:                         HostAdapter, HostAdapter->FullModelName);
        !          3765:       else BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n",
        !          3766:                            HostAdapter, HostAdapter->FullModelName);
        !          3767:     }
        !          3768:   else
        !          3769:     {
        !          3770:       BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter,
        !          3771:                       HostAdapter->FullModelName, Command->target);
        !          3772:       BusLogic_IncrementErrorCounter(
        !          3773:        &HostAdapter->TargetStatistics[Command->target]
        !          3774:                      .HostAdapterResetsAttempted);
        !          3775:     }
        !          3776:   /*
        !          3777:     Attempt to Reset and Reinitialize the Host Adapter.
        !          3778:   */
        !          3779:   if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
        !          3780:        BusLogic_InitializeHostAdapter(HostAdapter)))
        !          3781:     {
        !          3782:       BusLogic_Error("Resetting %s Failed\n", HostAdapter,
        !          3783:                     HostAdapter->FullModelName);
        !          3784:       Result = SCSI_RESET_ERROR;
        !          3785:       goto Done;
        !          3786:     }
        !          3787:   if (Command != NULL)
        !          3788:     BusLogic_IncrementErrorCounter(
        !          3789:       &HostAdapter->TargetStatistics[Command->target]
        !          3790:                    .HostAdapterResetsCompleted);
        !          3791:   /*
        !          3792:     Mark all currently executing CCBs as having been Reset.
        !          3793:   */
        !          3794:   for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3795:     if (CCB->Status == BusLogic_CCB_Active)
        !          3796:       CCB->Status = BusLogic_CCB_Reset;
        !          3797:   /*
        !          3798:     Wait a few seconds between the Host Adapter Hard Reset which initiates
        !          3799:     a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
        !          3800:     confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
        !          3801:     Note that a timer interrupt may occur here, but all active CCBs have
        !          3802:     already been marked Reset and so a reentrant call will return Pending.
        !          3803:   */
        !          3804:   if (HardReset)
        !          3805:     BusLogic_Delay(HostAdapter->BusSettleTime);
        !          3806:   /*
        !          3807:     If this is a Synchronous Reset, perform completion processing for
        !          3808:     the Command being Reset.
        !          3809:   */
        !          3810:   if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
        !          3811:     {
        !          3812:       Command->result = DID_RESET << 16;
        !          3813:       Command->scsi_done(Command);
        !          3814:     }
        !          3815:   /*
        !          3816:     Perform completion processing for all CCBs marked as Reset.
        !          3817:   */
        !          3818:   for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3819:     if (CCB->Status == BusLogic_CCB_Reset)
        !          3820:       {
        !          3821:        Command = CCB->Command;
        !          3822:        BusLogic_DeallocateCCB(CCB);
        !          3823:        while (Command != NULL)
        !          3824:          {
        !          3825:            SCSI_Command_T *NextCommand = Command->reset_chain;
        !          3826:            Command->reset_chain = NULL;
        !          3827:            Command->result = DID_RESET << 16;
        !          3828:            Command->scsi_done(Command);
        !          3829:            Command = NextCommand;
        !          3830:          }
        !          3831:       }
        !          3832:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          3833:     {
        !          3834:       HostAdapter->LastResetAttempted[TargetID] = jiffies;
        !          3835:       HostAdapter->LastResetCompleted[TargetID] = jiffies;
        !          3836:     }
        !          3837:   Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
        !          3838:   /*
        !          3839:     Release exclusive access to Host Adapter.
        !          3840:   */
        !          3841: Done:
        !          3842:   BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3843:   return Result;
        !          3844: }
        !          3845: 
        !          3846: 
        !          3847: /*
        !          3848:   BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target
        !          3849:   Device associated with Command.
        !          3850: */
        !          3851: 
        !          3852: static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
        !          3853:                                       SCSI_Command_T *Command,
        !          3854:                                       unsigned int ResetFlags)
        !          3855: {
        !          3856:   int TargetID = Command->target;
        !          3857:   BusLogic_CCB_T *CCB, *XCCB;
        !          3858:   ProcessorFlags_T ProcessorFlags;
        !          3859:   int Result = -1;
        !          3860:   BusLogic_IncrementErrorCounter(
        !          3861:     &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
        !          3862:   /*
        !          3863:     Acquire exclusive access to Host Adapter.
        !          3864:   */
        !          3865:   BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          3866:   /*
        !          3867:     If this is an Asynchronous Reset and this Command has already completed,
        !          3868:     then no Reset is necessary.
        !          3869:   */
        !          3870:   if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
        !          3871:     {
        !          3872:       if (Command->serial_number != Command->serial_number_at_timeout)
        !          3873:        {
        !          3874:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3875:                           "Already Completed\n", HostAdapter, TargetID);
        !          3876:          Result = SCSI_RESET_NOT_RUNNING;
        !          3877:          goto Done;
        !          3878:        }
        !          3879:       for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
        !          3880:        if (CCB->Command == Command) break;
        !          3881:       if (CCB == NULL)
        !          3882:        {
        !          3883:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3884:                           "No CCB Found\n", HostAdapter, TargetID);
        !          3885:          Result = SCSI_RESET_NOT_RUNNING;
        !          3886:          goto Done;
        !          3887:        }
        !          3888:       else if (CCB->Status == BusLogic_CCB_Completed)
        !          3889:        {
        !          3890:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3891:                           "CCB Completed\n", HostAdapter, TargetID);
        !          3892:          Result = SCSI_RESET_NOT_RUNNING;
        !          3893:          goto Done;
        !          3894:        }
        !          3895:       else if (CCB->Status == BusLogic_CCB_Reset)
        !          3896:        {
        !          3897:          BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3898:                           "Reset Pending\n", HostAdapter, TargetID);
        !          3899:          Result = SCSI_RESET_PENDING;
        !          3900:          goto Done;
        !          3901:        }
        !          3902:       else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
        !          3903:        {
        !          3904:          BusLogic_Warning("Bus Device Reset already pending to Target %d\n",
        !          3905:                           HostAdapter, TargetID);
        !          3906:          goto Done;
        !          3907:        }
        !          3908:     }
        !          3909:   /*
        !          3910:     If this is a Synchronous Reset and a Bus Device Reset is already pending
        !          3911:     for this Target Device, do not send a second one.  Add this Command to
        !          3912:     the list of Commands for which completion processing must be performed
        !          3913:     when the Bus Device Reset CCB completes.
        !          3914:   */
        !          3915:   if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
        !          3916:     if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL)
        !          3917:       {
        !          3918:        Command->reset_chain = CCB->Command;
        !          3919:        CCB->Command = Command;
        !          3920:        BusLogic_Warning("Unable to Reset Command to Target %d - "
        !          3921:                         "Reset Pending\n", HostAdapter, TargetID);
        !          3922:        Result = SCSI_RESET_PENDING;
        !          3923:        goto Done;
        !          3924:       }
        !          3925:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3926:     {
        !          3927:       /*
        !          3928:        MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as
        !          3929:        a non-tagged command.  Since non-tagged commands are not sent by the
        !          3930:        Host Adapter until the queue of outstanding tagged commands has
        !          3931:        completed, it is effectively impossible to send a Bus Device Reset
        !          3932:        while there are tagged commands outstanding.  Therefore, in that case a
        !          3933:        full Host Adapter Hard Reset and SCSI Bus Reset must be done.
        !          3934:       */
        !          3935:       if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
        !          3936:          HostAdapter->ActiveCommands[TargetID] > 0 &&
        !          3937:          HostAdapter->FirmwareVersion[0] < '5')
        !          3938:        goto Done;
        !          3939:     }
        !          3940:   /*
        !          3941:     Allocate a CCB from the Host Adapter's free list.  In the unlikely event
        !          3942:     that there are none available and memory allocation fails, attempt a full
        !          3943:     Host Adapter Hard Reset and SCSI Bus Reset.
        !          3944:   */
        !          3945:   CCB = BusLogic_AllocateCCB(HostAdapter);
        !          3946:   if (CCB == NULL) goto Done;
        !          3947:   BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n",
        !          3948:                   HostAdapter, CCB->SerialNumber, TargetID);
        !          3949:   CCB->Opcode = BusLogic_BusDeviceReset;
        !          3950:   CCB->TargetID = TargetID;
        !          3951:   /*
        !          3952:     For Synchronous Resets, arrange for the interrupt handler to perform
        !          3953:     completion processing for the Command being Reset.
        !          3954:   */
        !          3955:   if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
        !          3956:     {
        !          3957:       Command->reset_chain = NULL;
        !          3958:       CCB->Command = Command;
        !          3959:     }
        !          3960:   if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
        !          3961:     {
        !          3962:       /*
        !          3963:        Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
        !          3964:        If sending a Bus Device Reset is impossible, attempt a full Host
        !          3965:        Adapter Hard Reset and SCSI Bus Reset.
        !          3966:       */
        !          3967:       if (!(BusLogic_WriteOutgoingMailbox(
        !          3968:              HostAdapter, BusLogic_MailboxStartCommand, CCB)))
        !          3969:        {
        !          3970:          BusLogic_Warning("Unable to write Outgoing Mailbox for "
        !          3971:                           "Bus Device Reset\n", HostAdapter);
        !          3972:          BusLogic_DeallocateCCB(CCB);
        !          3973:          goto Done;
        !          3974:        }
        !          3975:     }
        !          3976:   else
        !          3977:     {
        !          3978:       /*
        !          3979:        Call the FlashPoint SCCB Manager to start execution of the CCB.
        !          3980:       */
        !          3981:       CCB->Status = BusLogic_CCB_Active;
        !          3982:       HostAdapter->ActiveCommands[TargetID]++;
        !          3983:       FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
        !          3984:     }
        !          3985:   /*
        !          3986:     If there is a currently executing CCB in the Host Adapter for this Command
        !          3987:     (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
        !          3988:     made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
        !          3989:     If there is no active CCB for this Command (i.e. this is a Synchronous
        !          3990:     Reset), then the Bus Device Reset CCB's Command field will have been set
        !          3991:     to the Command so that the interrupt for the completion of the Bus Device
        !          3992:     Reset can call the Completion Routine for the Command.  On successful
        !          3993:     execution of a Bus Device Reset, older firmware versions did return the
        !          3994:     pending CCBs with the appropriate completion code, but more recent firmware
        !          3995:     versions only return the Bus Device Reset CCB itself.  This driver handles
        !          3996:     both cases by marking all the currently executing CCBs to this Target
        !          3997:     Device as Reset.  When the Bus Device Reset CCB is processed by the
        !          3998:     interrupt handler, any remaining CCBs marked as Reset will have completion
        !          3999:     processing performed.
        !          4000:   */
        !          4001:   BusLogic_IncrementErrorCounter(
        !          4002:     &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
        !          4003:   HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
        !          4004:   HostAdapter->LastResetAttempted[TargetID] = jiffies;
        !          4005:   for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll)
        !          4006:     if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID)
        !          4007:       XCCB->Status = BusLogic_CCB_Reset;
        !          4008:   /*
        !          4009:     FlashPoint Host Adapters may have already completed the Bus Device
        !          4010:     Reset and BusLogic_QueueCompletedCCB been called, or it may still be
        !          4011:     pending.
        !          4012:   */
        !          4013:   Result = SCSI_RESET_PENDING;
        !          4014:   if (BusLogic_FlashPointHostAdapterP(HostAdapter))
        !          4015:     if (CCB->Status == BusLogic_CCB_Completed)
        !          4016:       {
        !          4017:        BusLogic_ProcessCompletedCCBs(HostAdapter);
        !          4018:        Result = SCSI_RESET_SUCCESS;
        !          4019:       }
        !          4020:   /*
        !          4021:     If a Bus Device Reset was not possible for some reason, force a full
        !          4022:     Host Adapter Hard Reset and SCSI Bus Reset.
        !          4023:   */
        !          4024: Done:
        !          4025:   if (Result < 0)
        !          4026:     Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
        !          4027:   /*
        !          4028:     Release exclusive access to Host Adapter.
        !          4029:   */
        !          4030:   BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
        !          4031:   return Result;
        !          4032: }
        !          4033: 
        !          4034: 
        !          4035: /*
        !          4036:   BusLogic_ResetCommand takes appropriate action to reset Command.
        !          4037: */
        !          4038: 
        !          4039: int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags)
        !          4040: {
        !          4041:   BusLogic_HostAdapter_T *HostAdapter =
        !          4042:     (BusLogic_HostAdapter_T *) Command->host->hostdata;
        !          4043:   int TargetID = Command->target;
        !          4044:   BusLogic_ErrorRecoveryStrategy_T
        !          4045:     ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID];
        !          4046:   /*
        !          4047:     Disable Tagged Queuing if it is active for this Target Device and if
        !          4048:     it has been less than 10 minutes since the last reset occurred, or since
        !          4049:     the system was initialized if no prior resets have occurred.
        !          4050:   */
        !          4051:   if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
        !          4052:       jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ)
        !          4053:     {
        !          4054:       HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
        !          4055:       HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
        !          4056:       BusLogic_Warning("Tagged Queuing now disabled for Target %d\n",
        !          4057:                       HostAdapter, TargetID);
        !          4058:     }
        !          4059:   switch (ErrorRecoveryStrategy)
        !          4060:     {
        !          4061:     case BusLogic_ErrorRecovery_Default:
        !          4062:       if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET)
        !          4063:        return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
        !          4064:       else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
        !          4065:        return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
        !          4066:       /* Fall through to Bus Device Reset case. */
        !          4067:     case BusLogic_ErrorRecovery_BusDeviceReset:
        !          4068:       /*
        !          4069:        The Bus Device Reset Error Recovery Strategy only graduates to a Hard
        !          4070:        Reset when no commands have completed successfully since the last Bus
        !          4071:        Device Reset and it has been at least 100 milliseconds.  This prevents
        !          4072:        a sequence of commands that all timeout together from immediately
        !          4073:        forcing a Hard Reset before the Bus Device Reset has had a chance to
        !          4074:        clear the error condition.
        !          4075:       */
        !          4076:       if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag ||
        !          4077:          jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10)
        !          4078:        {
        !          4079:          HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
        !          4080:          return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags);
        !          4081:        }
        !          4082:       /* Fall through to Hard Reset case. */
        !          4083:     case BusLogic_ErrorRecovery_HardReset:
        !          4084:       return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
        !          4085:     case BusLogic_ErrorRecovery_None:
        !          4086:       BusLogic_Warning("Error Recovery for Target %d Suppressed\n",
        !          4087:                       HostAdapter, TargetID);
        !          4088:       break;
        !          4089:     }
        !          4090:   return SCSI_RESET_PUNT;
        !          4091: }
        !          4092: 
        !          4093: 
        !          4094: /*
        !          4095:   BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
        !          4096:   Parameters for Disk.  The default disk geometry is 64 heads, 32 sectors, and
        !          4097:   the appropriate number of cylinders so as not to exceed drive capacity.  In
        !          4098:   order for disks equal to or larger than 1 GB to be addressable by the BIOS
        !          4099:   without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
        !          4100:   may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
        !          4101:   series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
        !          4102:   series MultiMaster Host Adapters.  With Extended Translation enabled, drives
        !          4103:   between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
        !          4104:   heads and 32 sectors, and drives above 2 GB inclusive are given a disk
        !          4105:   geometry of 255 heads and 63 sectors.  However, if the BIOS detects that the
        !          4106:   Extended Translation setting does not match the geometry in the partition
        !          4107:   table, then the translation inferred from the partition table will be used by
        !          4108:   the BIOS, and a warning may be displayed.
        !          4109: */
        !          4110: 
        !          4111: int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
        !          4112:                                int *Parameters)
        !          4113: {
        !          4114:   BusLogic_HostAdapter_T *HostAdapter =
        !          4115:     (BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
        !          4116:   BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
        !          4117:   struct buffer_head *BufferHead;
        !          4118:   if (HostAdapter->ExtendedTranslationEnabled &&
        !          4119:       Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
        !          4120:     {
        !          4121:       if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
        !          4122:        {
        !          4123:          DiskParameters->Heads = 255;
        !          4124:          DiskParameters->Sectors = 63;
        !          4125:        }
        !          4126:       else
        !          4127:        {
        !          4128:          DiskParameters->Heads = 128;
        !          4129:          DiskParameters->Sectors = 32;
        !          4130:        }
        !          4131:     }
        !          4132:   else
        !          4133:     {
        !          4134:       DiskParameters->Heads = 64;
        !          4135:       DiskParameters->Sectors = 32;
        !          4136:     }
        !          4137:   DiskParameters->Cylinders =
        !          4138:     Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
        !          4139:   /*
        !          4140:     Attempt to read the first 1024 bytes from the disk device.
        !          4141:   */
        !          4142:   BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, 1024);
        !          4143:   if (BufferHead == NULL) return 0;
        !          4144:   /*
        !          4145:     If the boot sector partition table flag is valid, search for a partition
        !          4146:     table entry whose end_head matches one of the standard BusLogic geometry
        !          4147:     translations (64/32, 128/32, or 255/63).
        !          4148:   */
        !          4149:   if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55)
        !          4150:     {
        !          4151:       PartitionTable_T *FirstPartitionEntry =
        !          4152:        (PartitionTable_T *) (BufferHead->b_data + 0x1BE);
        !          4153:       PartitionTable_T *PartitionEntry = FirstPartitionEntry;
        !          4154:       int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
        !          4155:       unsigned char PartitionEntryEndHead, PartitionEntryEndSector;
        !          4156:       for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
        !          4157:        {
        !          4158:          PartitionEntryEndHead = PartitionEntry->end_head;
        !          4159:          PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
        !          4160:          if (PartitionEntryEndHead == 64-1)
        !          4161:            {
        !          4162:              DiskParameters->Heads = 64;
        !          4163:              DiskParameters->Sectors = 32;
        !          4164:              break;
        !          4165:            }
        !          4166:          else if (PartitionEntryEndHead == 128-1)
        !          4167:            {
        !          4168:              DiskParameters->Heads = 128;
        !          4169:              DiskParameters->Sectors = 32;
        !          4170:              break;
        !          4171:            }
        !          4172:          else if (PartitionEntryEndHead == 255-1)
        !          4173:            {
        !          4174:              DiskParameters->Heads = 255;
        !          4175:              DiskParameters->Sectors = 63;
        !          4176:              break;
        !          4177:            }
        !          4178:          PartitionEntry++;
        !          4179:        }
        !          4180:       if (PartitionNumber == 4)
        !          4181:        {
        !          4182:          PartitionEntryEndHead = FirstPartitionEntry->end_head;
        !          4183:          PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
        !          4184:        }
        !          4185:       DiskParameters->Cylinders =
        !          4186:        Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
        !          4187:       if (PartitionNumber < 4 &&
        !          4188:          PartitionEntryEndSector == DiskParameters->Sectors)
        !          4189:        {
        !          4190:          if (DiskParameters->Cylinders != SavedCylinders)
        !          4191:            BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n",
        !          4192:                             HostAdapter,
        !          4193:                             DiskParameters->Heads, DiskParameters->Sectors);
        !          4194:        }
        !          4195:       else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
        !          4196:        {
        !          4197:          BusLogic_Warning("Warning: Partition Table appears to "
        !          4198:                           "have Geometry %d/%d which is\n", HostAdapter,
        !          4199:                           PartitionEntryEndHead + 1,
        !          4200:                           PartitionEntryEndSector);
        !          4201:          BusLogic_Warning("not compatible with current BusLogic "
        !          4202:                           "Host Adapter Geometry %d/%d\n", HostAdapter,
        !          4203:                           DiskParameters->Heads, DiskParameters->Sectors);
        !          4204:        }
        !          4205:     }
        !          4206:   brelse(BufferHead);
        !          4207:   return 0;
        !          4208: }
        !          4209: 
        !          4210: 
        !          4211: /*
        !          4212:   BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
        !          4213: */
        !          4214: 
        !          4215: int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer,
        !          4216:                               off_t Offset, int BytesAvailable,
        !          4217:                               int HostNumber, int WriteFlag)
        !          4218: {
        !          4219:   BusLogic_HostAdapter_T *HostAdapter;
        !          4220:   BusLogic_TargetStatistics_T *TargetStatistics;
        !          4221:   int TargetID, Length;
        !          4222:   char *Buffer;
        !          4223:   for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
        !          4224:        HostAdapter != NULL;
        !          4225:        HostAdapter = HostAdapter->Next)
        !          4226:     if (HostAdapter->HostNumber == HostNumber) break;
        !          4227:   if (HostAdapter == NULL)
        !          4228:     {
        !          4229:       BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n",
        !          4230:                     NULL, HostNumber);
        !          4231:       return 0;
        !          4232:     }
        !          4233:   TargetStatistics = HostAdapter->TargetStatistics;
        !          4234:   if (WriteFlag)
        !          4235:     {
        !          4236:       HostAdapter->ExternalHostAdapterResets = 0;
        !          4237:       HostAdapter->HostAdapterInternalErrors = 0;
        !          4238:       memset(TargetStatistics, 0,
        !          4239:             BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T));
        !          4240:       return 0;
        !          4241:     }
        !          4242:   Buffer = HostAdapter->MessageBuffer;
        !          4243:   Length = HostAdapter->MessageBufferLength;
        !          4244:   Length += sprintf(&Buffer[Length], "\n\
        !          4245: Current Driver Queue Depth:    %d\n\
        !          4246: Currently Allocated CCBs:      %d\n",
        !          4247:                    HostAdapter->DriverQueueDepth,
        !          4248:                    HostAdapter->AllocatedCCBs);
        !          4249:   Length += sprintf(&Buffer[Length], "\n\n\
        !          4250:                           DATA TRANSFER STATISTICS\n\
        !          4251: \n\
        !          4252: Target Tagged Queuing  Queue Depth  Active  Attempted  Completed\n\
        !          4253: ====== ==============  ===========  ======  =========  =========\n");
        !          4254:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          4255:     {
        !          4256:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          4257:       if (!TargetFlags->TargetExists) continue;
        !          4258:       Length +=
        !          4259:        sprintf(&Buffer[Length], "  %2d %s", TargetID,
        !          4260:                (TargetFlags->TaggedQueuingSupported
        !          4261:                 ? (TargetFlags->TaggedQueuingActive
        !          4262:                    ? "    Active"
        !          4263:                    : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
        !          4264:                       ? "  Permitted" : "   Disabled"))
        !          4265:                 : "Not Supported"));
        !          4266:       Length += sprintf(&Buffer[Length],
        !          4267:                        "           %3d       %3u    %9u        %9u\n",
        !          4268:                        HostAdapter->QueueDepth[TargetID],
        !          4269:                        HostAdapter->ActiveCommands[TargetID],
        !          4270:                        TargetStatistics[TargetID].CommandsAttempted,
        !          4271:                        TargetStatistics[TargetID].CommandsCompleted);
        !          4272:     }
        !          4273:   Length += sprintf(&Buffer[Length], "\n\
        !          4274: Target  Read Commands  Write Commands   Total Bytes Read    Total Bytes Written\n\
        !          4275: ======  =============  ==============  ===================  ===================\n");
        !          4276:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          4277:     {
        !          4278:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          4279:       if (!TargetFlags->TargetExists) continue;
        !          4280:       Length +=
        !          4281:        sprintf(&Buffer[Length], "  %2d   %9u    %9u", TargetID,
        !          4282:                TargetStatistics[TargetID].ReadCommands,
        !          4283:                TargetStatistics[TargetID].WriteCommands);
        !          4284:       if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
        !          4285:        Length +=
        !          4286:          sprintf(&Buffer[Length], "     %9u%09u",
        !          4287:                  TargetStatistics[TargetID].TotalBytesRead.Billions,
        !          4288:                  TargetStatistics[TargetID].TotalBytesRead.Units);
        !          4289:       else
        !          4290:        Length +=
        !          4291:          sprintf(&Buffer[Length], "            %9u",
        !          4292:                  TargetStatistics[TargetID].TotalBytesRead.Units);
        !          4293:       if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
        !          4294:        Length +=
        !          4295:          sprintf(&Buffer[Length], "   %9u%09u\n",
        !          4296:                  TargetStatistics[TargetID].TotalBytesWritten.Billions,
        !          4297:                  TargetStatistics[TargetID].TotalBytesWritten.Units);
        !          4298:       else
        !          4299:        Length +=
        !          4300:          sprintf(&Buffer[Length], "         %9u\n",
        !          4301:                  TargetStatistics[TargetID].TotalBytesWritten.Units);
        !          4302:     }
        !          4303:   Length += sprintf(&Buffer[Length], "\n\
        !          4304: Target  Command    0-1KB      1-2KB      2-4KB      4-8KB     8-16KB\n\
        !          4305: ======  =======  =========  =========  =========  =========  =========\n");
        !          4306:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          4307:     {
        !          4308:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          4309:       if (!TargetFlags->TargetExists) continue;
        !          4310:       Length +=
        !          4311:        sprintf(&Buffer[Length],
        !          4312:                "  %2d   Read    %9u  %9u  %9u  %9u  %9u\n", TargetID,
        !          4313:                TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
        !          4314:                TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
        !          4315:                TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
        !          4316:                TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
        !          4317:                TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
        !          4318:       Length +=
        !          4319:        sprintf(&Buffer[Length],
        !          4320:                "  %2d   Write   %9u  %9u  %9u  %9u  %9u\n", TargetID,
        !          4321:                TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
        !          4322:                TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
        !          4323:                TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
        !          4324:                TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
        !          4325:                TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
        !          4326:     }
        !          4327:   Length += sprintf(&Buffer[Length], "\n\
        !          4328: Target  Command   16-32KB    32-64KB   64-128KB   128-256KB   256KB+\n\
        !          4329: ======  =======  =========  =========  =========  =========  =========\n");
        !          4330:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          4331:     {
        !          4332:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          4333:       if (!TargetFlags->TargetExists) continue;
        !          4334:       Length +=
        !          4335:        sprintf(&Buffer[Length],
        !          4336:                "  %2d   Read    %9u  %9u  %9u  %9u  %9u\n", TargetID,
        !          4337:                TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
        !          4338:                TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
        !          4339:                TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
        !          4340:                TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
        !          4341:                TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
        !          4342:       Length +=
        !          4343:        sprintf(&Buffer[Length],
        !          4344:                "  %2d   Write   %9u  %9u  %9u  %9u  %9u\n", TargetID,
        !          4345:                TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
        !          4346:                TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
        !          4347:                TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
        !          4348:                TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
        !          4349:                TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
        !          4350:     }
        !          4351:   Length += sprintf(&Buffer[Length], "\n\n\
        !          4352:                           ERROR RECOVERY STATISTICS\n\
        !          4353: \n\
        !          4354:          Command Aborts      Bus Device Resets   Host Adapter Resets\n\
        !          4355: Target Requested Completed  Requested Completed  Requested Completed\n\
        !          4356:   ID   \\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////\n\
        !          4357: ======  ===== ===== =====    ===== ===== =====    ===== ===== =====\n");
        !          4358:   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
        !          4359:     {
        !          4360:       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
        !          4361:       if (!TargetFlags->TargetExists) continue;
        !          4362:       Length +=
        !          4363:        sprintf(&Buffer[Length], "\
        !          4364:   %2d   %5d %5d %5d    %5d %5d %5d        %5d %5d %5d\n", TargetID,
        !          4365:                TargetStatistics[TargetID].CommandAbortsRequested,
        !          4366:                TargetStatistics[TargetID].CommandAbortsAttempted,
        !          4367:                TargetStatistics[TargetID].CommandAbortsCompleted,
        !          4368:                TargetStatistics[TargetID].BusDeviceResetsRequested,
        !          4369:                TargetStatistics[TargetID].BusDeviceResetsAttempted,
        !          4370:                TargetStatistics[TargetID].BusDeviceResetsCompleted,
        !          4371:                TargetStatistics[TargetID].HostAdapterResetsRequested,
        !          4372:                TargetStatistics[TargetID].HostAdapterResetsAttempted,
        !          4373:                TargetStatistics[TargetID].HostAdapterResetsCompleted);
        !          4374:     }
        !          4375:   Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n",
        !          4376:                    HostAdapter->ExternalHostAdapterResets);
        !          4377:   Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n",
        !          4378:                    HostAdapter->HostAdapterInternalErrors);
        !          4379:   if (Length >= BusLogic_MessageBufferSize)
        !          4380:     BusLogic_Error("Message Buffer length %d exceeds size %d\n",
        !          4381:                   HostAdapter, Length, BusLogic_MessageBufferSize);
        !          4382:   if ((Length -= Offset) <= 0) return 0;
        !          4383:   if (Length >= BytesAvailable) Length = BytesAvailable;
        !          4384:   *StartPointer = &HostAdapter->MessageBuffer[Offset];
        !          4385:   return Length;
        !          4386: }
        !          4387: 
        !          4388: 
        !          4389: /*
        !          4390:   BusLogic_Message prints Driver Messages.
        !          4391: */
        !          4392: 
        !          4393: static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel,
        !          4394:                             char *Format,
        !          4395:                             BusLogic_HostAdapter_T *HostAdapter,
        !          4396:                             ...)
        !          4397: {
        !          4398:   static char Buffer[BusLogic_LineBufferSize];
        !          4399:   static boolean BeginningOfLine = true;
        !          4400:   va_list Arguments;
        !          4401:   int Length = 0;
        !          4402:   va_start(Arguments, HostAdapter);
        !          4403:   Length = vsprintf(Buffer, Format, Arguments);
        !          4404:   va_end(Arguments);
        !          4405:   if (MessageLevel == BusLogic_AnnounceLevel)
        !          4406:     {
        !          4407:       static int AnnouncementLines = 0;
        !          4408:       strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
        !          4409:             Buffer);
        !          4410:       HostAdapter->MessageBufferLength += Length;
        !          4411:       if (++AnnouncementLines <= 2)
        !          4412:        printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
        !          4413:     }
        !          4414:   else if (MessageLevel == BusLogic_InfoLevel)
        !          4415:     {
        !          4416:       strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
        !          4417:             Buffer);
        !          4418:       HostAdapter->MessageBufferLength += Length;
        !          4419:       if (BeginningOfLine)
        !          4420:        {
        !          4421:          if (Buffer[0] != '\n' || Length > 1)
        !          4422:            printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
        !          4423:                   HostAdapter->HostNumber, Buffer);
        !          4424:        }
        !          4425:       else printk("%s", Buffer);
        !          4426:     }
        !          4427:   else
        !          4428:     {
        !          4429:       if (BeginningOfLine)
        !          4430:        {
        !          4431:          if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
        !          4432:            printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
        !          4433:                   HostAdapter->HostNumber, Buffer);
        !          4434:          else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
        !          4435:        }
        !          4436:       else printk("%s", Buffer);
        !          4437:     }
        !          4438:   BeginningOfLine = (Buffer[Length-1] == '\n');
        !          4439: }
        !          4440: 
        !          4441: 
        !          4442: /*
        !          4443:   BusLogic_ParseKeyword parses an individual option keyword.  It returns true
        !          4444:   and updates the pointer if the keyword is recognized and false otherwise.
        !          4445: */
        !          4446: 
        !          4447: static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
        !          4448: {
        !          4449:   char *Pointer = *StringPointer;
        !          4450:   while (*Keyword != '\0')
        !          4451:     {
        !          4452:       char StringChar = *Pointer++;
        !          4453:       char KeywordChar = *Keyword++;
        !          4454:       if (StringChar >= 'A' && StringChar <= 'Z')
        !          4455:        StringChar += 'a' - 'Z';
        !          4456:       if (KeywordChar >= 'A' && KeywordChar <= 'Z')
        !          4457:        KeywordChar += 'a' - 'Z';
        !          4458:       if (StringChar != KeywordChar) return false;
        !          4459:     }
        !          4460:   *StringPointer = Pointer;
        !          4461:   return true;
        !          4462: }
        !          4463: 
        !          4464: 
        !          4465: /*
        !          4466:   BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
        !          4467:   specifications.
        !          4468: 
        !          4469:   BusLogic Driver Options may be specified either via the Linux Kernel Command
        !          4470:   Line or via the Loadable Kernel Module Installation Facility.  Driver Options
        !          4471:   for multiple host adapters may be specified either by separating the option
        !          4472:   strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
        !          4473:   command line.  Individual option specifications for a single host adapter are
        !          4474:   separated by commas.  The Probing and Debugging Options apply to all host
        !          4475:   adapters whereas the remaining options apply individually only to the
        !          4476:   selected host adapter.
        !          4477: 
        !          4478:   The BusLogic Driver Probing Options comprise the following:
        !          4479: 
        !          4480:   IO:<integer>
        !          4481: 
        !          4482:     The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
        !          4483:     MultiMaster Host Adapter.  If neither "IO:" nor "NoProbeISA" options are
        !          4484:     specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
        !          4485:     will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134).  Multiple
        !          4486:     "IO:" options may be specified to precisely determine the I/O Addresses to
        !          4487:     be probed, but the probe order will always follow the standard list.
        !          4488: 
        !          4489:   NoProbe
        !          4490: 
        !          4491:     The "NoProbe" option disables all probing and therefore no BusLogic Host
        !          4492:     Adapters will be detected.
        !          4493: 
        !          4494:   NoProbeISA
        !          4495: 
        !          4496:     The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
        !          4497:     Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
        !          4498:     will be detected.
        !          4499: 
        !          4500:   NoProbePCI
        !          4501: 
        !          4502:     The "NoProbePCI" options disables the interrogation of PCI Configuration
        !          4503:     Space and therefore only ISA Multimaster Host Adapters will be detected, as
        !          4504:     well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
        !          4505:     Port set to "Primary" or "Alternate".
        !          4506: 
        !          4507:   NoSortPCI
        !          4508: 
        !          4509:     The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
        !          4510:     enumerated in the order provided by the PCI BIOS, ignoring any setting of
        !          4511:     the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
        !          4512: 
        !          4513:   MultiMasterFirst
        !          4514: 
        !          4515:     The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
        !          4516:     before FlashPoint Host Adapters.  By default, if both FlashPoint and PCI
        !          4517:     MultiMaster Host Adapters are present, this driver will probe for
        !          4518:     FlashPoint Host Adapters first unless the BIOS primary disk is controlled
        !          4519:     by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
        !          4520:     Adapters will be probed first.
        !          4521: 
        !          4522:   FlashPointFirst
        !          4523: 
        !          4524:     The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
        !          4525:     before MultiMaster Host Adapters.
        !          4526: 
        !          4527:   The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
        !          4528:   the Queue Depth and whether Tagged Queuing is permitted for each Target
        !          4529:   Device (assuming that the Target Device supports Tagged Queuing).  The Queue
        !          4530:   Depth is the number of SCSI Commands that are allowed to be concurrently
        !          4531:   presented for execution (either to the Host Adapter or Target Device).  Note
        !          4532:   that explicitly enabling Tagged Queuing may lead to problems; the option to
        !          4533:   enable or disable Tagged Queuing is provided primarily to allow disabling
        !          4534:   Tagged Queuing on Target Devices that do not implement it correctly.  The
        !          4535:   following options are available:
        !          4536: 
        !          4537:   QueueDepth:<integer>
        !          4538: 
        !          4539:     The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
        !          4540:     Target Devices that support Tagged Queuing, as well as the maximum Queue
        !          4541:     Depth for devices that do not support Tagged Queuing.  If no Queue Depth
        !          4542:     option is provided, the Queue Depth will be determined automatically based
        !          4543:     on the Host Adapter's Total Queue Depth and the number, type, speed, and
        !          4544:     capabilities of the detected Target Devices.  For Host Adapters that
        !          4545:     require ISA Bounce Buffers, the Queue Depth is automatically set by default
        !          4546:     to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
        !          4547:     excessive preallocation of DMA Bounce Buffer memory.  Target Devices that
        !          4548:     do not support Tagged Queuing always have their Queue Depth set to
        !          4549:     BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
        !          4550:     lower Queue Depth option is provided.  A Queue Depth of 1 automatically
        !          4551:     disables Tagged Queuing.
        !          4552: 
        !          4553:   QueueDepth:[<integer>,<integer>...]
        !          4554: 
        !          4555:     The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
        !          4556:     individually for each Target Device.  If an <integer> is omitted, the
        !          4557:     associated Target Device will have its Queue Depth selected automatically.
        !          4558: 
        !          4559:   TaggedQueuing:Default
        !          4560: 
        !          4561:     The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
        !          4562:     based on the firmware version of the BusLogic Host Adapter and based on
        !          4563:     whether the Queue Depth allows queuing multiple commands.
        !          4564: 
        !          4565:   TaggedQueuing:Enable
        !          4566: 
        !          4567:     The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
        !          4568:     all Target Devices on this Host Adapter, overriding any limitation that
        !          4569:     would otherwise be imposed based on the Host Adapter firmware version.
        !          4570: 
        !          4571:   TaggedQueuing:Disable
        !          4572: 
        !          4573:     The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
        !          4574:     for all Target Devices on this Host Adapter.
        !          4575: 
        !          4576:   TaggedQueuing:<Target-Spec>
        !          4577: 
        !          4578:     The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
        !          4579:     Tagged Queuing individually for each Target Device.  <Target-Spec> is a
        !          4580:     sequence of "Y", "N", and "X" characters.  "Y" enables Tagged Queuing, "N"
        !          4581:     disables Tagged Queuing, and "X" accepts the default based on the firmware
        !          4582:     version.  The first character refers to Target Device 0, the second to
        !          4583:     Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
        !          4584:     does not cover all the Target Devices, unspecified characters are assumed
        !          4585:     to be "X".
        !          4586: 
        !          4587:   The BusLogic Driver Error Recovery Option allows for explicitly specifying
        !          4588:   the Error Recovery action to be performed when BusLogic_ResetCommand is
        !          4589:   called due to a SCSI Command failing to complete successfully.  The following
        !          4590:   options are available:
        !          4591: 
        !          4592:   ErrorRecovery:Default
        !          4593: 
        !          4594:     The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
        !          4595:     Reset and Bus Device Reset options based on the recommendation of the SCSI
        !          4596:     Subsystem.
        !          4597: 
        !          4598:   ErrorRecovery:HardReset
        !          4599: 
        !          4600:     The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
        !          4601:     Adapter Hard Reset which also causes a SCSI Bus Reset.
        !          4602: 
        !          4603:   ErrorRecovery:BusDeviceReset
        !          4604: 
        !          4605:     The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
        !          4606:     a Bus Device Reset message to the individual Target Device causing the
        !          4607:     error.  If Error Recovery is again initiated for this Target Device and no
        !          4608:     SCSI Command to this Target Device has completed successfully since the Bus
        !          4609:     Device Reset message was sent, then a Hard Reset will be attempted.
        !          4610: 
        !          4611:   ErrorRecovery:None
        !          4612: 
        !          4613:     The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
        !          4614:     This option should only be selected if a SCSI Bus Reset or Bus Device Reset
        !          4615:     will cause the Target Device or a critical operation to suffer a complete
        !          4616:     and unrecoverable failure.
        !          4617: 
        !          4618:   ErrorRecovery:<Target-Spec>
        !          4619: 
        !          4620:     The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
        !          4621:     Error Recovery individually for each Target Device.  <Target-Spec> is a
        !          4622:     sequence of "D", "H", "B", and "N" characters.  "D" selects Default, "H"
        !          4623:     selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
        !          4624:     The first character refers to Target Device 0, the second to Target Device
        !          4625:     1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
        !          4626:     cover all the possible Target Devices, unspecified characters are assumed
        !          4627:     to be "D".
        !          4628: 
        !          4629:   The BusLogic Driver Miscellaneous Options comprise the following:
        !          4630: 
        !          4631:   BusSettleTime:<seconds>
        !          4632: 
        !          4633:     The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
        !          4634:     seconds.  The Bus Settle Time is the amount of time to wait between a Host
        !          4635:     Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
        !          4636:     Commands.  If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
        !          4637: 
        !          4638:   InhibitTargetInquiry
        !          4639: 
        !          4640:     The "InhibitTargetInquiry" option inhibits the execution of an Inquire
        !          4641:     Target Devices or Inquire Installed Devices command on MultiMaster Host
        !          4642:     Adapters.  This may be necessary with some older Target Devices that do not
        !          4643:     respond correctly when Logical Units above 0 are addressed.
        !          4644: 
        !          4645:   The BusLogic Driver Debugging Options comprise the following:
        !          4646: 
        !          4647:   TraceProbe
        !          4648: 
        !          4649:     The "TraceProbe" option enables tracing of Host Adapter Probing.
        !          4650: 
        !          4651:   TraceHardwareReset
        !          4652: 
        !          4653:     The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
        !          4654:     Reset.
        !          4655: 
        !          4656:   TraceConfiguration
        !          4657: 
        !          4658:     The "TraceConfiguration" option enables tracing of Host Adapter
        !          4659:     Configuration.
        !          4660: 
        !          4661:   TraceErrors
        !          4662: 
        !          4663:     The "TraceErrors" option enables tracing of SCSI Commands that return an
        !          4664:     error from the Target Device.  The CDB and Sense Data will be printed for
        !          4665:     each SCSI Command that fails.
        !          4666: 
        !          4667:   Debug
        !          4668: 
        !          4669:     The "Debug" option enables all debugging options.
        !          4670: 
        !          4671:   The following examples demonstrate setting the Queue Depth for Target Devices
        !          4672:   1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
        !          4673:   Devices on the second host adapter to 31, and the Bus Settle Time on the
        !          4674:   second host adapter to 30 seconds.
        !          4675: 
        !          4676:   Linux Kernel Command Line:
        !          4677: 
        !          4678:     linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
        !          4679: 
        !          4680:   LILO Linux Boot Loader (in /etc/lilo.conf):
        !          4681: 
        !          4682:     append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
        !          4683: 
        !          4684:   INSMOD Loadable Kernel Module Installation Facility:
        !          4685: 
        !          4686:     insmod BusLogic.o \
        !          4687:        'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
        !          4688: 
        !          4689:   NOTE: Module Utilities 2.1.71 or later is required for correct parsing
        !          4690:        of driver options containing commas.
        !          4691: 
        !          4692: */
        !          4693: 
        !          4694: static void BusLogic_ParseDriverOptions(char *OptionsString)
        !          4695: {
        !          4696:   while (true)
        !          4697:     {
        !          4698:       BusLogic_DriverOptions_T *DriverOptions =
        !          4699:        &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
        !          4700:       int TargetID;
        !          4701:       memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T));
        !          4702:       for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
        !          4703:        DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4704:          BusLogic_ErrorRecovery_Default;
        !          4705:       while (*OptionsString != '\0' && *OptionsString != ';')
        !          4706:        {
        !          4707:          /* Probing Options. */
        !          4708:          if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
        !          4709:            {
        !          4710:              BusLogic_IO_Address_T IO_Address =
        !          4711:                simple_strtoul(OptionsString, &OptionsString, 0);
        !          4712:              BusLogic_ProbeOptions.LimitedProbeISA = true;
        !          4713:              switch (IO_Address)
        !          4714:                {
        !          4715:                case 0x330:
        !          4716:                  BusLogic_ProbeOptions.Probe330 = true;
        !          4717:                  break;
        !          4718:                case 0x334:
        !          4719:                  BusLogic_ProbeOptions.Probe334 = true;
        !          4720:                  break;
        !          4721:                case 0x230:
        !          4722:                  BusLogic_ProbeOptions.Probe230 = true;
        !          4723:                  break;
        !          4724:                case 0x234:
        !          4725:                  BusLogic_ProbeOptions.Probe234 = true;
        !          4726:                  break;
        !          4727:                case 0x130:
        !          4728:                  BusLogic_ProbeOptions.Probe130 = true;
        !          4729:                  break;
        !          4730:                case 0x134:
        !          4731:                  BusLogic_ProbeOptions.Probe134 = true;
        !          4732:                  break;
        !          4733:                default:
        !          4734:                  BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4735:                                 "(illegal I/O Address 0x%X)\n",
        !          4736:                                 NULL, IO_Address);
        !          4737:                  return;
        !          4738:                }
        !          4739:            }
        !          4740:          else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
        !          4741:            BusLogic_ProbeOptions.NoProbeISA = true;
        !          4742:          else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
        !          4743:            BusLogic_ProbeOptions.NoProbePCI = true;
        !          4744:          else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
        !          4745:            BusLogic_ProbeOptions.NoProbe = true;
        !          4746:          else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
        !          4747:            BusLogic_ProbeOptions.NoSortPCI = true;
        !          4748:          else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
        !          4749:            BusLogic_ProbeOptions.MultiMasterFirst = true;
        !          4750:          else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
        !          4751:            BusLogic_ProbeOptions.FlashPointFirst = true;
        !          4752:          /* Tagged Queuing Options. */
        !          4753:          else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
        !          4754:                   BusLogic_ParseKeyword(&OptionsString, "QD:["))
        !          4755:            {
        !          4756:              for (TargetID = 0;
        !          4757:                   TargetID < BusLogic_MaxTargetDevices;
        !          4758:                   TargetID++)
        !          4759:                {
        !          4760:                  unsigned short QueueDepth =
        !          4761:                    simple_strtoul(OptionsString, &OptionsString, 0);
        !          4762:                  if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
        !          4763:                    {
        !          4764:                      BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4765:                                     "(illegal Queue Depth %d)\n",
        !          4766:                                     NULL, QueueDepth);
        !          4767:                      return;
        !          4768:                    }
        !          4769:                  DriverOptions->QueueDepth[TargetID] = QueueDepth;
        !          4770:                  if (*OptionsString == ',')
        !          4771:                    OptionsString++;
        !          4772:                  else if (*OptionsString == ']')
        !          4773:                    break;
        !          4774:                  else
        !          4775:                    {
        !          4776:                      BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4777:                                     "(',' or ']' expected at '%s')\n",
        !          4778:                                     NULL, OptionsString);
        !          4779:                      return;
        !          4780:                    }
        !          4781:                }
        !          4782:              if (*OptionsString != ']')
        !          4783:                {
        !          4784:                  BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4785:                                 "(']' expected at '%s')\n",
        !          4786:                                 NULL, OptionsString);
        !          4787:                  return;
        !          4788:                }
        !          4789:              else OptionsString++;
        !          4790:            }
        !          4791:          else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
        !          4792:                   BusLogic_ParseKeyword(&OptionsString, "QD:"))
        !          4793:            {
        !          4794:              unsigned short QueueDepth =
        !          4795:                simple_strtoul(OptionsString, &OptionsString, 0);
        !          4796:              if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
        !          4797:                {
        !          4798:                  BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4799:                                 "(illegal Queue Depth %d)\n",
        !          4800:                                 NULL, QueueDepth);
        !          4801:                  return;
        !          4802:                }
        !          4803:              DriverOptions->CommonQueueDepth = QueueDepth;
        !          4804:              for (TargetID = 0;
        !          4805:                   TargetID < BusLogic_MaxTargetDevices;
        !          4806:                   TargetID++)
        !          4807:                DriverOptions->QueueDepth[TargetID] = QueueDepth;
        !          4808:            }
        !          4809:          else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
        !          4810:                   BusLogic_ParseKeyword(&OptionsString, "TQ:"))
        !          4811:            {
        !          4812:              if (BusLogic_ParseKeyword(&OptionsString, "Default"))
        !          4813:                {
        !          4814:                  DriverOptions->TaggedQueuingPermitted = 0x0000;
        !          4815:                  DriverOptions->TaggedQueuingPermittedMask = 0x0000;
        !          4816:                }
        !          4817:              else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
        !          4818:                {
        !          4819:                  DriverOptions->TaggedQueuingPermitted = 0xFFFF;
        !          4820:                  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
        !          4821:                }
        !          4822:              else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
        !          4823:                {
        !          4824:                  DriverOptions->TaggedQueuingPermitted = 0x0000;
        !          4825:                  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
        !          4826:                }
        !          4827:              else
        !          4828:                {
        !          4829:                  unsigned short TargetBit;
        !          4830:                  for (TargetID = 0, TargetBit = 1;
        !          4831:                       TargetID < BusLogic_MaxTargetDevices;
        !          4832:                       TargetID++, TargetBit <<= 1)
        !          4833:                    switch (*OptionsString++)
        !          4834:                      {
        !          4835:                      case 'Y':
        !          4836:                        DriverOptions->TaggedQueuingPermitted |= TargetBit;
        !          4837:                        DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
        !          4838:                        break;
        !          4839:                      case 'N':
        !          4840:                        DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
        !          4841:                        DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
        !          4842:                        break;
        !          4843:                      case 'X':
        !          4844:                        break;
        !          4845:                      default:
        !          4846:                        OptionsString--;
        !          4847:                        TargetID = BusLogic_MaxTargetDevices;
        !          4848:                        break;
        !          4849:                      }
        !          4850:                }
        !          4851:            }
        !          4852:          /* Error Recovery Option. */
        !          4853:          else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") ||
        !          4854:                   BusLogic_ParseKeyword(&OptionsString, "ER:"))
        !          4855:            {
        !          4856:              if (BusLogic_ParseKeyword(&OptionsString, "Default"))
        !          4857:                for (TargetID = 0;
        !          4858:                     TargetID < BusLogic_MaxTargetDevices;
        !          4859:                     TargetID++)
        !          4860:                  DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4861:                    BusLogic_ErrorRecovery_Default;
        !          4862:              else if (BusLogic_ParseKeyword(&OptionsString, "HardReset"))
        !          4863:                for (TargetID = 0;
        !          4864:                     TargetID < BusLogic_MaxTargetDevices;
        !          4865:                     TargetID++)
        !          4866:                  DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4867:                    BusLogic_ErrorRecovery_HardReset;
        !          4868:              else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset"))
        !          4869:                for (TargetID = 0;
        !          4870:                     TargetID < BusLogic_MaxTargetDevices;
        !          4871:                     TargetID++)
        !          4872:                  DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4873:                    BusLogic_ErrorRecovery_BusDeviceReset;
        !          4874:              else if (BusLogic_ParseKeyword(&OptionsString, "None"))
        !          4875:                for (TargetID = 0;
        !          4876:                     TargetID < BusLogic_MaxTargetDevices;
        !          4877:                     TargetID++)
        !          4878:                  DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4879:                    BusLogic_ErrorRecovery_None;
        !          4880:              else
        !          4881:                for (TargetID = 0;
        !          4882:                     TargetID < BusLogic_MaxTargetDevices;
        !          4883:                     TargetID++)
        !          4884:                  switch (*OptionsString++)
        !          4885:                    {
        !          4886:                    case 'D':
        !          4887:                      DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4888:                        BusLogic_ErrorRecovery_Default;
        !          4889:                      break;
        !          4890:                    case 'H':
        !          4891:                      DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4892:                        BusLogic_ErrorRecovery_HardReset;
        !          4893:                      break;
        !          4894:                    case 'B':
        !          4895:                      DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4896:                        BusLogic_ErrorRecovery_BusDeviceReset;
        !          4897:                      break;
        !          4898:                    case 'N':
        !          4899:                      DriverOptions->ErrorRecoveryStrategy[TargetID] =
        !          4900:                        BusLogic_ErrorRecovery_None;
        !          4901:                      break;
        !          4902:                    default:
        !          4903:                      OptionsString--;
        !          4904:                      TargetID = BusLogic_MaxTargetDevices;
        !          4905:                      break;
        !          4906:                    }
        !          4907:            }
        !          4908:          /* Miscellaneous Options. */
        !          4909:          else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
        !          4910:                   BusLogic_ParseKeyword(&OptionsString, "BST:"))
        !          4911:            {
        !          4912:              unsigned short BusSettleTime =
        !          4913:                simple_strtoul(OptionsString, &OptionsString, 0);
        !          4914:              if (BusSettleTime > 5 * 60)
        !          4915:                {
        !          4916:                  BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4917:                                 "(illegal Bus Settle Time %d)\n",
        !          4918:                                 NULL, BusSettleTime);
        !          4919:                  return;
        !          4920:                }
        !          4921:              DriverOptions->BusSettleTime = BusSettleTime;
        !          4922:            }
        !          4923:          else if (BusLogic_ParseKeyword(&OptionsString,
        !          4924:                                         "InhibitTargetInquiry"))
        !          4925:            DriverOptions->LocalOptions.InhibitTargetInquiry = true;
        !          4926:          /* Debugging Options. */
        !          4927:          else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
        !          4928:              BusLogic_GlobalOptions.TraceProbe = true;
        !          4929:          else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
        !          4930:              BusLogic_GlobalOptions.TraceHardwareReset = true;
        !          4931:          else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
        !          4932:              BusLogic_GlobalOptions.TraceConfiguration = true;
        !          4933:          else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
        !          4934:              BusLogic_GlobalOptions.TraceErrors = true;
        !          4935:          else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
        !          4936:            {
        !          4937:              BusLogic_GlobalOptions.TraceProbe = true;
        !          4938:              BusLogic_GlobalOptions.TraceHardwareReset = true;
        !          4939:              BusLogic_GlobalOptions.TraceConfiguration = true;
        !          4940:              BusLogic_GlobalOptions.TraceErrors = true;
        !          4941:            }
        !          4942:          if (*OptionsString == ',')
        !          4943:            OptionsString++;
        !          4944:          else if (*OptionsString != ';' && *OptionsString != '\0')
        !          4945:            {
        !          4946:              BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
        !          4947:                             "ignored\n", NULL, OptionsString);
        !          4948:              *OptionsString = '\0';
        !          4949:            }
        !          4950:        }
        !          4951:       if (!(BusLogic_DriverOptionsCount == 0 ||
        !          4952:            BusLogic_ProbeInfoCount == 0 ||
        !          4953:            BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
        !          4954:        {
        !          4955:          BusLogic_Error("BusLogic: Invalid Driver Options "
        !          4956:                         "(all or no I/O Addresses must be specified)\n", NULL);
        !          4957:          return;
        !          4958:        }
        !          4959:       /*
        !          4960:        Tagged Queuing is disabled when the Queue Depth is 1 since queuing
        !          4961:        multiple commands is not possible.
        !          4962:       */
        !          4963:       for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
        !          4964:        if (DriverOptions->QueueDepth[TargetID] == 1)
        !          4965:          {
        !          4966:            unsigned short TargetBit = 1 << TargetID;
        !          4967:            DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
        !          4968:            DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
        !          4969:          }
        !          4970:       if (*OptionsString == ';') OptionsString++;
        !          4971:       if (*OptionsString == '\0') return;
        !          4972:     }
        !          4973: }
        !          4974: 
        !          4975: 
        !          4976: /*
        !          4977:   BusLogic_Setup handles processing of Kernel Command Line Arguments.
        !          4978: */
        !          4979: 
        !          4980: void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers)
        !          4981: {
        !          4982:   if (CommandLineIntegers[0] != 0)
        !          4983:     {
        !          4984:       BusLogic_Error("BusLogic: Obsolete Command Line Entry "
        !          4985:                     "Format Ignored\n", NULL);
        !          4986:       return;
        !          4987:     }
        !          4988:   if (CommandLineString == NULL || *CommandLineString == '\0') return;
        !          4989:   BusLogic_ParseDriverOptions(CommandLineString);
        !          4990: }
        !          4991: 
        !          4992: 
        !          4993: /*
        !          4994:   Include Module support if requested.
        !          4995: */
        !          4996: 
        !          4997: #ifdef MODULE
        !          4998: 
        !          4999: SCSI_Host_Template_T driver_template = BUSLOGIC;
        !          5000: 
        !          5001: #include "scsi_module.c"
        !          5002: 
        !          5003: #endif

unix.superglobalmegacorp.com

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