Annotation of ntddk/src/scsi/aha154x/aha154x.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     aha154x.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This is the port driver for the Adaptec 1540B SCSI Adapter.
        !            12: 
        !            13: Author:
        !            14: 
        !            15:     Mike Glass
        !            16:     Tuong Hoang (Adaptec)
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     kernel mode only
        !            21: 
        !            22: Notes:
        !            23: 
        !            24: Revision History:
        !            25: 
        !            26: --*/
        !            27: 
        !            28: #include "miniport.h"
        !            29: #include "aha154x.h"               // includes scsi.h
        !            30: 
        !            31: //
        !            32: // This conditionally compiles in the code to force the DMA transfer speed
        !            33: // to 5.0.
        !            34: //
        !            35: 
        !            36: #define FORCE_DMA_SPEED 1
        !            37: 
        !            38: //
        !            39: // The following structure is allocated
        !            40: // from noncached memory as data will be DMA'd to
        !            41: // and from it.
        !            42: //
        !            43: 
        !            44: typedef struct _NONCACHED_EXTENSION {
        !            45: 
        !            46:     //
        !            47:     // Physical base address of mailboxes
        !            48:     //
        !            49: 
        !            50:     ULONG MailboxPA;
        !            51: 
        !            52:     //
        !            53:     // Mailboxes
        !            54:     //
        !            55: 
        !            56:     MBO              Mbo[MB_COUNT];
        !            57:     MBI              Mbi[MB_COUNT];
        !            58: 
        !            59: } NONCACHED_EXTENSION, *PNONCACHED_EXTENSION;
        !            60: 
        !            61: //
        !            62: // Device extension
        !            63: //
        !            64: 
        !            65: typedef struct _HW_DEVICE_EXTENSION {
        !            66: 
        !            67:     //
        !            68:     // NonCached extension
        !            69:     //
        !            70: 
        !            71:     PNONCACHED_EXTENSION NoncachedExtension;
        !            72: 
        !            73:     //
        !            74:     // Adapter parameters
        !            75:     //
        !            76: 
        !            77:     PBASE_REGISTER   BaseIoAddress;
        !            78: 
        !            79:     //
        !            80:     // Host Target id.
        !            81:     //
        !            82: 
        !            83:     UCHAR HostTargetId;
        !            84: 
        !            85:     //
        !            86:     // Old in\out box indexes.
        !            87:     //
        !            88: 
        !            89:     UCHAR MboIndex;
        !            90: 
        !            91:     UCHAR MbiIndex;
        !            92: 
        !            93:     //
        !            94:     // Pending request.
        !            95:     //
        !            96: 
        !            97:     BOOLEAN PendingRequest;
        !            98: 
        !            99:     //
        !           100:     // Bus on time to use.
        !           101:     //
        !           102: 
        !           103:     UCHAR BusOnTime;
        !           104: 
        !           105: } HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
        !           106: 
        !           107: //
        !           108: // Logical unit extension
        !           109: //
        !           110: 
        !           111: typedef struct _HW_LU_EXTENSION {
        !           112:     PSCSI_REQUEST_BLOCK CurrentSrb;
        !           113: } HW_LU_EXTENSION, *PHW_LU_EXTENSION;
        !           114: 
        !           115: 
        !           116: //
        !           117: // Function declarations
        !           118: //
        !           119: // Functions that start with 'A154x' are entry points
        !           120: // for the OS port driver.
        !           121: //
        !           122: 
        !           123: ULONG
        !           124: DriverEntry(
        !           125:     IN PVOID DriverObject,
        !           126:     IN PVOID Argument2
        !           127:     );
        !           128: 
        !           129: ULONG
        !           130: A154xDetermineInstalled(
        !           131:     IN PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           132:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           133:     IN OUT PULONG AdapterCount,
        !           134:     OUT PBOOLEAN Again
        !           135:     );
        !           136: 
        !           137: ULONG
        !           138: A154xFindAdapter(
        !           139:     IN PVOID HwDeviceExtension,
        !           140:     IN PVOID Context,
        !           141:     IN PVOID BusInformation,
        !           142:     IN PCHAR ArgumentString,
        !           143:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           144:     OUT PBOOLEAN Again
        !           145:     );
        !           146: 
        !           147: BOOLEAN
        !           148: A154xHwInitialize(
        !           149:     IN PVOID DeviceExtension
        !           150:     );
        !           151: 
        !           152: BOOLEAN
        !           153: A154xStartIo(
        !           154:     IN PVOID DeviceExtension,
        !           155:     IN PSCSI_REQUEST_BLOCK Srb
        !           156:     );
        !           157: 
        !           158: BOOLEAN
        !           159: A154xInterrupt(
        !           160:     IN PVOID DeviceExtension
        !           161:     );
        !           162: 
        !           163: BOOLEAN
        !           164: A154xResetBus(
        !           165:     IN PVOID HwDeviceExtension,
        !           166:     IN ULONG PathId
        !           167:     );
        !           168: 
        !           169: VOID
        !           170: GetHostAdapterBoardId (
        !           171:     IN PVOID HwDeviceExtension,
        !           172:     OUT PUCHAR BoardId
        !           173:     );
        !           174: 
        !           175: //
        !           176: // This function is called from A154xStartIo.
        !           177: //
        !           178: 
        !           179: VOID
        !           180: BuildCcb(
        !           181:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           182:     IN PSCSI_REQUEST_BLOCK Srb
        !           183:     );
        !           184: 
        !           185: //
        !           186: // This function is called from BuildCcb.
        !           187: //
        !           188: 
        !           189: VOID
        !           190: BuildSdl(
        !           191:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           192:     IN PSCSI_REQUEST_BLOCK Srb
        !           193:     );
        !           194: 
        !           195: //
        !           196: // This function is called from A154xInitialize.
        !           197: //
        !           198: 
        !           199: BOOLEAN
        !           200: AdapterPresent(
        !           201:     IN PVOID HwDeviceExtension
        !           202:     );
        !           203: 
        !           204: //
        !           205: // This function is called from A154xInterrupt.
        !           206: //
        !           207: 
        !           208: UCHAR
        !           209: MapError(
        !           210:     IN PVOID HwDeviceExtension,
        !           211:     IN PSCSI_REQUEST_BLOCK Srb,
        !           212:     IN PCCB Ccb
        !           213:     );
        !           214: 
        !           215: BOOLEAN
        !           216: ReadCommandRegister(
        !           217:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           218:     OUT PUCHAR DataByte,
        !           219:     IN BOOLEAN TimeOutFlag
        !           220:     );
        !           221: 
        !           222: BOOLEAN
        !           223: WriteCommandRegister(
        !           224:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           225:     IN UCHAR AdapterCommand,
        !           226:     IN BOOLEAN LogError
        !           227:     );
        !           228: 
        !           229: BOOLEAN
        !           230: WriteDataRegister(
        !           231:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           232:     IN UCHAR DataByte
        !           233:     );
        !           234: 
        !           235: BOOLEAN
        !           236: ScatterGatherSupported (
        !           237:    IN PHW_DEVICE_EXTENSION HwDeviceExtension
        !           238:    );
        !           239: 
        !           240: BOOLEAN
        !           241: FinishHBACmd(
        !           242:     IN PHW_DEVICE_EXTENSION HwDeviceExtension
        !           243:     );
        !           244: 
        !           245: BOOLEAN
        !           246: SpinForInterrupt(
        !           247:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !           248:     IN BOOLEAN TimeOutFlag
        !           249:     );
        !           250: 
        !           251: BOOLEAN SendUnlockCommand(
        !           252:     IN PVOID HwDeviceExtension,
        !           253:     IN UCHAR locktype
        !           254:     );
        !           255: 
        !           256: BOOLEAN UnlockMailBoxes(
        !           257:     IN PVOID HwDeviceExtension
        !           258:     );
        !           259: 
        !           260: ULONG
        !           261: AhaParseArgumentString(
        !           262:     IN PCHAR String,
        !           263:     IN PCHAR KeyWord
        !           264:     );
        !           265: 
        !           266: ULONG
        !           267: DriverEntry(
        !           268:     IN PVOID DriverObject,
        !           269:     IN PVOID Argument2
        !           270:     )
        !           271: 
        !           272: /*++
        !           273: 
        !           274: Routine Description:
        !           275: 
        !           276:     Installable driver initialization entry point for system.
        !           277: 
        !           278: Arguments:
        !           279: 
        !           280:     Driver Object
        !           281: 
        !           282: Return Value:
        !           283: 
        !           284:     Status from ScsiPortInitialize()
        !           285: 
        !           286: --*/
        !           287: 
        !           288: {
        !           289:     HW_INITIALIZATION_DATA hwInitializationData;
        !           290:     ULONG adapterCount;
        !           291:     ULONG isaStatus;
        !           292:     ULONG mcaStatus;
        !           293:     ULONG i;
        !           294: 
        !           295:     DebugPrint((1,"\n\nSCSI Adaptec 154X MiniPort Driver\n"));
        !           296: 
        !           297:     //
        !           298:     // Zero out structure.
        !           299:     //
        !           300: 
        !           301:     for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) {
        !           302:         ((PUCHAR)&hwInitializationData)[i] = 0;
        !           303:     }
        !           304: 
        !           305:     //
        !           306:     // Set size of hwInitializationData.
        !           307:     //
        !           308: 
        !           309:     hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
        !           310: 
        !           311:     //
        !           312:     // Set entry points.
        !           313:     //
        !           314: 
        !           315:     hwInitializationData.HwInitialize = A154xHwInitialize;
        !           316:     hwInitializationData.HwResetBus = A154xResetBus;
        !           317:     hwInitializationData.HwStartIo = A154xStartIo;
        !           318:     hwInitializationData.HwInterrupt = A154xInterrupt;
        !           319:     hwInitializationData.HwFindAdapter = A154xFindAdapter;
        !           320: 
        !           321:     //
        !           322:     // Indicate no buffer mapping but will need physical addresses.
        !           323:     //
        !           324: 
        !           325:     hwInitializationData.NeedPhysicalAddresses = TRUE;
        !           326: 
        !           327:     //
        !           328:     // Specify size of extensions.
        !           329:     //
        !           330: 
        !           331:     hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
        !           332:     hwInitializationData.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
        !           333: 
        !           334:     //
        !           335:     // Specifiy the bus type.
        !           336:     //
        !           337: 
        !           338:     hwInitializationData.AdapterInterfaceType = Isa;
        !           339:     hwInitializationData.NumberOfAccessRanges = 1;
        !           340: 
        !           341:     //
        !           342:     // Ask for SRB extensions for CCBs.
        !           343:     //
        !           344: 
        !           345:     hwInitializationData.SrbExtensionSize = sizeof(CCB);
        !           346: 
        !           347:     //
        !           348:     // The adapter count is used by the find adapter routine to track how
        !           349:     // which adapter addresses have been tested.
        !           350:     //
        !           351: 
        !           352:     adapterCount = 0;
        !           353: 
        !           354:     isaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &adapterCount);
        !           355: 
        !           356:     //
        !           357:     // Now try to configure for the Mca bus.
        !           358:     // Specifiy the bus type.
        !           359:     //
        !           360: 
        !           361:     hwInitializationData.AdapterInterfaceType = MicroChannel;
        !           362:     adapterCount = 0;
        !           363:     mcaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &adapterCount);
        !           364: 
        !           365:     //
        !           366:     // Return the smaller status.
        !           367:     //
        !           368: 
        !           369:     return(mcaStatus < isaStatus ? mcaStatus : isaStatus);
        !           370: 
        !           371: } // end A154xEntry()
        !           372: 
        !           373: 
        !           374: ULONG
        !           375: A154xFindAdapter(
        !           376:     IN PVOID HwDeviceExtension,
        !           377:     IN PVOID Context,
        !           378:     IN PVOID BusInformation,
        !           379:     IN PCHAR ArgumentString,
        !           380:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           381:     OUT PBOOLEAN Again
        !           382:     )
        !           383: /*++
        !           384: 
        !           385: Routine Description:
        !           386: 
        !           387:     This function is called by the OS-specific port driver after
        !           388:     the necessary storage has been allocated, to gather information
        !           389:     about the adapter's configuration.
        !           390: 
        !           391: Arguments:
        !           392: 
        !           393:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !           394:     Context - Register base address
        !           395:     ConfigInfo - Configuration information structure describing HBA
        !           396:         This structure is defined in PORT.H.
        !           397: 
        !           398: Return Value:
        !           399: 
        !           400:     ULONG
        !           401: 
        !           402: --*/
        !           403: 
        !           404: {
        !           405:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !           406:     ULONG length;
        !           407:     ULONG status;
        !           408:     UCHAR adapterTid;
        !           409:     UCHAR dmaChannel;
        !           410:     UCHAR irq;
        !           411:     UCHAR bit;
        !           412: 
        !           413:     //
        !           414:     // Determine if there are any adapters installed.  Determine installed
        !           415:     // will initialize the BaseIoAddress if an adapter is found.
        !           416:     //
        !           417: 
        !           418:     status = A154xDetermineInstalled(deviceExtension,
        !           419:                         ConfigInfo,
        !           420:                         Context,
        !           421:                         Again);
        !           422: 
        !           423:     //
        !           424:     // If there are not adapter's found then return.
        !           425:     //
        !           426: 
        !           427:     if (status != SP_RETURN_FOUND) {
        !           428:         return(status);
        !           429:     }
        !           430: 
        !           431:     //
        !           432:     // Issue adapter command to get IRQ.
        !           433:     //
        !           434:     // Returns 3 data bytes:
        !           435:     //
        !           436:     // Byte 0   Dma Channel
        !           437:     //
        !           438:     // Byte 1   Interrupt Channel
        !           439:     //
        !           440:     // Byte 2   Adapter SCSI ID
        !           441:     //
        !           442: 
        !           443:     if (!WriteCommandRegister(deviceExtension, AC_RET_CONFIGURATION_DATA, TRUE)) {
        !           444:         DebugPrint((1,"A154xFindAdapter: Get configuration data command failed\n"));
        !           445:         return SP_RETURN_ERROR;
        !           446:     }
        !           447: 
        !           448:     //
        !           449:     // Determine DMA channel.
        !           450:     //
        !           451: 
        !           452:     if (!ReadCommandRegister(deviceExtension,&dmaChannel,TRUE)) {
        !           453:         DebugPrint((1,"A154xFindAdapter: Couldn't read dma channel\n"));
        !           454:         return SP_RETURN_ERROR;
        !           455:     }
        !           456: 
        !           457:     if (ConfigInfo->AdapterInterfaceType != MicroChannel) {
        !           458: 
        !           459:         WHICH_BIT(dmaChannel,bit);
        !           460:     
        !           461:         ConfigInfo->DmaChannel = bit;
        !           462:     
        !           463:         DebugPrint((2,"A154xFindAdapter: DMA channel is %x\n",
        !           464:             ConfigInfo->DmaChannel));
        !           465:     
        !           466:     } else {
        !           467:         ConfigInfo->InterruptMode = LevelSensitive;
        !           468:     }
        !           469: 
        !           470:     //
        !           471:     // Determine hardware interrupt vector.
        !           472:     //
        !           473: 
        !           474:     if (!ReadCommandRegister(deviceExtension,&irq,TRUE)) {
        !           475:         DebugPrint((1,"A154xFindAdapter: Couldn't read adapter irq\n"));
        !           476:         return SP_RETURN_ERROR;
        !           477:     }
        !           478: 
        !           479:     WHICH_BIT(irq, bit);
        !           480: 
        !           481:     ConfigInfo->BusInterruptLevel = (UCHAR) 9 + bit;
        !           482: 
        !           483:     //
        !           484:     // Determine what SCSI bus id the adapter is on.
        !           485:     //
        !           486: 
        !           487:     if (!ReadCommandRegister(deviceExtension,&adapterTid,TRUE)) {
        !           488:         DebugPrint((1,"A154xFindAdapter: Couldn't read adapter SCSI id\n"));
        !           489:         return SP_RETURN_ERROR;
        !           490:     }
        !           491: 
        !           492:     //
        !           493:     // Set number of buses.
        !           494:     //
        !           495: 
        !           496:     ConfigInfo->NumberOfBuses = 1;
        !           497:     ConfigInfo->InitiatorBusId[0] = adapterTid;
        !           498:     deviceExtension->HostTargetId = adapterTid;
        !           499: 
        !           500:     ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE;
        !           501:     ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_DESCRIPTORS - 1;
        !           502:     ConfigInfo->ScatterGather = ScatterGatherSupported(HwDeviceExtension);
        !           503: 
        !           504:     if (!ConfigInfo->ScatterGather) {
        !           505:         //ConfigInfo->NumberOfPhysicalBreaks = 1;
        !           506:         DebugPrint((1,"Aha154x: Scatter/Gather not supported!"));
        !           507:     }
        !           508: 
        !           509:     ConfigInfo->Master = TRUE;
        !           510: 
        !           511:     //
        !           512:     // Allocate a Noncached Extension to use for mail boxes.
        !           513:     //
        !           514: 
        !           515:     deviceExtension->NoncachedExtension = ScsiPortGetUncachedExtension(
        !           516:                                 deviceExtension,
        !           517:                                 ConfigInfo,
        !           518:                                 sizeof(NONCACHED_EXTENSION));
        !           519: 
        !           520:     if (deviceExtension->NoncachedExtension == NULL) {
        !           521: 
        !           522:         //
        !           523:         // Log error.
        !           524:         //
        !           525: 
        !           526:         ScsiPortLogError(
        !           527:             deviceExtension,
        !           528:             NULL,
        !           529:             0,
        !           530:             0,
        !           531:             0,
        !           532:             SP_INTERNAL_ADAPTER_ERROR,
        !           533:             7 << 8
        !           534:             );
        !           535: 
        !           536:         return(SP_RETURN_ERROR);
        !           537:     }
        !           538: 
        !           539:     //
        !           540:     // Convert virtual to physical mailbox address.
        !           541:     //
        !           542: 
        !           543:     deviceExtension->NoncachedExtension->MailboxPA =
        !           544:            ScsiPortConvertPhysicalAddressToUlong(
        !           545:             ScsiPortGetPhysicalAddress(deviceExtension,
        !           546:                                  NULL,
        !           547:                                  deviceExtension->NoncachedExtension->Mbo,
        !           548:                                  &length));
        !           549: 
        !           550:     //
        !           551:     // Set default bus on time.  Then check for an override parameter.
        !           552:     //
        !           553: 
        !           554:     deviceExtension->BusOnTime = 0x07;
        !           555:     if (ArgumentString != NULL) {
        !           556: 
        !           557:         length = AhaParseArgumentString(ArgumentString, "BUSONTIME");
        !           558: 
        !           559:         //
        !           560:         // Validate that the new bus on time is reasonable before attempting
        !           561:         // to set it.
        !           562:         //
        !           563: 
        !           564:         if (length >= 2 && length <= 15) {
        !           565: 
        !           566:             deviceExtension->BusOnTime = (UCHAR) length;
        !           567:             DebugPrint((1,"A154xFindAdapter: Setting bus on time: %ld\n", length));
        !           568:         }
        !           569:     }
        !           570: 
        !           571:     DebugPrint((3,"A154xFindAdapter: Configuration completed\n"));
        !           572:     return SP_RETURN_FOUND;
        !           573: } // end A154xFindAdapter()
        !           574: 
        !           575: 
        !           576: BOOLEAN
        !           577: AdaptecAdapter(
        !           578:     IN PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           579:     IN ULONG   IoPort,
        !           580:     IN BOOLEAN Mca
        !           581:     )
        !           582: 
        !           583: /*++
        !           584: 
        !           585: Routine Description:
        !           586: 
        !           587:     This routine checks the Special Options byte of the Adapter Inquiry
        !           588:     command to see if it is one of the two values returned by Adaptec
        !           589:     Adapters.  This avoids claiming adapters from BusLogic and DTC.
        !           590: 
        !           591: Arguments:
        !           592: 
        !           593:     HwDeviceExtension - miniport driver's adapter extension.
        !           594: 
        !           595: Return Values:
        !           596: 
        !           597:     TRUE if the adapter looks like an Adaptec.
        !           598:     FALSE if not.
        !           599: 
        !           600: --*/
        !           601: 
        !           602: {
        !           603:     ULONG i;
        !           604:     UCHAR byte;
        !           605:     UCHAR specialOptions;
        !           606:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !           607:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !           608: 
        !           609:     if (Mca == TRUE) {
        !           610:         INIT_DATA initData;
        !           611:         LONG slot;
        !           612:         LONG i;
        !           613: 
        !           614:         for (slot = 0; slot < NUMBER_POS_SLOTS; slot++) {
        !           615:             i = ScsiPortGetBusData(HwDeviceExtension,
        !           616:                                    Pos,
        !           617:                                    0,
        !           618:                                    slot,
        !           619:                                    &initData.PosData[slot],
        !           620:                                    sizeof(POS_DATA));
        !           621:             if (i < (sizeof(POS_DATA))) {
        !           622:                 initData.PosData[slot].AdapterId = 0xffff;
        !           623:             }
        !           624:         }
        !           625: 
        !           626:         for (slot = 0; slot < NUMBER_POS_SLOTS; slot++) {
        !           627:             if (initData.PosData[slot].AdapterId == POS_IDENTIFIER) {
        !           628:                 switch (initData.PosData[slot].IoPortInformation & POS_PORT_MASK) {
        !           629:                 case POS_PORT_130:
        !           630:                     if (IoPort == 0x0130) {
        !           631:                         return TRUE;
        !           632:                     }
        !           633:                     break;
        !           634:                 case POS_PORT_134:
        !           635:                     if (IoPort == 0x0134) {
        !           636:                         return TRUE;
        !           637:                     }
        !           638:                     break;
        !           639:                 case POS_PORT_230:
        !           640:                     if (IoPort == 0x0230) {
        !           641:                         return TRUE;
        !           642:                     }
        !           643:                     break;
        !           644:                 case POS_PORT_234:
        !           645:                     if (IoPort == 0x234) {
        !           646:                         return TRUE;
        !           647:                     }
        !           648:                     break;
        !           649:                 case POS_PORT_330:
        !           650:                     if (IoPort == 0x330) {
        !           651:                         return TRUE;
        !           652:                     }
        !           653:                     break;
        !           654:                 case POS_PORT_334:
        !           655:                     if (IoPort == 0x334) {
        !           656:                         return TRUE;
        !           657:                     }
        !           658:                     break;
        !           659:                 }
        !           660:             }
        !           661:         }
        !           662:         return FALSE;
        !           663:     }
        !           664: 
        !           665:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
        !           666:                            IOP_INTERRUPT_RESET);
        !           667: 
        !           668:     if (!WriteCommandRegister(HwDeviceExtension,AC_ADAPTER_INQUIRY,FALSE)) {
        !           669:         return FALSE;
        !           670:     }
        !           671: 
        !           672:     //
        !           673:     // Byte 0.
        !           674:     //
        !           675: 
        !           676:     if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) {
        !           677:         return FALSE;
        !           678:     }
        !           679: 
        !           680:     //
        !           681:     // Get the special options byte.
        !           682:     //
        !           683: 
        !           684:     if ((ReadCommandRegister(HwDeviceExtension,&specialOptions,TRUE)) == FALSE) {
        !           685:         return FALSE;
        !           686:     }
        !           687: 
        !           688:     //
        !           689:     // Get the last two bytes and clear the interrupt.
        !           690:     //
        !           691: 
        !           692:     if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) {
        !           693:         return FALSE;
        !           694:     }
        !           695: 
        !           696:     if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) {
        !           697:         return FALSE;
        !           698:     }
        !           699: 
        !           700:     //
        !           701:     // Interrupt handler is not yet installed so wait for HACC by hand.
        !           702:     //
        !           703: 
        !           704:     for (i = 0; i<5000; i++) {
        !           705:         if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) ==
        !           706:             (IOP_ANY_INTERRUPT | IOP_COMMAND_COMPLETE) ) {
        !           707:             break;
        !           708:         }
        !           709:         ScsiPortStallExecution(1);
        !           710:     }
        !           711: 
        !           712:     if ((specialOptions == 0x30) || (specialOptions == 0x42)) {
        !           713:         return TRUE;
        !           714:     }
        !           715: 
        !           716:     return FALSE;
        !           717: }
        !           718: 
        !           719: ULONG
        !           720: A154xDetermineInstalled(
        !           721:     IN PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           722:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           723:     IN OUT PULONG AdapterCount,
        !           724:     OUT PBOOLEAN Again
        !           725:     )
        !           726: 
        !           727: /*++
        !           728: 
        !           729: Routine Description:
        !           730: 
        !           731:     Determine if Adaptec 154X SCSI adapter is installed in system
        !           732:     by reading the status register as each base I/O address
        !           733:     and looking for a pattern.  If an adapter is found, the BaseIoAddres is
        !           734:     initialized.
        !           735: 
        !           736: Arguments:
        !           737: 
        !           738:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !           739: 
        !           740:     ConfigInfo - Supplies the known configuraiton information.
        !           741: 
        !           742:     AdapterCount - Supplies the count of adapter slots which have been tested.
        !           743: 
        !           744:     Again - Returns whehter the  OS specific driver should call again.
        !           745: 
        !           746: Return Value:
        !           747: 
        !           748:     Returns a status indicating whether a driver is present or not.
        !           749: 
        !           750: --*/
        !           751: 
        !           752: {
        !           753:     PBASE_REGISTER baseIoAddress;
        !           754:     PUCHAR ioSpace;
        !           755:     UCHAR  portValue;
        !           756: 
        !           757:     //
        !           758:     // The following table specifies the ports to be checked when searching for
        !           759:     // an adapter.  A zero entry terminates the search.
        !           760:     //
        !           761: 
        !           762:     CONST ULONG AdapterAddresses[7] = {0X330, 0X334, 0X234, 0X134, 0X130, 0X230, 0};
        !           763: 
        !           764: 
        !           765:     //
        !           766:     // Get the system physical address for this card.  The card uses I/O space.
        !           767:     //
        !           768: 
        !           769:     ioSpace = ScsiPortGetDeviceBase(
        !           770:         HwDeviceExtension,                  // HwDeviceExtension
        !           771:         ConfigInfo->AdapterInterfaceType,   // AdapterInterfaceType
        !           772:         ConfigInfo->SystemIoBusNumber,      // SystemIoBusNumber
        !           773:         ScsiPortConvertUlongToPhysicalAddress(0),
        !           774:         0x400,                              // NumberOfBytes
        !           775:         TRUE                                // InIoSpace
        !           776:         );
        !           777: 
        !           778:     //
        !           779:     // Scan though the adapter address looking for adapters.
        !           780:     //
        !           781: 
        !           782:     while (AdapterAddresses[*AdapterCount] != 0) {
        !           783: 
        !           784:         //
        !           785:         // Check to see if adapter present in system.
        !           786:         //
        !           787: 
        !           788:         baseIoAddress = (PBASE_REGISTER)(ioSpace + AdapterAddresses[*AdapterCount]);
        !           789:         HwDeviceExtension->BaseIoAddress = baseIoAddress;
        !           790: 
        !           791:         //
        !           792:         // Update the adapter count.
        !           793:         //
        !           794: 
        !           795:         (*AdapterCount)++;
        !           796: 
        !           797:         portValue = ScsiPortReadPortUchar((PUCHAR)baseIoAddress);
        !           798: 
        !           799:         //
        !           800:         // Check for Adaptec adapter.
        !           801:         // The mask (0x29) are bits that may or may not be set.
        !           802:         // The bit 0x10 (IOP_SCSI_HBA_IDLE) should be set.
        !           803:         //
        !           804: 
        !           805:         if ((portValue & ~0x29) == IOP_SCSI_HBA_IDLE) {
        !           806: 
        !           807:             if (!AdaptecAdapter(HwDeviceExtension, AdapterAddresses[(*AdapterCount) - 1],
        !           808:                       (BOOLEAN)(ConfigInfo->AdapterInterfaceType == MicroChannel ? TRUE : FALSE))) {
        !           809:                 DebugPrint((1,"A154xDetermineInstalled: Clone command completed successfully - \n not our board;"));
        !           810:                 continue;
        !           811:             }
        !           812: 
        !           813:             //
        !           814:             // An adapter has been found.  Set the base address in the device
        !           815:             // extension, and request another call.
        !           816:             //
        !           817: 
        !           818:             HwDeviceExtension->BaseIoAddress = baseIoAddress;
        !           819:             *Again = TRUE;
        !           820: 
        !           821:             //
        !           822:             // Fill in the access array information.
        !           823:             //
        !           824: 
        !           825:             (*ConfigInfo->AccessRanges)[0].RangeStart =
        !           826:                 ScsiPortConvertUlongToPhysicalAddress(
        !           827:                     AdapterAddresses[*AdapterCount - 1]);
        !           828:             (*ConfigInfo->AccessRanges)[0].RangeLength = 4;
        !           829:             (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
        !           830: 
        !           831:             return(SP_RETURN_FOUND);
        !           832:         }
        !           833:     }
        !           834: 
        !           835:     //
        !           836:     // The entire table has been searched and no adapters have been found.
        !           837:     // There is no need to call again and the device base can now be freed.
        !           838:     // Clear the adapter count for the next bus.
        !           839:     //
        !           840: 
        !           841:     *Again = FALSE;
        !           842:     *(AdapterCount) = 0;
        !           843: 
        !           844:     ScsiPortFreeDeviceBase(
        !           845:         HwDeviceExtension,
        !           846:         ioSpace
        !           847:         );
        !           848: 
        !           849:      return(SP_RETURN_NOT_FOUND);
        !           850: 
        !           851: } // end A154xDetermineInstalled()
        !           852: 
        !           853: 
        !           854: BOOLEAN
        !           855: A154xHwInitialize(
        !           856:     IN PVOID HwDeviceExtension
        !           857:     )
        !           858: 
        !           859: /*++
        !           860: 
        !           861: Routine Description:
        !           862: 
        !           863:     This routine is called from ScsiPortInitialize
        !           864:     to set up the adapter so that it is ready to service requests.
        !           865: 
        !           866: Arguments:
        !           867: 
        !           868:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !           869: 
        !           870: Return Value:
        !           871: 
        !           872:     TRUE - if initialization successful.
        !           873:     FALSE - if initialization unsuccessful.
        !           874: 
        !           875: --*/
        !           876: 
        !           877: {
        !           878:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !           879:     PNONCACHED_EXTENSION noncachedExtension =
        !           880:         deviceExtension->NoncachedExtension;
        !           881:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !           882:     UCHAR status;
        !           883:     ULONG i;
        !           884: 
        !           885:     DebugPrint((2,"A154xHwInitialize: Reset aha154X and SCSI bus\n"));
        !           886: 
        !           887:     //
        !           888:     // Reset SCSI chip.
        !           889:     //
        !           890: 
        !           891:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET);
        !           892: 
        !           893:     //
        !           894:     // Inform the port driver that the bus has been reset.
        !           895:     //
        !           896: 
        !           897:     ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
        !           898: 
        !           899:     ScsiPortStallExecution(500*1000);
        !           900: 
        !           901:     //
        !           902:     // Wait up to 5000 microseconds for adapter to initialize.
        !           903:     //
        !           904: 
        !           905:     for (i = 0; i < 5000; i++) {
        !           906: 
        !           907:         ScsiPortStallExecution(1);
        !           908: 
        !           909:         status = ScsiPortReadPortUchar(&deviceExtension->BaseIoAddress->StatusRegister);
        !           910: 
        !           911:         if (status & IOP_SCSI_HBA_IDLE) {
        !           912:             break;
        !           913:         }
        !           914:     }
        !           915: 
        !           916:     //
        !           917:     // Check if reset failed or succeeded.
        !           918:     //
        !           919: 
        !           920:     if (!(status & IOP_SCSI_HBA_IDLE) || !(status & IOP_MAILBOX_INIT_REQUIRED)) {
        !           921:         DebugPrint((1,"A154xInitialize: Reset SCSI bus failed\n"));
        !           922:         return FALSE;
        !           923:     }
        !           924: 
        !           925:     //
        !           926:     // Unlock mailboxes in case the adapter is a 1540B with 1Gb support
        !           927:     // or 1540C with extended translation enabled.
        !           928:     //
        !           929: 
        !           930:     status = UnlockMailBoxes(deviceExtension);
        !           931:     (VOID) SpinForInterrupt(deviceExtension,FALSE);
        !           932: 
        !           933:     //
        !           934:     // Zero out mailboxes.
        !           935:     //
        !           936: 
        !           937:     for (i=0; i<MB_COUNT; i++) {
        !           938: 
        !           939:         PMBO mailboxOut;
        !           940:         PMBI mailboxIn;
        !           941: 
        !           942:         mailboxIn = &noncachedExtension->Mbi[i];
        !           943:         mailboxOut = &noncachedExtension->Mbo[i];
        !           944: 
        !           945:         mailboxOut->Command = mailboxIn->Status = 0;
        !           946:     }
        !           947: 
        !           948:     //
        !           949:     // Zero preivous indexes.
        !           950:     //
        !           951: 
        !           952:     deviceExtension->MboIndex = 0;
        !           953:     deviceExtension->MbiIndex = 0;
        !           954: 
        !           955:     DebugPrint((3,"A154xHwInitialize: Initialize mailbox\n"));
        !           956: 
        !           957:     if (!WriteCommandRegister(deviceExtension,AC_MAILBOX_INITIALIZATION, TRUE)) {
        !           958:         DebugPrint((1,"A154xHwInitialize: Couldn't initialize mailboxes\n"));
        !           959:         return FALSE;
        !           960:     }
        !           961: 
        !           962:     //
        !           963:     // Send Adapter number of mailbox locations.
        !           964:     //
        !           965: 
        !           966:     if (!WriteDataRegister(deviceExtension, MB_COUNT)) {
        !           967:         return FALSE;
        !           968:     }
        !           969: 
        !           970:     //
        !           971:     // Send the most significant byte of the mailbox physical address.
        !           972:     //
        !           973: 
        !           974:     if (!WriteDataRegister(deviceExtension,
        !           975:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte2)) {
        !           976:         return FALSE;
        !           977:     }
        !           978: 
        !           979:     //
        !           980:     // Send the middle byte of the mailbox physical address.
        !           981:     //
        !           982: 
        !           983:     if (!WriteDataRegister(deviceExtension,
        !           984:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte1)) {
        !           985:         return FALSE;
        !           986:     }
        !           987: 
        !           988:     //
        !           989:     // Send the least significant byte of the mailbox physical address.
        !           990:     //
        !           991: 
        !           992:     if (!WriteDataRegister(deviceExtension,
        !           993:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte0)) {
        !           994:         return FALSE;
        !           995:     }
        !           996: 
        !           997: #ifdef FORCE_DMA_SPEED
        !           998:     //
        !           999:     // Set the DMA transfer speed to 5.0 MB/second. This is because
        !          1000:     // faster transfer speeds cause data corruption on 486/33 machines.
        !          1001:     // This overrides the card jumper setting.
        !          1002:     //
        !          1003: 
        !          1004:     if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE)) {
        !          1005: 
        !          1006:         DebugPrint((1,"Can't set dma transfer speed\n"));
        !          1007: 
        !          1008:     } else if (!WriteDataRegister(deviceExtension, DMA_SPEED_50_MBS)) {
        !          1009: 
        !          1010:         DebugPrint((1,"Can't set dma transfer speed\n"));
        !          1011:     }
        !          1012: 
        !          1013:     //
        !          1014:     // Wait for interrupt.
        !          1015:     //
        !          1016: 
        !          1017:     if (!SpinForInterrupt(deviceExtension,TRUE)) {
        !          1018: 
        !          1019:         DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
        !          1020:         return TRUE;
        !          1021:     }
        !          1022: #endif
        !          1023: 
        !          1024:     //
        !          1025:     // Override default setting for bus on time. This makes floppy
        !          1026:     // drives work better with this adapter.
        !          1027:     //
        !          1028: 
        !          1029:     if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE)) {
        !          1030: 
        !          1031:         DebugPrint((1,"Can't set bus on time\n"));
        !          1032: 
        !          1033:     } else if (!WriteDataRegister(deviceExtension, deviceExtension->BusOnTime)) {
        !          1034: 
        !          1035:         DebugPrint((1,"Can't set bus on time\n"));
        !          1036:     }
        !          1037: 
        !          1038:     //
        !          1039:     // Wait for interrupt.
        !          1040:     //
        !          1041: 
        !          1042:     if (!SpinForInterrupt(deviceExtension,TRUE)) {
        !          1043: 
        !          1044:         DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
        !          1045:         return TRUE;
        !          1046:     }
        !          1047: 
        !          1048: 
        !          1049:     //
        !          1050:     // Override the default CCB timeout of 250 mseconds to 500 (0x1F4).
        !          1051:     //
        !          1052: 
        !          1053:     if (!WriteCommandRegister(deviceExtension, AC_SET_SELECTION_TIMEOUT, TRUE)) {
        !          1054:         DebugPrint((1,"A154xHwInitialize: Can't set CCB timeout\n"));
        !          1055:     }
        !          1056:     else {
        !          1057:         if (!WriteDataRegister(deviceExtension,0x01)) {
        !          1058:             DebugPrint((1,"A154xHwInitialize: Can't set timeout selection enable\n"));
        !          1059:         }
        !          1060: 
        !          1061:         if (!WriteDataRegister(deviceExtension,0x00)) {
        !          1062:             DebugPrint((1,"A154xHwInitialize: Can't set second byte\n"));
        !          1063:         }
        !          1064: 
        !          1065:         if (!WriteDataRegister(deviceExtension,0x01)) {
        !          1066:             DebugPrint((1,"A154xHwInitialize: Can't set MSB\n"));
        !          1067:         }
        !          1068: 
        !          1069:         if (!WriteDataRegister(deviceExtension,0xF4)) {
        !          1070:             DebugPrint((1,"A154xHwInitialize: Can't set LSB\n"));
        !          1071:         }
        !          1072:     }
        !          1073: 
        !          1074: 
        !          1075:     //
        !          1076:     // Wait for interrupt.
        !          1077:     //
        !          1078: 
        !          1079:     if (!SpinForInterrupt(deviceExtension,TRUE)) {
        !          1080: 
        !          1081:         DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
        !          1082:         return TRUE;
        !          1083:     }
        !          1084: 
        !          1085: 
        !          1086:     return TRUE;
        !          1087: 
        !          1088: } // end A154xHwInitialize()
        !          1089: 
        !          1090: 
        !          1091: BOOLEAN
        !          1092: A154xStartIo(
        !          1093:     IN PVOID HwDeviceExtension,
        !          1094:     IN PSCSI_REQUEST_BLOCK Srb
        !          1095:     )
        !          1096: 
        !          1097: /*++
        !          1098: 
        !          1099: Routine Description:
        !          1100: 
        !          1101:     This routine is called from the SCSI port driver synchronized
        !          1102:     with the kernel. The mailboxes are scanned for an empty one and
        !          1103:     the CCB is written to it. Then the doorbell is rung and the
        !          1104:     OS port driver is notified that the adapter can take
        !          1105:     another request, if any are available.
        !          1106: 
        !          1107: Arguments:
        !          1108: 
        !          1109:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !          1110:     Srb - IO request packet
        !          1111: 
        !          1112: Return Value:
        !          1113: 
        !          1114:     TRUE
        !          1115: 
        !          1116: --*/
        !          1117: 
        !          1118: {
        !          1119:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          1120:     PNONCACHED_EXTENSION noncachedExtension =
        !          1121:         deviceExtension->NoncachedExtension;
        !          1122:     PMBO mailboxOut;
        !          1123:     PCCB ccb;
        !          1124:     PHW_LU_EXTENSION luExtension;
        !          1125: 
        !          1126:     ULONG i = deviceExtension->MboIndex;
        !          1127:     ULONG physicalCcb;
        !          1128:     ULONG length;
        !          1129: 
        !          1130:     DebugPrint((3,"A154xStartIo: Enter routine\n"));
        !          1131: 
        !          1132:     //
        !          1133:     // Check if command is an ABORT request.
        !          1134:     //
        !          1135: 
        !          1136:     if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
        !          1137: 
        !          1138:         //
        !          1139:         // Verify that SRB to abort is still outstanding.
        !          1140:         //
        !          1141: 
        !          1142:         luExtension =
        !          1143:                 ScsiPortGetLogicalUnit(deviceExtension,
        !          1144:                                        Srb->PathId,
        !          1145:                                        Srb->TargetId,
        !          1146:                                        Srb->Lun);
        !          1147: 
        !          1148:         if (!luExtension->CurrentSrb) {
        !          1149: 
        !          1150:             DebugPrint((1, "A154xStartIo: SRB to abort already completed\n"));
        !          1151: 
        !          1152:             //
        !          1153:             // Complete abort SRB.
        !          1154:             //
        !          1155: 
        !          1156:             Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
        !          1157: 
        !          1158:             ScsiPortNotification(RequestComplete,
        !          1159:                                  deviceExtension,
        !          1160:                                  Srb);
        !          1161:             //
        !          1162:             // Adapter ready for next request.
        !          1163:             //
        !          1164: 
        !          1165:             ScsiPortNotification(NextRequest,
        !          1166:                                  deviceExtension,
        !          1167:                                  NULL);
        !          1168: 
        !          1169:             return TRUE;
        !          1170:         }
        !          1171: 
        !          1172:         //
        !          1173:         // Get CCB to abort.
        !          1174:         //
        !          1175: 
        !          1176:         ccb = Srb->NextSrb->SrbExtension;
        !          1177: 
        !          1178:         //
        !          1179:         // Set abort SRB for completion.
        !          1180:         //
        !          1181: 
        !          1182:         ccb->AbortSrb = Srb;
        !          1183: 
        !          1184:     } else {
        !          1185: 
        !          1186:         ccb = Srb->SrbExtension;
        !          1187: 
        !          1188:         //
        !          1189:         // Save SRB back pointer in CCB.
        !          1190:         //
        !          1191: 
        !          1192:         ccb->SrbAddress = Srb;
        !          1193:     }
        !          1194: 
        !          1195:     //
        !          1196:     // Get CCB physical address.
        !          1197:     //
        !          1198: 
        !          1199:     physicalCcb = ScsiPortConvertPhysicalAddressToUlong(
        !          1200:         ScsiPortGetPhysicalAddress(deviceExtension, NULL, ccb, &length));
        !          1201: 
        !          1202:     //
        !          1203:     // Find free mailboxOut.
        !          1204:     //
        !          1205: 
        !          1206:     do {
        !          1207: 
        !          1208:         mailboxOut = &noncachedExtension->Mbo[i % MB_COUNT];
        !          1209:         i++;
        !          1210: 
        !          1211:     } while (mailboxOut->Command != MBO_FREE);
        !          1212: 
        !          1213:     //
        !          1214:     // Save the next free location.
        !          1215:     //
        !          1216: 
        !          1217:     deviceExtension->MboIndex = (UCHAR) (i % MB_COUNT);
        !          1218: 
        !          1219:     DebugPrint((3,"A154xStartIo: MBO address %lx, Loop count = %d\n", mailboxOut, i));
        !          1220: 
        !          1221:     //
        !          1222:     // Write CCB to mailbox.
        !          1223:     //
        !          1224: 
        !          1225:     FOUR_TO_THREE(&mailboxOut->Address,
        !          1226:                   (PFOUR_BYTE)&physicalCcb);
        !          1227: 
        !          1228:     switch (Srb->Function) {
        !          1229: 
        !          1230:         case SRB_FUNCTION_ABORT_COMMAND:
        !          1231: 
        !          1232:             DebugPrint((1, "A154xStartIo: Abort request received\n"));
        !          1233: 
        !          1234:             //
        !          1235:             // BUGBUG: Race condition (what if CCB to be aborted
        !          1236:             //      completes after setting new SrbAddress?)
        !          1237:             //
        !          1238: 
        !          1239:             mailboxOut->Command = MBO_ABORT;
        !          1240: 
        !          1241:             break;
        !          1242: 
        !          1243:         case SRB_FUNCTION_RESET_BUS:
        !          1244: 
        !          1245:             //
        !          1246:             // Reset aha154x and SCSI bus.
        !          1247:             //
        !          1248: 
        !          1249:             DebugPrint((1, "A154xStartIo: Reset bus request received\n"));
        !          1250: 
        !          1251:             if (!A154xResetBus(
        !          1252:                 deviceExtension,
        !          1253:                 Srb->PathId
        !          1254:                 )) {
        !          1255: 
        !          1256:                 DebugPrint((1,"A154xStartIo: Reset bus failed\n"));
        !          1257: 
        !          1258:                 Srb->SrbStatus = SRB_STATUS_ERROR;
        !          1259: 
        !          1260:             } else {
        !          1261: 
        !          1262:                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
        !          1263:             }
        !          1264: 
        !          1265: 
        !          1266:             ScsiPortNotification(RequestComplete,
        !          1267:                          deviceExtension,
        !          1268:                          Srb);
        !          1269: 
        !          1270:             ScsiPortNotification(NextRequest,
        !          1271:                          deviceExtension,
        !          1272:                          NULL);
        !          1273: 
        !          1274:             return TRUE;
        !          1275: 
        !          1276:         case SRB_FUNCTION_EXECUTE_SCSI:
        !          1277: 
        !          1278:             //
        !          1279:             // Get logical unit extension.
        !          1280:             //
        !          1281: 
        !          1282:             luExtension =
        !          1283:                 ScsiPortGetLogicalUnit(deviceExtension,
        !          1284:                                        Srb->PathId,
        !          1285:                                        Srb->TargetId,
        !          1286:                                        Srb->Lun);
        !          1287: 
        !          1288:             //
        !          1289:             // Move SRB to logical unit extension.
        !          1290:             //
        !          1291: 
        !          1292:             luExtension->CurrentSrb = Srb;
        !          1293: 
        !          1294:             //
        !          1295:             // Build CCB.
        !          1296:             //
        !          1297: 
        !          1298:             BuildCcb(deviceExtension, Srb);
        !          1299: 
        !          1300:             mailboxOut->Command = MBO_START;
        !          1301: 
        !          1302:             break;
        !          1303: 
        !          1304:         case SRB_FUNCTION_RESET_DEVICE:
        !          1305: 
        !          1306:             DebugPrint((1,"A154xStartIo: Reset device not supported\n"));
        !          1307: 
        !          1308:             //
        !          1309:             // Drop through to default.
        !          1310:             //
        !          1311: 
        !          1312:         default:
        !          1313: 
        !          1314:             //
        !          1315:             // Set error, complete request
        !          1316:             // and signal ready for next request.
        !          1317:             //
        !          1318: 
        !          1319:             Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        !          1320: 
        !          1321:             ScsiPortNotification(RequestComplete,
        !          1322:                          deviceExtension,
        !          1323:                          Srb);
        !          1324: 
        !          1325:             ScsiPortNotification(NextRequest,
        !          1326:                          deviceExtension,
        !          1327:                          NULL);
        !          1328: 
        !          1329:             return TRUE;
        !          1330: 
        !          1331:     } // end switch
        !          1332: 
        !          1333:     //
        !          1334:     // Tell 154xb a CCB is available now.
        !          1335:     //
        !          1336: 
        !          1337:     if (!WriteCommandRegister(deviceExtension,AC_START_SCSI_COMMAND, FALSE)) {
        !          1338: 
        !          1339:         //
        !          1340:         // Let request time out and fail.
        !          1341:         //
        !          1342: 
        !          1343:         DebugPrint((1,"A154xStartIo: Can't write command to adapter\n"));
        !          1344: 
        !          1345:         deviceExtension->PendingRequest = TRUE;
        !          1346: 
        !          1347:     } else {
        !          1348: 
        !          1349:         //
        !          1350:         // Command(s) submitted. Clear pending request flag.
        !          1351:         //
        !          1352: 
        !          1353:         deviceExtension->PendingRequest = FALSE;
        !          1354: 
        !          1355:         //
        !          1356:         // Adapter ready for next request.
        !          1357:         //
        !          1358: 
        !          1359:         ScsiPortNotification(NextRequest,
        !          1360:                              deviceExtension,
        !          1361:                              NULL);
        !          1362:     }
        !          1363: 
        !          1364:     return TRUE;
        !          1365: 
        !          1366: } // end A154xStartIo()
        !          1367: 
        !          1368: 
        !          1369: BOOLEAN
        !          1370: A154xInterrupt(
        !          1371:     IN PVOID HwDeviceExtension
        !          1372:     )
        !          1373: 
        !          1374: /*++
        !          1375: 
        !          1376: Routine Description:
        !          1377: 
        !          1378:     This is the interrupt service routine for the adaptec 154x SCSI adapter.
        !          1379:     It reads the interrupt register to determine if the adapter is indeed
        !          1380:     the source of the interrupt and clears the interrupt at the device.
        !          1381:     If the adapter is interrupting because a mailbox is full, the CCB is
        !          1382:     retrieved to complete the request.
        !          1383: 
        !          1384: Arguments:
        !          1385: 
        !          1386:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !          1387: 
        !          1388: Return Value:
        !          1389: 
        !          1390:     TRUE if MailboxIn full
        !          1391: 
        !          1392: --*/
        !          1393: 
        !          1394: {
        !          1395:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          1396:     PNONCACHED_EXTENSION noncachedExtension =
        !          1397:         deviceExtension->NoncachedExtension;
        !          1398:     PCCB ccb;
        !          1399:     PSCSI_REQUEST_BLOCK srb;
        !          1400:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          1401:     PMBI mailboxIn;
        !          1402:     ULONG physicalCcb;
        !          1403:     PHW_LU_EXTENSION luExtension;
        !          1404:     ULONG residualBytes;
        !          1405:     ULONG i;
        !          1406: 
        !          1407:     UCHAR InterruptFlags;
        !          1408: 
        !          1409:     InterruptFlags = ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister);
        !          1410: 
        !          1411:     //
        !          1412:     // Determine cause of interrupt.
        !          1413:     //
        !          1414: 
        !          1415:     if (InterruptFlags & IOP_COMMAND_COMPLETE) {
        !          1416: 
        !          1417:         //
        !          1418:         // Adapter command completed.
        !          1419:         //
        !          1420: 
        !          1421:         DebugPrint((2,"A154xInterrupt: Adapter Command complete\n"));
        !          1422:         DebugPrint((3,"A154xInterrupt: Interrupt flags %x\n", InterruptFlags));
        !          1423:         DebugPrint((3,"A154xInterrupt: Status %x\n",
        !          1424:             ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)));
        !          1425: 
        !          1426:         //
        !          1427:         // Clear interrupt on adapter.
        !          1428:         //
        !          1429: 
        !          1430:         ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
        !          1431: 
        !          1432:         return TRUE;
        !          1433: 
        !          1434:     } else if (InterruptFlags & IOP_MBI_FULL) {
        !          1435: 
        !          1436:         DebugPrint((3,"A154xInterrupt: MBI Full\n"));
        !          1437: 
        !          1438:         //
        !          1439:         // Clear interrupt on adapter.
        !          1440:         //
        !          1441: 
        !          1442:         ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
        !          1443: 
        !          1444:     } else if (InterruptFlags & IOP_SCSI_RESET_DETECTED) {
        !          1445: 
        !          1446:         DebugPrint((1,"A154xInterrupt: SCSI Reset detected\n"));
        !          1447: 
        !          1448:         //
        !          1449:         // Clear interrupt on adapter.
        !          1450:         //
        !          1451: 
        !          1452:         ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
        !          1453: 
        !          1454:         //
        !          1455:         // Notify of reset.
        !          1456:         //
        !          1457: 
        !          1458:         ScsiPortNotification(ResetDetected,
        !          1459:                              deviceExtension,
        !          1460:                              NULL);
        !          1461: 
        !          1462:         return TRUE;
        !          1463: 
        !          1464:     } else {
        !          1465: 
        !          1466:         DebugPrint((4,"A154xInterrupt: Spurious interrupt\n"));
        !          1467: 
        !          1468:         return FALSE;
        !          1469:     }
        !          1470: 
        !          1471:     //
        !          1472:     // Determine which MailboxIn location contains the CCB.
        !          1473:     //
        !          1474: 
        !          1475:     for (i=0; i<MB_COUNT; i++) {
        !          1476: 
        !          1477:         mailboxIn = &noncachedExtension->Mbi[deviceExtension->MbiIndex];
        !          1478: 
        !          1479:         //
        !          1480:         // Look for a mailbox entry with a legitimate status.
        !          1481:         //
        !          1482: 
        !          1483:         if (mailboxIn->Status != MBI_FREE) {
        !          1484: 
        !          1485:             //
        !          1486:             // Point to the next in box.
        !          1487:             //
        !          1488: 
        !          1489:             deviceExtension->MbiIndex = (deviceExtension->MbiIndex + 1) % MB_COUNT;
        !          1490: 
        !          1491:             //
        !          1492:             // MBI found. Convert CCB to big endian.
        !          1493:             //
        !          1494: 
        !          1495:             THREE_TO_FOUR((PFOUR_BYTE)&physicalCcb,
        !          1496:                 &mailboxIn->Address);
        !          1497: 
        !          1498:             DebugPrint((3, "A154xInterrupt: Physical CCB %lx\n", physicalCcb));
        !          1499: 
        !          1500:             //
        !          1501:             // Check if physical CCB is zero.
        !          1502:             // This is done to cover for hardware errors.
        !          1503:             //
        !          1504: 
        !          1505:             if (!physicalCcb) {
        !          1506: 
        !          1507:                 DebugPrint((1,"A154xInterrupt: Physical CCB address is 0\n"));
        !          1508: 
        !          1509:                 //
        !          1510:                 // Indicate MBI is available.
        !          1511:                 //
        !          1512: 
        !          1513:                 mailboxIn->Status = MBI_FREE;
        !          1514: 
        !          1515:                 continue;
        !          1516:             }
        !          1517: 
        !          1518:             //
        !          1519:             // Convert Physical CCB to Virtual.
        !          1520:             //
        !          1521: 
        !          1522:             ccb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalCcb));
        !          1523: 
        !          1524: 
        !          1525:             DebugPrint((3, "A154xInterrupt: Virtual CCB %lx\n", ccb));
        !          1526: 
        !          1527:             //
        !          1528:             // Make sure the virtual address was found.
        !          1529:             //
        !          1530: 
        !          1531:             if (ccb == NULL) {
        !          1532: 
        !          1533:                 //
        !          1534:                 // A bad physcial address was return by the adapter.
        !          1535:                 // Log it as an error.
        !          1536:                 //
        !          1537: 
        !          1538:                 ScsiPortLogError(
        !          1539:                     HwDeviceExtension,
        !          1540:                     NULL,
        !          1541:                     0,
        !          1542:                     deviceExtension->HostTargetId,
        !          1543:                     0,
        !          1544:                     SP_INTERNAL_ADAPTER_ERROR,
        !          1545:                     5 << 8
        !          1546:                     );
        !          1547: 
        !          1548:                 //
        !          1549:                 // Indicate MBI is available.
        !          1550:                 //
        !          1551: 
        !          1552:                 mailboxIn->Status = MBI_FREE;
        !          1553: 
        !          1554:                 continue;
        !          1555:             }
        !          1556: 
        !          1557:             //
        !          1558:             // Get SRB from CCB.
        !          1559:             //
        !          1560: 
        !          1561:             srb = ccb->SrbAddress;
        !          1562: 
        !          1563:             //
        !          1564:             // Get logical unit extension.
        !          1565:             //
        !          1566: 
        !          1567:             luExtension =
        !          1568:                 ScsiPortGetLogicalUnit(deviceExtension,
        !          1569:                                        srb->PathId,
        !          1570:                                        srb->TargetId,
        !          1571:                                        srb->Lun);
        !          1572: 
        !          1573:             //
        !          1574:             // Make sure the luExtension was found and it has a current request.
        !          1575:             //
        !          1576: 
        !          1577:             if (luExtension == NULL || (luExtension->CurrentSrb == NULL &&
        !          1578:                 mailboxIn->Status != MBI_NOT_FOUND)) {
        !          1579: 
        !          1580:                 //
        !          1581:                 // A bad physcial address was return by the adapter.
        !          1582:                 // Log it as an error.
        !          1583:                 //
        !          1584: 
        !          1585:                 ScsiPortLogError(
        !          1586:                     HwDeviceExtension,
        !          1587:                     NULL,
        !          1588:                     0,
        !          1589:                     deviceExtension->HostTargetId,
        !          1590:                     0,
        !          1591:                     SP_INTERNAL_ADAPTER_ERROR,
        !          1592:                     (6 << 8) | mailboxIn->Status
        !          1593:                     );
        !          1594: 
        !          1595:                 //
        !          1596:                 // Indicate MBI is available.
        !          1597:                 //
        !          1598: 
        !          1599:                 mailboxIn->Status = MBI_FREE;
        !          1600: 
        !          1601:                 continue;
        !          1602:             }
        !          1603: 
        !          1604:             //
        !          1605:             // Check MBI status.
        !          1606:             //
        !          1607: 
        !          1608:             switch (mailboxIn->Status) {
        !          1609: 
        !          1610:             case MBI_SUCCESS:
        !          1611: 
        !          1612:                 //
        !          1613:                 // Update SRB with number of bytes transferred.
        !          1614:                 //
        !          1615: 
        !          1616:                 THREE_TO_FOUR((PFOUR_BYTE)&residualBytes,
        !          1617:                               &ccb->DataLength);
        !          1618: 
        !          1619:                 if (residualBytes != 0) {
        !          1620: 
        !          1621:                     DebugPrint((1, "A154xInterrupt: Underrun occured. Request length = %lx, Residual length = %lx\n", srb->DataTransferLength, residualBytes));
        !          1622:                     srb->DataTransferLength -= residualBytes;
        !          1623:                     srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
        !          1624: 
        !          1625:                 } else {
        !          1626: 
        !          1627:                     srb->SrbStatus = SRB_STATUS_SUCCESS;
        !          1628: 
        !          1629:                 }
        !          1630: 
        !          1631:                 luExtension->CurrentSrb = NULL;
        !          1632: 
        !          1633:                 break;
        !          1634: 
        !          1635:             case MBI_NOT_FOUND:
        !          1636: 
        !          1637:                 DebugPrint((1, "A154xInterrupt: CCB abort failed %lx\n", ccb));
        !          1638: 
        !          1639:                 srb = ccb->AbortSrb;
        !          1640: 
        !          1641:                 srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
        !          1642: 
        !          1643:                 //
        !          1644:                 // Check if SRB still outstanding.
        !          1645:                 //
        !          1646: 
        !          1647:                 if (luExtension->CurrentSrb) {
        !          1648: 
        !          1649:                     //
        !          1650:                     // Complete this SRB.
        !          1651:                     //
        !          1652: 
        !          1653:                     luExtension->CurrentSrb->SrbStatus = SRB_STATUS_TIMEOUT;
        !          1654: 
        !          1655:                     ScsiPortNotification(RequestComplete,
        !          1656:                                          deviceExtension,
        !          1657:                                          luExtension->CurrentSrb);
        !          1658: 
        !          1659:                     luExtension->CurrentSrb = NULL;
        !          1660:                 }
        !          1661: 
        !          1662:                 break;
        !          1663: 
        !          1664:             case MBI_ABORT:
        !          1665: 
        !          1666:                 DebugPrint((1, "A154xInterrupt: CCB aborted\n"));
        !          1667: 
        !          1668:                 //
        !          1669:                 // Update target status in aborted SRB.
        !          1670:                 //
        !          1671: 
        !          1672:                 srb->SrbStatus = SRB_STATUS_ABORTED;
        !          1673: 
        !          1674:                 //
        !          1675:                 // Call notification routine for the aborted SRB.
        !          1676:                 //
        !          1677: 
        !          1678:                 ScsiPortNotification(RequestComplete,
        !          1679:                                      deviceExtension,
        !          1680:                                      srb);
        !          1681: 
        !          1682:                 luExtension->CurrentSrb = NULL;
        !          1683: 
        !          1684:                 //
        !          1685:                 // Get the abort SRB from CCB.
        !          1686:                 //
        !          1687: 
        !          1688:                 srb = ccb->AbortSrb;
        !          1689: 
        !          1690:                 //
        !          1691:                 // Set status for completing abort request.
        !          1692:                 //
        !          1693: 
        !          1694:                 srb->SrbStatus = SRB_STATUS_SUCCESS;
        !          1695: 
        !          1696:                 break;
        !          1697: 
        !          1698:             case MBI_ERROR:
        !          1699: 
        !          1700:                 DebugPrint((2, "A154xInterrupt: Error occurred\n"));
        !          1701: 
        !          1702:                 srb->SrbStatus = MapError(deviceExtension, srb, ccb);
        !          1703: 
        !          1704:                 //
        !          1705:                 // Check if ABORT command.
        !          1706:                 //
        !          1707: 
        !          1708:                 if (srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
        !          1709: 
        !          1710:                     //
        !          1711:                     // Check if SRB still outstanding.
        !          1712:                     //
        !          1713: 
        !          1714:                     if (luExtension->CurrentSrb) {
        !          1715: 
        !          1716:                         //
        !          1717:                         // Complete this SRB.
        !          1718:                         //
        !          1719: 
        !          1720:                         luExtension->CurrentSrb->SrbStatus = SRB_STATUS_TIMEOUT;
        !          1721: 
        !          1722:                         ScsiPortNotification(RequestComplete,
        !          1723:                                              deviceExtension,
        !          1724:                                              luExtension->CurrentSrb);
        !          1725: 
        !          1726:                     }
        !          1727: 
        !          1728:                     DebugPrint((1,"A154xInterrupt: Abort command failed\n"));
        !          1729:                 }
        !          1730: 
        !          1731:                 luExtension->CurrentSrb = NULL;
        !          1732: 
        !          1733:                 break;
        !          1734: 
        !          1735:             default:
        !          1736: 
        !          1737:                 //
        !          1738:                 // Log the error.
        !          1739:                 //
        !          1740: 
        !          1741:                 ScsiPortLogError(
        !          1742:                     HwDeviceExtension,
        !          1743:                     NULL,
        !          1744:                     0,
        !          1745:                     deviceExtension->HostTargetId,
        !          1746:                     0,
        !          1747:                     SP_INTERNAL_ADAPTER_ERROR,
        !          1748:                     (1 << 8) | mailboxIn->Status
        !          1749:                     );
        !          1750: 
        !          1751:                 DebugPrint((1, "A154xInterrupt: Unrecognized mailbox status\n"));
        !          1752: 
        !          1753:                 mailboxIn->Status = MBI_FREE;
        !          1754: 
        !          1755:                 continue;
        !          1756: 
        !          1757:             } // end switch
        !          1758: 
        !          1759:             //
        !          1760:             // Indicate MBI is available.
        !          1761:             //
        !          1762: 
        !          1763:             mailboxIn->Status = MBI_FREE;
        !          1764: 
        !          1765:             DebugPrint((2, "A154xInterrupt: SCSI Status %x\n", srb->ScsiStatus));
        !          1766: 
        !          1767:             DebugPrint((2, "A154xInterrupt: Adapter Status %x\n", ccb->HostStatus));
        !          1768: 
        !          1769:             //
        !          1770:             // Update target status in SRB.
        !          1771:             //
        !          1772: 
        !          1773:             srb->ScsiStatus = ccb->TargetStatus;
        !          1774: 
        !          1775:             //
        !          1776:             // Signal request completion.
        !          1777:             //
        !          1778: 
        !          1779:             ScsiPortNotification(RequestComplete,
        !          1780:                             (PVOID)deviceExtension,
        !          1781:                             srb);
        !          1782: 
        !          1783:         } else {
        !          1784: 
        !          1785:             break;
        !          1786: 
        !          1787:         } // end if ((mailboxIn->Status == MBI_SUCCESS ...
        !          1788: 
        !          1789:     } // end for (i=0; i<MB_COUNT; i++) {
        !          1790: 
        !          1791:     if (deviceExtension->PendingRequest) {
        !          1792: 
        !          1793:         //
        !          1794:         // The last write command to the adapter failed.  Try and start it now.
        !          1795:         //
        !          1796: 
        !          1797:         deviceExtension->PendingRequest = FALSE;
        !          1798: 
        !          1799:         //
        !          1800:         // Tell 154xb a CCB is available now.
        !          1801:         //
        !          1802: 
        !          1803:         if (!WriteCommandRegister(deviceExtension,AC_START_SCSI_COMMAND, FALSE)) {
        !          1804: 
        !          1805:             //
        !          1806:             // Let request time out and fail.
        !          1807:             //
        !          1808: 
        !          1809:             DebugPrint((1,"A154xInterrupt: Can't write command to adapter\n"));
        !          1810: 
        !          1811:             deviceExtension->PendingRequest = TRUE;
        !          1812: 
        !          1813:         } else {
        !          1814: 
        !          1815:             //
        !          1816:             // Adapter ready for next request.
        !          1817:             //
        !          1818: 
        !          1819:             ScsiPortNotification(NextRequest,
        !          1820:                                  deviceExtension,
        !          1821:                                  NULL);
        !          1822:         }
        !          1823:     }
        !          1824: 
        !          1825:     return TRUE;
        !          1826: 
        !          1827: } // end A154xInterrupt()
        !          1828: 
        !          1829: 
        !          1830: VOID
        !          1831: BuildCcb(
        !          1832:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          1833:     IN PSCSI_REQUEST_BLOCK Srb
        !          1834:     )
        !          1835: 
        !          1836: /*++
        !          1837: 
        !          1838: Routine Description:
        !          1839: 
        !          1840:     Build CCB for 154x.
        !          1841: 
        !          1842: Arguments:
        !          1843: 
        !          1844:     DeviceExtenson
        !          1845:     SRB
        !          1846: 
        !          1847: Return Value:
        !          1848: 
        !          1849:     Nothing.
        !          1850: 
        !          1851: --*/
        !          1852: 
        !          1853: {
        !          1854:     PCCB ccb = Srb->SrbExtension;
        !          1855: 
        !          1856:     DebugPrint((3,"BuildCcb: Enter routine\n"));
        !          1857: 
        !          1858:     //
        !          1859:     // Set target id and LUN.
        !          1860:     //
        !          1861: 
        !          1862:     ccb->ControlByte = (UCHAR)(Srb->TargetId << 5) | Srb->Lun;
        !          1863: 
        !          1864:     //
        !          1865:     // Set CCB Operation Code.
        !          1866:     //
        !          1867: 
        !          1868: 
        !          1869:     ccb->OperationCode = SCATTER_GATHER_COMMAND;
        !          1870: 
        !          1871:     //
        !          1872:     // Set transfer direction bit.
        !          1873:     //
        !          1874: 
        !          1875:     if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
        !          1876: 
        !          1877:        //
        !          1878:        // Check if both direction bits are set. This is an
        !          1879:        // indication that the direction has not been specified.
        !          1880:        //
        !          1881: 
        !          1882:        if (!(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
        !          1883:            ccb->ControlByte |= CCB_DATA_XFER_OUT;
        !          1884:        }
        !          1885: 
        !          1886:     } else if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
        !          1887:        ccb->ControlByte |= CCB_DATA_XFER_IN;
        !          1888:     } else {
        !          1889: 
        !          1890:        //
        !          1891:        // if no data transfer, we must set ccb command to to INITIATOR
        !          1892:        // instead of SCATTER_GATHER and zero ccb data pointer and length.
        !          1893:        //
        !          1894: 
        !          1895:        ccb->OperationCode = SCSI_INITIATOR_COMMAND;
        !          1896:        ccb->DataPointer.Msb = 0;
        !          1897:        ccb->DataPointer.Mid = 0;
        !          1898:        ccb->DataPointer.Lsb = 0;
        !          1899:        ccb->DataLength.Msb = 0;
        !          1900:        ccb->DataLength.Mid = 0;
        !          1901:        ccb->DataLength.Lsb = 0;
        !          1902:     }
        !          1903: 
        !          1904:     //
        !          1905:     // 01h disables auto request sense.
        !          1906:     //
        !          1907: 
        !          1908:     ccb->RequestSenseLength = 1;
        !          1909: 
        !          1910:     //
        !          1911:     // Set CDB length and copy to CCB.
        !          1912:     //
        !          1913: 
        !          1914:     ccb->CdbLength = (UCHAR)Srb->CdbLength;
        !          1915: 
        !          1916:     ScsiPortMoveMemory(ccb->Cdb, Srb->Cdb, ccb->CdbLength);
        !          1917: 
        !          1918:     //
        !          1919:     // Set reserved bytes to zero.
        !          1920:     //
        !          1921: 
        !          1922:     ccb->Reserved[0] = 0;
        !          1923:     ccb->Reserved[1] = 0;
        !          1924: 
        !          1925:     ccb->LinkIdentifier = 0;
        !          1926: 
        !          1927:     //
        !          1928:     // Zero link pointer.
        !          1929:     //
        !          1930: 
        !          1931:     ccb->LinkPointer.Msb = 0;
        !          1932:     ccb->LinkPointer.Lsb = 0;
        !          1933:     ccb->LinkPointer.Mid = 0;
        !          1934: 
        !          1935:     //
        !          1936:     // Build SDL in CCB if data transfer.
        !          1937:     //
        !          1938: 
        !          1939:     if (Srb->DataTransferLength > 0) {
        !          1940:         BuildSdl(DeviceExtension, Srb);
        !          1941:     }
        !          1942: 
        !          1943:     //
        !          1944:     // Move 0xff to Target Status to indicate
        !          1945:     // CCB has not completed.
        !          1946:     //
        !          1947: 
        !          1948:     ccb->TargetStatus = 0xFF;
        !          1949: 
        !          1950:     return;
        !          1951: 
        !          1952: } // end BuildCcb()
        !          1953: 
        !          1954: 
        !          1955: VOID
        !          1956: BuildSdl(
        !          1957:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          1958:     IN PSCSI_REQUEST_BLOCK Srb
        !          1959:     )
        !          1960: 
        !          1961: /*++
        !          1962: 
        !          1963: Routine Description:
        !          1964: 
        !          1965:     This routine builds a scatter/gather descriptor list for the CCB.
        !          1966: 
        !          1967: Arguments:
        !          1968: 
        !          1969:     DeviceExtension
        !          1970:     Srb
        !          1971: 
        !          1972: Return Value:
        !          1973: 
        !          1974:     None
        !          1975: 
        !          1976: --*/
        !          1977: 
        !          1978: {
        !          1979:     PVOID dataPointer = Srb->DataBuffer;
        !          1980:     ULONG bytesLeft = Srb->DataTransferLength;
        !          1981:     PCCB ccb = Srb->SrbExtension;
        !          1982:     PSDL sdl = &ccb->Sdl;
        !          1983:     ULONG physicalSdl;
        !          1984:     ULONG physicalAddress;
        !          1985:     ULONG length;
        !          1986:     ULONG four;
        !          1987:     PTHREE_BYTE three;
        !          1988:     ULONG i = 0;
        !          1989: 
        !          1990:     DebugPrint((3,"BuildSdl: Enter routine\n"));
        !          1991: 
        !          1992:     //
        !          1993:     // Get physical SDL address.
        !          1994:     //
        !          1995: 
        !          1996:     physicalSdl = ScsiPortConvertPhysicalAddressToUlong(
        !          1997:         ScsiPortGetPhysicalAddress(DeviceExtension, NULL,
        !          1998:         sdl, &length));
        !          1999: 
        !          2000:     //
        !          2001:     // Create SDL segment descriptors.
        !          2002:     //
        !          2003: 
        !          2004:     do {
        !          2005: 
        !          2006:         DebugPrint((3, "BuildSdl: Data buffer %lx\n", dataPointer));
        !          2007: 
        !          2008:         //
        !          2009:         // Get physical address and length of contiguous
        !          2010:         // physical buffer.
        !          2011:         //
        !          2012: 
        !          2013:         physicalAddress =
        !          2014:             ScsiPortConvertPhysicalAddressToUlong(
        !          2015:                 ScsiPortGetPhysicalAddress(DeviceExtension,
        !          2016:                                        Srb,
        !          2017:                                        dataPointer,
        !          2018:                                        &length));
        !          2019: 
        !          2020:         DebugPrint((3, "BuildSdl: Physical address %lx\n", physicalAddress));
        !          2021:         DebugPrint((3, "BuildSdl: Data length %lx\n", length));
        !          2022:         DebugPrint((3, "BuildSdl: Bytes left %lx\n", bytesLeft));
        !          2023: 
        !          2024:         //
        !          2025:         // If length of physical memory is more
        !          2026:         // than bytes left in transfer, use bytes
        !          2027:         // left as final length.
        !          2028:         //
        !          2029: 
        !          2030:         if  (length > bytesLeft) {
        !          2031:             length = bytesLeft;
        !          2032:         }
        !          2033: 
        !          2034:         //
        !          2035:         // Convert length to 3-byte big endian format.
        !          2036:         //
        !          2037: 
        !          2038:         four = length;
        !          2039:         three = &sdl->Sgd[i].Length;
        !          2040:         FOUR_TO_THREE(three, (PFOUR_BYTE)&four);
        !          2041: 
        !          2042:         //
        !          2043:         // Convert physical address to 3-byte big endian format.
        !          2044:         //
        !          2045: 
        !          2046:         four = (ULONG)physicalAddress;
        !          2047:         three = &sdl->Sgd[i].Address;
        !          2048:         FOUR_TO_THREE(three, (PFOUR_BYTE)&four);
        !          2049:         i++;
        !          2050: 
        !          2051:         //
        !          2052:         // Adjust counts.
        !          2053:         //
        !          2054: 
        !          2055:         dataPointer = (PUCHAR)dataPointer + length;
        !          2056:         bytesLeft -= length;
        !          2057: 
        !          2058:     } while (bytesLeft);
        !          2059: 
        !          2060:     //
        !          2061:     // Write SDL length to CCB.
        !          2062:     //
        !          2063: 
        !          2064:     four = i * sizeof(SGD);
        !          2065:     three = &ccb->DataLength;
        !          2066:     FOUR_TO_THREE(three, (PFOUR_BYTE)&four);
        !          2067: 
        !          2068:     DebugPrint((3,"BuildSdl: SDL length is %d\n", four));
        !          2069: 
        !          2070:     //
        !          2071:     // Write SDL address to CCB.
        !          2072:     //
        !          2073: 
        !          2074:     FOUR_TO_THREE(&ccb->DataPointer,
        !          2075:         (PFOUR_BYTE)&physicalSdl);
        !          2076: 
        !          2077:     DebugPrint((3,"BuildSdl: SDL address is %lx\n", sdl));
        !          2078: 
        !          2079:     DebugPrint((3,"BuildSdl: CCB address is %lx\n", ccb));
        !          2080: 
        !          2081:     return;
        !          2082: 
        !          2083: } // end BuildSdl()
        !          2084: 
        !          2085: 
        !          2086: BOOLEAN
        !          2087: A154xResetBus(
        !          2088:     IN PVOID HwDeviceExtension,
        !          2089:     IN ULONG PathId
        !          2090:     )
        !          2091: 
        !          2092: /*++
        !          2093: 
        !          2094: Routine Description:
        !          2095: 
        !          2096:     Reset Adaptec 154X SCSI adapter and SCSI bus.
        !          2097:     Initialize adapter mailbox.
        !          2098: 
        !          2099: Arguments:
        !          2100: 
        !          2101:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !          2102: 
        !          2103: Return Value:
        !          2104: 
        !          2105:     Nothing.
        !          2106: 
        !          2107: 
        !          2108: --*/
        !          2109: 
        !          2110: {
        !          2111:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          2112:     PNONCACHED_EXTENSION noncachedExtension =
        !          2113:         deviceExtension->NoncachedExtension;
        !          2114:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          2115:     UCHAR status;
        !          2116:     ULONG i;
        !          2117: 
        !          2118:     DebugPrint((2,"ResetBus: Reset aha154X and SCSI bus\n"));
        !          2119: 
        !          2120:     //
        !          2121:     // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
        !          2122:     //
        !          2123: 
        !          2124:     ScsiPortCompleteRequest(deviceExtension,
        !          2125:                             (UCHAR) PathId,
        !          2126:                             0xFF,
        !          2127:                             0xFF,
        !          2128:                             (ULONG) SRB_STATUS_BUS_RESET);
        !          2129: 
        !          2130:     //
        !          2131:     // Reset SCSI chip.
        !          2132:     //
        !          2133: 
        !          2134:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET);
        !          2135: 
        !          2136:     ScsiPortStallExecution(500 * 1000);
        !          2137: 
        !          2138:     //
        !          2139:     // Wait up to 5000 microseconds for adapter to initialize.
        !          2140:     //
        !          2141: 
        !          2142:     for (i = 0; i < 5000; i++) {
        !          2143: 
        !          2144:         ScsiPortStallExecution(1);
        !          2145: 
        !          2146:         status = ScsiPortReadPortUchar(&deviceExtension->BaseIoAddress->StatusRegister);
        !          2147: 
        !          2148:         if (status & IOP_SCSI_HBA_IDLE) {
        !          2149:             break;
        !          2150:         }
        !          2151:     }
        !          2152: 
        !          2153:     //
        !          2154:     // Zero out mailboxes.
        !          2155:     //
        !          2156: 
        !          2157:     for (i=0; i<MB_COUNT; i++) {
        !          2158: 
        !          2159:         PMBO mailboxOut;
        !          2160:         PMBI mailboxIn;
        !          2161: 
        !          2162:         mailboxIn = &noncachedExtension->Mbi[i];
        !          2163:         mailboxOut = &noncachedExtension->Mbo[i];
        !          2164: 
        !          2165:         mailboxOut->Command = mailboxIn->Status = 0;
        !          2166:     }
        !          2167: 
        !          2168:     //
        !          2169:     // Zero previous indexes.
        !          2170:     //
        !          2171: 
        !          2172:     deviceExtension->MboIndex = 0;
        !          2173:     deviceExtension->MbiIndex = 0;
        !          2174: 
        !          2175:     if (deviceExtension->PendingRequest) {
        !          2176: 
        !          2177:         deviceExtension->PendingRequest = FALSE;
        !          2178: 
        !          2179:         //
        !          2180:         // Adapter ready for next request.
        !          2181:         //
        !          2182: 
        !          2183:         ScsiPortNotification(NextRequest,
        !          2184:                              deviceExtension,
        !          2185:                              NULL);
        !          2186:     }
        !          2187: 
        !          2188:     if (!(status & IOP_SCSI_HBA_IDLE)) {
        !          2189:         return(FALSE);
        !          2190:     }
        !          2191: 
        !          2192:     //
        !          2193:     // Unlock mailboxes in case the adapter is a 1540B with 1Gb support
        !          2194:     // or 1540C with extended translation enabled.  Maiboxes cannot be
        !          2195:     // initialized until unlock code is sent.
        !          2196: 
        !          2197:     status = UnlockMailBoxes(deviceExtension);
        !          2198: 
        !          2199:     if (!SpinForInterrupt(deviceExtension,FALSE)) {
        !          2200:         DebugPrint((1,"A154xResetBus: Failed to unlock mailboxes\n"));
        !          2201:         return FALSE;
        !          2202:     }
        !          2203: 
        !          2204: 
        !          2205:     DebugPrint((3,"ResetBus: Initialize mailbox\n"));
        !          2206: 
        !          2207:     if (!WriteCommandRegister(deviceExtension,AC_MAILBOX_INITIALIZATION, TRUE)) {
        !          2208:         DebugPrint((1,"A154xResetBus: Couldn't initialize mailboxes\n"));
        !          2209:         return FALSE;
        !          2210:     }
        !          2211: 
        !          2212:     //
        !          2213:     // Send Adapter number of mailbox locations.
        !          2214:     //
        !          2215: 
        !          2216:     if (!WriteDataRegister(deviceExtension,MB_COUNT)) {
        !          2217:         return FALSE;
        !          2218:     }
        !          2219: 
        !          2220:     //
        !          2221:     // Send the most significant byte of the mailbox physical address.
        !          2222:     //
        !          2223: 
        !          2224:     if (!WriteDataRegister(deviceExtension,
        !          2225:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte2)) {
        !          2226:         return FALSE;
        !          2227:     }
        !          2228: 
        !          2229:     //
        !          2230:     // Send the middle byte of the mailbox physical address.
        !          2231:     //
        !          2232: 
        !          2233:     if (!WriteDataRegister(deviceExtension,
        !          2234:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte1)) {
        !          2235:         return FALSE;
        !          2236:     }
        !          2237: 
        !          2238:     //
        !          2239:     // Send the least significant byte of the mailbox physical address.
        !          2240:     //
        !          2241: 
        !          2242:     if (!WriteDataRegister(deviceExtension,
        !          2243:         ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte0)) {
        !          2244:         return FALSE;
        !          2245:     }
        !          2246: 
        !          2247: #ifdef FORCE_DMA_SPEED
        !          2248:     //
        !          2249:     // Set the DMA transfer speed to 5.0 MB/second. This is because
        !          2250:     // faster transfer speeds cause data corruption on 486/33 machines.
        !          2251:     // This overrides the card jumper setting.
        !          2252:     //
        !          2253: 
        !          2254:     if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE)) {
        !          2255: 
        !          2256:         DebugPrint((1,"Can't set dma transfer speed\n"));
        !          2257: 
        !          2258:     } else if (!WriteDataRegister(deviceExtension, DMA_SPEED_50_MBS)) {
        !          2259: 
        !          2260:         DebugPrint((1,"Can't set dma transfer speed\n"));
        !          2261:     }
        !          2262: 
        !          2263:     //
        !          2264:     // Wait for interrupt.
        !          2265:     //
        !          2266: 
        !          2267:     if (!SpinForInterrupt(deviceExtension,TRUE)) {
        !          2268: 
        !          2269:         DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
        !          2270:     }
        !          2271: #endif
        !          2272: 
        !          2273:     //
        !          2274:     // Override default setting for bus on time. This makes floppy
        !          2275:     // drives work better with this adapter.
        !          2276:     //
        !          2277: 
        !          2278:     if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE)) {
        !          2279: 
        !          2280:         DebugPrint((1,"Can't set bus on time\n"));
        !          2281: 
        !          2282:     } else if (!WriteDataRegister(deviceExtension, 0x07)) {
        !          2283: 
        !          2284:         DebugPrint((1,"Can't set bus on time\n"));
        !          2285:     }
        !          2286: 
        !          2287:     //
        !          2288:     // Wait for interrupt.
        !          2289:     //
        !          2290: 
        !          2291:     if (!SpinForInterrupt(deviceExtension,TRUE)) {
        !          2292: 
        !          2293:         DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
        !          2294:     }
        !          2295: 
        !          2296:     return TRUE;
        !          2297: 
        !          2298: } // end A154xResetBus()
        !          2299: 
        !          2300: 
        !          2301: UCHAR
        !          2302: MapError(
        !          2303:     IN PVOID HwDeviceExtension,
        !          2304:     IN PSCSI_REQUEST_BLOCK Srb,
        !          2305:     IN PCCB Ccb
        !          2306:     )
        !          2307: 
        !          2308: /*++
        !          2309: 
        !          2310: Routine Description:
        !          2311: 
        !          2312:     Translate A154x error to SRB error, and log an error if necessary.
        !          2313: 
        !          2314: Arguments:
        !          2315: 
        !          2316:     HwDeviceExtension - The hardware device extension.
        !          2317: 
        !          2318:     Srb - The failing Srb.
        !          2319: 
        !          2320:     Ccb - Command Control Block contains error.
        !          2321: 
        !          2322: Return Value:
        !          2323: 
        !          2324:     SRB Error
        !          2325: 
        !          2326: --*/
        !          2327: 
        !          2328: {
        !          2329:     UCHAR status;
        !          2330:     ULONG logError;
        !          2331:     ULONG residualBytes;
        !          2332: 
        !          2333:     switch (Ccb->HostStatus) {
        !          2334: 
        !          2335:         case CCB_COMPLETE:
        !          2336:         case CCB_SELECTION_TIMEOUT:
        !          2337: 
        !          2338:             if (Ccb->TargetStatus == SCSISTAT_CHECK_CONDITION) {
        !          2339: 
        !          2340:                 //
        !          2341:                 // Update SRB with number of bytes transferred.
        !          2342:                 //
        !          2343: 
        !          2344:                 THREE_TO_FOUR((PFOUR_BYTE)&residualBytes,
        !          2345:                               &Ccb->DataLength);
        !          2346: 
        !          2347:                 DebugPrint((1, "Aha154x MapError: Underrun occured. Request length = %lx, Residual length = %lx\n", Srb->DataTransferLength, residualBytes));
        !          2348:                 Srb->DataTransferLength -= residualBytes;
        !          2349:             }
        !          2350: 
        !          2351:             return SRB_STATUS_ERROR;
        !          2352: 
        !          2353:         case CCB_DATA_OVER_UNDER_RUN:
        !          2354:             THREE_TO_FOUR((PFOUR_BYTE)&residualBytes,
        !          2355:                          &Ccb->DataLength);
        !          2356:            if (residualBytes) {
        !          2357:                Srb->DataTransferLength -= residualBytes;
        !          2358:            } else {
        !          2359:                logError = SP_PROTOCOL_ERROR;
        !          2360:            }
        !          2361:             status = SRB_STATUS_DATA_OVERRUN;
        !          2362:             break;
        !          2363: 
        !          2364:         case CCB_UNEXPECTED_BUS_FREE:
        !          2365:             status = SRB_STATUS_UNEXPECTED_BUS_FREE;
        !          2366:             logError = SP_UNEXPECTED_DISCONNECT;
        !          2367:             break;
        !          2368: 
        !          2369:         case CCB_PHASE_SEQUENCE_FAIL:
        !          2370:         case CCB_INVALID_DIRECTION:
        !          2371:             status = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
        !          2372:             logError = SP_PROTOCOL_ERROR;
        !          2373:             break;
        !          2374: 
        !          2375:         case CCB_BAD_MBO_COMMAND:
        !          2376:         case CCB_INVALID_OP_CODE:
        !          2377:         case CCB_BAD_LINKED_LUN:
        !          2378:         case CCB_DUPLICATE_CCB:
        !          2379:         case CCB_INVALID_CCB:
        !          2380:             status = SRB_STATUS_INVALID_REQUEST;
        !          2381:             logError = SP_INTERNAL_ADAPTER_ERROR;
        !          2382:             break;
        !          2383: 
        !          2384:        default:
        !          2385:            status = SRB_STATUS_ERROR;
        !          2386:            logError = SP_INTERNAL_ADAPTER_ERROR;
        !          2387:            break;
        !          2388:     }
        !          2389: 
        !          2390:     ScsiPortLogError(
        !          2391:         HwDeviceExtension,
        !          2392:         Srb,
        !          2393:         Srb->PathId,
        !          2394:         Srb->TargetId,
        !          2395:         Srb->Lun,
        !          2396:         logError,
        !          2397:         (2 << 8) | Ccb->HostStatus
        !          2398:         );
        !          2399: 
        !          2400:     return(status);
        !          2401: 
        !          2402: } // end MapError()
        !          2403: 
        !          2404: 
        !          2405: BOOLEAN
        !          2406: ReadCommandRegister(
        !          2407:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          2408:     OUT PUCHAR DataByte,
        !          2409:     IN BOOLEAN TimeOutFlag
        !          2410:     )
        !          2411: 
        !          2412: /*++
        !          2413: 
        !          2414: Routine Description:
        !          2415: 
        !          2416:     Read command register.
        !          2417: 
        !          2418: Arguments:
        !          2419: 
        !          2420:     DeviceExtesion - Pointer to adapder extension
        !          2421:     DataByte - Byte read from register
        !          2422: 
        !          2423: Return Value:
        !          2424: 
        !          2425:     TRUE if command register read.
        !          2426:     FALSE if timed out waiting for adapter.
        !          2427: 
        !          2428: --*/
        !          2429: 
        !          2430: {
        !          2431:     PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress;
        !          2432:     ULONG i;
        !          2433: 
        !          2434:     //
        !          2435:     // Wait up to 5000 microseconds for adapter to be ready.
        !          2436:     //
        !          2437: 
        !          2438:     for (i=0; i<5000; i++) {
        !          2439: 
        !          2440:         if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
        !          2441:             IOP_DATA_IN_PORT_FULL) {
        !          2442: 
        !          2443:             //
        !          2444:             // Adapter ready. Break out of loop.
        !          2445:             //
        !          2446: 
        !          2447:             break;
        !          2448: 
        !          2449:         } else {
        !          2450: 
        !          2451:             //
        !          2452:             // Stall 1 microsecond before
        !          2453:             // trying again.
        !          2454:             //
        !          2455: 
        !          2456:             ScsiPortStallExecution(1);
        !          2457:         }
        !          2458:     }
        !          2459: 
        !          2460:     if ( (i==5000) && (TimeOutFlag == TRUE)) {
        !          2461: 
        !          2462:             ScsiPortLogError(
        !          2463:                 DeviceExtension,
        !          2464:                 NULL,
        !          2465:                 0,
        !          2466:                 DeviceExtension->HostTargetId,
        !          2467:                 0,
        !          2468:                 SP_INTERNAL_ADAPTER_ERROR,
        !          2469:                 3 << 8
        !          2470:                 );
        !          2471: 
        !          2472:         DebugPrint((1, "Aha154x:ReadCommandRegister:  Read command timed out\n"));
        !          2473:         return FALSE;
        !          2474:     }
        !          2475: 
        !          2476:     *DataByte = ScsiPortReadPortUchar(&baseIoAddress->CommandRegister);
        !          2477: 
        !          2478:     return TRUE;
        !          2479: 
        !          2480: } // end ReadCommandRegister()
        !          2481: 
        !          2482: 
        !          2483: BOOLEAN
        !          2484: WriteCommandRegister(
        !          2485:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          2486:     IN UCHAR AdapterCommand,
        !          2487:     IN BOOLEAN WaitForIdle
        !          2488:     )
        !          2489: 
        !          2490: /*++
        !          2491: 
        !          2492: Routine Description:
        !          2493: 
        !          2494:     Write operation code to command register.
        !          2495: 
        !          2496: Arguments:
        !          2497: 
        !          2498:     DeviceExtension - Pointer to adapter extension
        !          2499:     AdapterCommand - Value to be written to register
        !          2500:     WaitForIdle - Indicates if the idle bit needs to be checked
        !          2501: 
        !          2502: Return Value:
        !          2503: 
        !          2504:     TRUE if command sent.
        !          2505:     FALSE if timed out waiting for adapter.
        !          2506: 
        !          2507: --*/
        !          2508: 
        !          2509: {
        !          2510:     PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress;
        !          2511:     ULONG i;
        !          2512:     UCHAR status;
        !          2513: 
        !          2514:     //
        !          2515:     // Wait up to 500 microseconds for adapter to be ready.
        !          2516:     //
        !          2517: 
        !          2518:     for (i=0; i<5000; i++) {
        !          2519: 
        !          2520:         status = ScsiPortReadPortUchar(&baseIoAddress->StatusRegister);
        !          2521: 
        !          2522:         if ((status & IOP_COMMAND_DATA_OUT_FULL) ||
        !          2523:             ( WaitForIdle && !(status & IOP_SCSI_HBA_IDLE))) {
        !          2524: 
        !          2525:             //
        !          2526:             // Stall 1 microsecond before
        !          2527:             // trying again.
        !          2528:             //
        !          2529: 
        !          2530:             ScsiPortStallExecution(1);
        !          2531: 
        !          2532:         } else {
        !          2533: 
        !          2534:             //
        !          2535:             // Adapter ready. Break out of loop.
        !          2536:             //
        !          2537: 
        !          2538:             break;
        !          2539:         }
        !          2540:     }
        !          2541: 
        !          2542:     if (i==5000) {
        !          2543: 
        !          2544:         ScsiPortLogError(
        !          2545:             DeviceExtension,
        !          2546:             NULL,
        !          2547:             0,
        !          2548:             DeviceExtension->HostTargetId,
        !          2549:             0,
        !          2550:             SP_INTERNAL_ADAPTER_ERROR,
        !          2551:             (4 << 8) | status);
        !          2552: 
        !          2553:         DebugPrint((1, "Aha154x:WriteCommandRegister:  Write command timed out\n"));
        !          2554:         return FALSE;
        !          2555:     }
        !          2556: 
        !          2557:     ScsiPortWritePortUchar(&baseIoAddress->CommandRegister, AdapterCommand);
        !          2558: 
        !          2559:     return TRUE;
        !          2560: 
        !          2561: } // end WriteCommandRegister()
        !          2562: 
        !          2563: 
        !          2564: BOOLEAN
        !          2565: WriteDataRegister(
        !          2566:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          2567:     IN UCHAR DataByte
        !          2568:     )
        !          2569: 
        !          2570: /*++
        !          2571: 
        !          2572: Routine Description:
        !          2573: 
        !          2574:     Write data byte to data register.
        !          2575: 
        !          2576: Arguments:
        !          2577: 
        !          2578:     DeviceExtension - Pointer to adapter extension
        !          2579:     DataByte - Value to be written to register
        !          2580: 
        !          2581: Return Value:
        !          2582: 
        !          2583:     TRUE if byte sent.
        !          2584:     FALSE if timed out waiting for adapter.
        !          2585: 
        !          2586: --*/
        !          2587: 
        !          2588: {
        !          2589:     PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress;
        !          2590:     ULONG i;
        !          2591: 
        !          2592:     //
        !          2593:     // Wait up to 500 microseconds for adapter to be idle
        !          2594:     // and ready for next byte.
        !          2595:     //
        !          2596: 
        !          2597:     for (i=0; i<500; i++) {
        !          2598: 
        !          2599:         if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
        !          2600:             IOP_COMMAND_DATA_OUT_FULL) {
        !          2601: 
        !          2602:             //
        !          2603:             // Stall 1 microsecond before
        !          2604:             // trying again.
        !          2605:             //
        !          2606: 
        !          2607:             ScsiPortStallExecution(1);
        !          2608: 
        !          2609:         } else {
        !          2610: 
        !          2611:             //
        !          2612:             // Adapter ready. Break out of loop.
        !          2613:             //
        !          2614: 
        !          2615:             break;
        !          2616:         }
        !          2617:     }
        !          2618: 
        !          2619:     if (i==500) {
        !          2620: 
        !          2621:             ScsiPortLogError(
        !          2622:                 DeviceExtension,
        !          2623:                 NULL,
        !          2624:                 0,
        !          2625:                 DeviceExtension->HostTargetId,
        !          2626:                 0,
        !          2627:                 SP_INTERNAL_ADAPTER_ERROR,
        !          2628:                 8 << 8);
        !          2629: 
        !          2630:         DebugPrint((1, "Aha154x:WriteDataRegister:  Write data timed out\n"));
        !          2631:         return FALSE;
        !          2632:     }
        !          2633: 
        !          2634:     ScsiPortWritePortUchar(&baseIoAddress->CommandRegister, DataByte);
        !          2635: 
        !          2636:     return TRUE;
        !          2637: 
        !          2638: } // end WriteDataRegister()
        !          2639: 
        !          2640: 
        !          2641: BOOLEAN
        !          2642: FirmwareBug (
        !          2643:     IN PVOID HwDeviceExtension
        !          2644:     )
        !          2645: 
        !          2646: /*++
        !          2647: 
        !          2648: Routine Description:
        !          2649: 
        !          2650:     Check to see if the host adapter firmware has the scatter/gather
        !          2651:     bug.
        !          2652: 
        !          2653: Arguments:
        !          2654: 
        !          2655:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !          2656: 
        !          2657: Return Value:
        !          2658: 
        !          2659:     Return FALSE if there is no firmware bug.
        !          2660:     Return TRUE if firmware has scatter/gather bug.
        !          2661: 
        !          2662: --*/
        !          2663: 
        !          2664: {
        !          2665:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          2666:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          2667:     UCHAR ch;
        !          2668:     int i;
        !          2669: 
        !          2670:     //
        !          2671:     // Issue a RETURN SETUP DATA command
        !          2672:     // If timeout then return TRUE to indicate that there is a firmware bug.
        !          2673:     //
        !          2674: 
        !          2675:     if ((WriteCommandRegister(HwDeviceExtension,
        !          2676:          AC_RETURN_SETUP_DATA,FALSE)) == FALSE) {
        !          2677:          return TRUE;
        !          2678:     }
        !          2679: 
        !          2680: 
        !          2681:     //
        !          2682:     // Tell the adapter we want to read in 0x11 bytes.
        !          2683:     //
        !          2684: 
        !          2685:     if (WriteDataRegister(HwDeviceExtension,0x11) == FALSE) {
        !          2686:         return TRUE;
        !          2687:     }
        !          2688: 
        !          2689:     //
        !          2690:     // Now try to read in 0x11 bytes.
        !          2691:     //
        !          2692: 
        !          2693:     for (i = 0; i< 0x11; i++) {
        !          2694:         if (ReadCommandRegister(HwDeviceExtension,&ch,TRUE) == FALSE) {
        !          2695:             return TRUE;
        !          2696:         }
        !          2697:     }
        !          2698: 
        !          2699:     //
        !          2700:     // Clear adapter interrupt.
        !          2701:     //
        !          2702: 
        !          2703:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
        !          2704:                            IOP_INTERRUPT_RESET);
        !          2705: 
        !          2706:     //
        !          2707:     // Issue SET HA OPTION command.
        !          2708:     //
        !          2709: 
        !          2710:     if (WriteCommandRegister(HwDeviceExtension,
        !          2711:         AC_SET_HA_OPTION,FALSE) == FALSE) {
        !          2712:         return TRUE;
        !          2713:     }
        !          2714: 
        !          2715:     //
        !          2716:     // Delay 500 microseconds.
        !          2717:     //
        !          2718: 
        !          2719:     ScsiPortStallExecution(500);
        !          2720: 
        !          2721:     //
        !          2722:     // Check for invalid command.
        !          2723:     //
        !          2724: 
        !          2725:     if ( (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
        !          2726:           IOP_INVALID_COMMAND) ) {
        !          2727:         //
        !          2728:         // Clear adapter interrupt.
        !          2729:         //
        !          2730: 
        !          2731:         ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
        !          2732:                                IOP_INTERRUPT_RESET);
        !          2733:         return TRUE;
        !          2734:     }
        !          2735: 
        !          2736:     //
        !          2737:     // send 01h
        !          2738:     //
        !          2739: 
        !          2740:     if (WriteDataRegister(HwDeviceExtension,0x01) == FALSE) {
        !          2741:         return TRUE;
        !          2742:     }
        !          2743: 
        !          2744:     //
        !          2745:     // Send same byte as was last received.
        !          2746:     //
        !          2747: 
        !          2748:     if (WriteDataRegister(HwDeviceExtension,ch) == FALSE) {
        !          2749:         return TRUE;
        !          2750:     }
        !          2751: 
        !          2752:     //
        !          2753:     // Clear adapter interrupt.
        !          2754:     //
        !          2755: 
        !          2756:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
        !          2757:                            IOP_INTERRUPT_RESET);
        !          2758:     return FALSE;
        !          2759: } // end of FirmwareBug ()
        !          2760: 
        !          2761: 
        !          2762: VOID
        !          2763: GetHostAdapterBoardId (
        !          2764:     IN PVOID HwDeviceExtension,
        !          2765:     OUT PUCHAR BoardId
        !          2766:     )
        !          2767: 
        !          2768: /*++
        !          2769: 
        !          2770: Routine Description:
        !          2771: 
        !          2772:     Get board id, firmware id and hardware id from the host adapter.
        !          2773:     These info are used to determine if the host adapter supports
        !          2774:     scatter/gather.
        !          2775: 
        !          2776: Arguments:
        !          2777: 
        !          2778:     HwDeviceExtension - HBA miniport driver's adapter data storage
        !          2779: 
        !          2780: Return Value:
        !          2781: 
        !          2782:     Board id, hardware id and firmware id (in that order) by modyfing *BoardId
        !          2783:     If there is any error, it will just return with *BoardId unmodified
        !          2784: 
        !          2785: --*/
        !          2786: 
        !          2787: {
        !          2788:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          2789:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          2790:     UCHAR firmwareId;
        !          2791:     UCHAR board_Id;
        !          2792:     UCHAR hardwareId;
        !          2793:     ULONG i;
        !          2794: 
        !          2795:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
        !          2796:                            IOP_INTERRUPT_RESET);
        !          2797: 
        !          2798:     if (!WriteCommandRegister(HwDeviceExtension,AC_ADAPTER_INQUIRY,FALSE)) {
        !          2799:         return;
        !          2800:     }
        !          2801: 
        !          2802:     //
        !          2803:     // Save byte 0 as board ID.
        !          2804:     //
        !          2805: 
        !          2806:     if ((ReadCommandRegister(HwDeviceExtension,&board_Id,TRUE)) == FALSE) {
        !          2807:         return;
        !          2808:     }
        !          2809: 
        !          2810:     //
        !          2811:     // Ignore byte 1.  Use hardwareId as scrap storage.
        !          2812:     //
        !          2813: 
        !          2814:     if ((ReadCommandRegister(HwDeviceExtension,&hardwareId,TRUE)) == FALSE) {
        !          2815:         return;
        !          2816:     }
        !          2817: 
        !          2818:     //
        !          2819:     // Save byte 2 as hardware revision in hardwareId.
        !          2820:     //
        !          2821: 
        !          2822:     if ((ReadCommandRegister(HwDeviceExtension,&hardwareId,TRUE)) == FALSE) {
        !          2823:         return;
        !          2824:     }
        !          2825: 
        !          2826:     if ((ReadCommandRegister(HwDeviceExtension,&firmwareId,TRUE)) == FALSE) {
        !          2827:         return;
        !          2828:     }
        !          2829: 
        !          2830:     //
        !          2831:     // Interrupt handler is not yet installed so wait for HACC by hand.
        !          2832:     //
        !          2833: 
        !          2834:     for (i = 0; i<5000; i++) {
        !          2835:         if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) ==
        !          2836:             (IOP_ANY_INTERRUPT | IOP_COMMAND_COMPLETE) ) {
        !          2837:             break;
        !          2838:         }
        !          2839:         ScsiPortStallExecution(1);
        !          2840:     }
        !          2841: 
        !          2842:     //
        !          2843:     // If timeout then return with *BoardId unmodified.  This means that
        !          2844:     // scatter/gather won't be supported.
        !          2845:     //
        !          2846: 
        !          2847:     if (i == 5000) {
        !          2848:         return;
        !          2849:     }
        !          2850: 
        !          2851:     //
        !          2852:     // Clear adapter interrupt.
        !          2853:     //
        !          2854: 
        !          2855:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET);
        !          2856: 
        !          2857:     //
        !          2858:     // Return with appropriate ID's.
        !          2859:     //
        !          2860: 
        !          2861:     *BoardId++ = board_Id;
        !          2862:     *BoardId++ = hardwareId;
        !          2863:     *BoardId++ = firmwareId;
        !          2864: 
        !          2865:     DebugPrint((1,"board_id = %d\n",board_Id));
        !          2866:     DebugPrint((1,"hardwareid = %d\n",hardwareId));
        !          2867:     DebugPrint((1,"fid = %d\n",firmwareId));
        !          2868: 
        !          2869: }  // end of GetHostAdapterBoardId ()
        !          2870: 
        !          2871: 
        !          2872: BOOLEAN
        !          2873: ScatterGatherSupported (
        !          2874:    IN PHW_DEVICE_EXTENSION HwDeviceExtension
        !          2875:    )
        !          2876: 
        !          2877: /*++
        !          2878: 
        !          2879: Routine Description:
        !          2880:    Determine if the host adapter supports scatter/gather.  On older
        !          2881:    boards, scatter/gather is not supported.  On some boards, there is
        !          2882:    a bug that causes data corruption on multi-segment WRITE commands.
        !          2883:    The algorithm to determine whether the board has the scatter/gather
        !          2884:    bug is not "clean" but there is no other way since the firmware revision
        !          2885:    levels returned by the host adapter are inconsistent with previous
        !          2886:    releases.
        !          2887: 
        !          2888: Arguments:
        !          2889: 
        !          2890:    HwDeviceExtension - HBA miniport driver's adapter data storage
        !          2891: 
        !          2892: Return Value:
        !          2893: 
        !          2894:    Return TRUE if the algorithm determines that there is no scatter/gather
        !          2895:    firmware bug.
        !          2896: 
        !          2897:    Return FALSE if the algorithm determines that the adapter is an older
        !          2898:    board or that the firmware contains the scatter gather bug
        !          2899: 
        !          2900: --*/
        !          2901: {
        !          2902:    PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          2903:    PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          2904:    UCHAR HostAdapterId[3];
        !          2905: 
        !          2906:    GetHostAdapterBoardId(HwDeviceExtension,&HostAdapterId[0]);
        !          2907: 
        !          2908:    //
        !          2909:    // If it's an older board then scatter/gather is not supported.
        !          2910:    //
        !          2911: 
        !          2912:    if ( (HostAdapterId[BOARD_ID] == OLD_BOARD_ID1) ||
        !          2913:       (HostAdapterId[BOARD_ID] == OLD_BOARD_ID2) ) {
        !          2914:       return FALSE;
        !          2915:    }
        !          2916: 
        !          2917:    //
        !          2918:    // If 1540A/B then check for firmware bug.
        !          2919:    //
        !          2920: 
        !          2921:    if (HostAdapterId[BOARD_ID] == A154X_BOARD) {
        !          2922:       if (FirmwareBug(HwDeviceExtension)) {
        !          2923:          return FALSE;
        !          2924:       }
        !          2925:    }
        !          2926: 
        !          2927:    //
        !          2928:    // Now check hardware ID and firmware ID.
        !          2929:    //
        !          2930: 
        !          2931:    if (HostAdapterId[HARDWARE_ID] != A154X_BAD_HARDWARE_ID) {
        !          2932:       return TRUE;
        !          2933:    }
        !          2934: 
        !          2935:    if (HostAdapterId[FIRMWARE_ID] != A154X_BAD_FIRMWARE_ID) {
        !          2936:       return TRUE;
        !          2937:    }
        !          2938: 
        !          2939:    //
        !          2940:    // Host adapter has scatter/gather bug.
        !          2941:    // Clear interrupt on adapter.
        !          2942:    //
        !          2943: 
        !          2944:    ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET);
        !          2945: 
        !          2946:    return FALSE;
        !          2947: 
        !          2948: }  // end of ScatterGatherSupported ()
        !          2949: 
        !          2950: 
        !          2951: BOOLEAN
        !          2952: SpinForInterrupt(
        !          2953:     IN PHW_DEVICE_EXTENSION DeviceExtension,
        !          2954:     IN BOOLEAN TimeOutFlag
        !          2955:     )
        !          2956: 
        !          2957: /*++
        !          2958: 
        !          2959: Routine Description:
        !          2960: 
        !          2961:     Wait for interrupt.
        !          2962: 
        !          2963: Arguments:
        !          2964: 
        !          2965:     DeviceExtension - Pointer to adapter extension
        !          2966: 
        !          2967: Return Value:
        !          2968: 
        !          2969:     TRUE if interrupt occurred.
        !          2970:     FALSE if timed out waiting for interrupt.
        !          2971: 
        !          2972: --*/
        !          2973: 
        !          2974: {
        !          2975:     PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress;
        !          2976:     ULONG i;
        !          2977: 
        !          2978:     //
        !          2979:     // Wait up to 1 millisecond for interrupt to occur.
        !          2980:     //
        !          2981: 
        !          2982:     for (i=0; i<1000; i++) {
        !          2983: 
        !          2984:         if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) & IOP_COMMAND_COMPLETE) {
        !          2985: 
        !          2986:             //
        !          2987:             // Interrupt occurred. Break out of wait loop.
        !          2988:             //
        !          2989: 
        !          2990:             break;
        !          2991: 
        !          2992:         } else {
        !          2993: 
        !          2994:             //
        !          2995:             // Stall one microsecond.
        !          2996:             //
        !          2997: 
        !          2998:             ScsiPortStallExecution(1);
        !          2999:         }
        !          3000:     }
        !          3001: 
        !          3002:     if ( (i==1000) && (TimeOutFlag == TRUE)) {
        !          3003: 
        !          3004:         ScsiPortLogError(DeviceExtension,
        !          3005:                          NULL,
        !          3006:                          0,
        !          3007:                          DeviceExtension->HostTargetId,
        !          3008:                          0,
        !          3009:                          SP_INTERNAL_ADAPTER_ERROR,
        !          3010:                          9 << 8);
        !          3011: 
        !          3012:         DebugPrint((1, "Aha154x:SpinForInterrupt:  Timed out waiting for interrupt\n"));
        !          3013: 
        !          3014:         return FALSE;
        !          3015: 
        !          3016:     } else {
        !          3017: 
        !          3018:         //
        !          3019:         // Clear interrupt on adapter.
        !          3020:         //
        !          3021: 
        !          3022:         ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
        !          3023: 
        !          3024:         return TRUE;
        !          3025:     }
        !          3026: 
        !          3027: } // end SpinForInterrupt()
        !          3028: 
        !          3029: 
        !          3030: BOOLEAN UnlockMailBoxes (
        !          3031:     IN PVOID HwDeviceExtension
        !          3032:     )
        !          3033: 
        !          3034: /*++
        !          3035: 
        !          3036: Routine Description:
        !          3037: 
        !          3038:     Unlock 1542B+ or 1542C mailboxes so that the driver
        !          3039:     can zero out mailboxes when it's initializing the adapter.
        !          3040: 
        !          3041:     The mailboxes are locked if:
        !          3042:     1. >1Gb option is enabled (this option is available for 154xB+ and
        !          3043:        154xC).
        !          3044: 
        !          3045:     2. Dynamic scan lock option is enabled (154xC board only)
        !          3046: 
        !          3047:     The reason the mailboxes are locked by the adapter's firmware is
        !          3048:     because the BIOS is now reporting 255/63 translation instead of 64/32.
        !          3049:     As such, if a user inadvertently enabled the >1Gb option (enabling
        !          3050:     255/63 translation) and still uses an old driver, hard disk data
        !          3051:     will be corrupted.  Therefore, the firmware will not allow mailboxes
        !          3052:     to be initialized unless the user knows what he is doing and updates
        !          3053:     his driver so that his disk won't be trashed.
        !          3054: 
        !          3055: Arguments:
        !          3056: 
        !          3057:     DeviceExtension - Pointer to adapter extension
        !          3058: 
        !          3059: Return Value:
        !          3060: 
        !          3061:     TRUE if mailboxes are unlocked.
        !          3062:     FALSE if mailboxes are not unlocked.
        !          3063:     Note that if the adapter is just a 154xB board (without the >1Gb
        !          3064:     option), this routine will return FALSE.
        !          3065: 
        !          3066: --*/
        !          3067: 
        !          3068: {
        !          3069:     UCHAR locktype;
        !          3070: 
        !          3071:     //
        !          3072:     // Request information.
        !          3073:     //
        !          3074: 
        !          3075:     if (WriteCommandRegister(HwDeviceExtension, AC_GET_BIOS_INFO, TRUE) == FALSE) {
        !          3076:        return FALSE;
        !          3077:     }
        !          3078: 
        !          3079: 
        !          3080:     //
        !          3081:     // Retrieve first byte.
        !          3082:     //
        !          3083: 
        !          3084:     if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) {
        !          3085:         return FALSE;
        !          3086:     }
        !          3087: 
        !          3088:     //
        !          3089:     // Check for extended bios translation enabled option on 1540C and
        !          3090:     // 1540B with 1GB support.
        !          3091:     //
        !          3092: 
        !          3093:     if (locktype != TRANSLATION_ENABLED) {
        !          3094: 
        !          3095:         //
        !          3096:         // Extended translation is disabled.  Retrieve lock status.
        !          3097:         //
        !          3098: 
        !          3099:         if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) {
        !          3100:             return FALSE;
        !          3101:         }
        !          3102: 
        !          3103:         if (locktype == DYNAMIC_SCAN_LOCK) {
        !          3104:             return(SendUnlockCommand(HwDeviceExtension,locktype));
        !          3105:         }
        !          3106:         return FALSE;
        !          3107:     }
        !          3108: 
        !          3109:     //
        !          3110:     // Extended BIOS translation (255/63) is enabled.
        !          3111:     //
        !          3112: 
        !          3113: 
        !          3114:     if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) {
        !          3115:         return FALSE;
        !          3116:     }
        !          3117: 
        !          3118:     if ((locktype == TRANSLATION_LOCK) || (locktype == DYNAMIC_SCAN_LOCK)) {
        !          3119:         return(SendUnlockCommand(HwDeviceExtension,locktype));
        !          3120:     }
        !          3121: 
        !          3122:     return FALSE;
        !          3123: }  // end of UnlockMailBoxes ()
        !          3124: 
        !          3125: 
        !          3126: BOOLEAN
        !          3127: SendUnlockCommand(
        !          3128:     IN PVOID HwDeviceExtension,
        !          3129:     IN UCHAR locktype
        !          3130:     )
        !          3131: 
        !          3132: /*++
        !          3133: 
        !          3134: Routine Description:
        !          3135: 
        !          3136:     Send unlock command to 1542B+ or 1542C board so that the driver
        !          3137:     can zero out mailboxes when it's initializing the adapter.
        !          3138: 
        !          3139: 
        !          3140: Arguments:
        !          3141: 
        !          3142:     DeviceExtension - Pointer to adapter extension
        !          3143: 
        !          3144: Return Value:
        !          3145: 
        !          3146:     TRUE if commands are sent successfully.
        !          3147:     FALSE if not.
        !          3148: 
        !          3149: --*/
        !          3150: 
        !          3151: {
        !          3152:     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
        !          3153:     PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
        !          3154: 
        !          3155:     if (WriteCommandRegister(deviceExtension,
        !          3156:         AC_SET_MAILBOX_INTERFACE,TRUE) == FALSE) {
        !          3157:         return FALSE;
        !          3158:     }
        !          3159: 
        !          3160:     if (WriteDataRegister(deviceExtension,MAILBOX_UNLOCK) == FALSE) {
        !          3161:         return FALSE;
        !          3162:     }
        !          3163: 
        !          3164:     if (WriteDataRegister(deviceExtension,locktype) == FALSE) {
        !          3165:         return FALSE;
        !          3166:     }
        !          3167: 
        !          3168:     //
        !          3169:     // Clear interrupt on adapter.
        !          3170:     //
        !          3171: 
        !          3172: 
        !          3173:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
        !          3174: 
        !          3175:     return TRUE;
        !          3176: }  // end of SendUnlockCommand ()
        !          3177: 
        !          3178: 
        !          3179: BOOLEAN
        !          3180: FinishHBACmd(
        !          3181:     IN PHW_DEVICE_EXTENSION HwDeviceExtension
        !          3182:     )
        !          3183: 
        !          3184: /*++
        !          3185: 
        !          3186: Routine Description:
        !          3187: 
        !          3188:     Wait for command complete interrupt, clear interrupt, chk cmd status.
        !          3189:     This is done because the driver has not registered our interrupt handler
        !          3190:     (which would normally do this work).
        !          3191: 
        !          3192: Arguments:
        !          3193: 
        !          3194:     HwDeviceExtension - Pointer to adapter extension
        !          3195: 
        !          3196: Return Value:
        !          3197: 
        !          3198:     TRUE if command completed successfully.
        !          3199:     FALSE if timed out waiting for adapter or invalid command.
        !          3200: 
        !          3201: --*/
        !          3202: 
        !          3203: {
        !          3204:     PBASE_REGISTER baseIoAddress = HwDeviceExtension->BaseIoAddress;
        !          3205:     ULONG i;
        !          3206: 
        !          3207:     for (i=0; i<500; i++) {
        !          3208: 
        !          3209:         if (!((ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) &
        !          3210:             (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))==
        !          3211:             (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))) {
        !          3212: 
        !          3213:             //
        !          3214:             // Stall 1 microsecond before
        !          3215:             // trying again.
        !          3216:             //
        !          3217: 
        !          3218:             ScsiPortStallExecution(1);
        !          3219: 
        !          3220:         } else {
        !          3221: 
        !          3222:             //
        !          3223:             // Adapter ready. Break out of loop.
        !          3224:             //
        !          3225: 
        !          3226:             break;
        !          3227:         }
        !          3228:     }
        !          3229: 
        !          3230:     if (i==500) {
        !          3231: 
        !          3232:         ScsiPortLogError(HwDeviceExtension,
        !          3233:                          NULL,
        !          3234:                          0,
        !          3235:                          HwDeviceExtension->HostTargetId,
        !          3236:                          0,
        !          3237:                          SP_INTERNAL_ADAPTER_ERROR,
        !          3238:                          4 << 8);
        !          3239: 
        !          3240:         DebugPrint((1, "A154x:FinishHBACmd: Wait for CmdCmplt & AnyIntr failed\n"));
        !          3241:         return FALSE;
        !          3242:     }
        !          3243: 
        !          3244:     ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET);
        !          3245: 
        !          3246:     if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & (IOP_INVALID_COMMAND)) {
        !          3247:         return FALSE;
        !          3248:     }
        !          3249: 
        !          3250:     return TRUE;
        !          3251: } // end FinishHBACmd()
        !          3252: 
        !          3253: 
        !          3254: ULONG
        !          3255: AhaParseArgumentString(
        !          3256:     IN PCHAR String,
        !          3257:     IN PCHAR KeyWord
        !          3258:     )
        !          3259: 
        !          3260: /*++
        !          3261: 
        !          3262: Routine Description:
        !          3263: 
        !          3264:     This routine will parse the string for a match on the keyword, then
        !          3265:     calculate the value for the keyword and return it to the caller.
        !          3266: 
        !          3267: Arguments:
        !          3268: 
        !          3269:     String - The ASCII string to parse.
        !          3270:     KeyWord - The keyword for the value desired.
        !          3271: 
        !          3272: Return Values:
        !          3273: 
        !          3274:     Zero if value not found
        !          3275:     Value converted from ASCII to binary.
        !          3276: 
        !          3277: --*/
        !          3278: 
        !          3279: {
        !          3280:     PCHAR cptr;
        !          3281:     PCHAR kptr;
        !          3282:     ULONG value;
        !          3283:     ULONG stringLength = 0;
        !          3284:     ULONG keyWordLength = 0;
        !          3285:     ULONG index;
        !          3286: 
        !          3287:     //
        !          3288:     // Calculate the string length and lower case all characters.
        !          3289:     //
        !          3290:     cptr = String;
        !          3291:     while (*cptr) {
        !          3292: 
        !          3293:         if (*cptr >= 'A' && *cptr <= 'Z') {
        !          3294:             *cptr = *cptr + ('a' - 'A');
        !          3295:         }
        !          3296:         cptr++;
        !          3297:         stringLength++;
        !          3298:     }
        !          3299: 
        !          3300:     //
        !          3301:     // Calculate the keyword length and lower case all characters.
        !          3302:     //
        !          3303:     cptr = KeyWord;
        !          3304:     while (*cptr) {
        !          3305: 
        !          3306:         if (*cptr >= 'A' && *cptr <= 'Z') {
        !          3307:             *cptr = *cptr + ('a' - 'A');
        !          3308:         }
        !          3309:         cptr++;
        !          3310:         keyWordLength++;
        !          3311:     }
        !          3312: 
        !          3313:     if (keyWordLength > stringLength) {
        !          3314: 
        !          3315:         //
        !          3316:         // Can't possibly have a match.
        !          3317:         //
        !          3318:         return 0;
        !          3319:     }
        !          3320: 
        !          3321:     //
        !          3322:     // Now setup and start the compare.
        !          3323:     //
        !          3324:     cptr = String;
        !          3325: 
        !          3326: ContinueSearch:
        !          3327:     //
        !          3328:     // The input string may start with white space.  Skip it.
        !          3329:     //
        !          3330:     while (*cptr == ' ' || *cptr == '\t') {
        !          3331:         cptr++;
        !          3332:     }
        !          3333: 
        !          3334:     if (*cptr == '\0') {
        !          3335: 
        !          3336:         //
        !          3337:         // end of string.
        !          3338:         //
        !          3339:         return 0;
        !          3340:     }
        !          3341: 
        !          3342:     kptr = KeyWord;
        !          3343:     while (*cptr++ == *kptr++) {
        !          3344: 
        !          3345:         if (*(cptr - 1) == '\0') {
        !          3346: 
        !          3347:             //
        !          3348:             // end of string
        !          3349:             //
        !          3350:             return 0;
        !          3351:         }
        !          3352:     }
        !          3353: 
        !          3354:     if (*(kptr - 1) == '\0') {
        !          3355: 
        !          3356:         //
        !          3357:         // May have a match backup and check for blank or equals.
        !          3358:         //
        !          3359: 
        !          3360:         cptr--;
        !          3361:         while (*cptr == ' ' || *cptr == '\t') {
        !          3362:             cptr++;
        !          3363:         }
        !          3364: 
        !          3365:         //
        !          3366:         // Found a match.  Make sure there is an equals.
        !          3367:         //
        !          3368:         if (*cptr != '=') {
        !          3369: 
        !          3370:             //
        !          3371:             // Not a match so move to the next semicolon.
        !          3372:             //
        !          3373:             while (*cptr) {
        !          3374:                 if (*cptr++ == ';') {
        !          3375:                     goto ContinueSearch;
        !          3376:                 }
        !          3377:             }
        !          3378:             return 0;
        !          3379:         }
        !          3380: 
        !          3381:         //
        !          3382:         // Skip the equals sign.
        !          3383:         //
        !          3384:         cptr++;
        !          3385: 
        !          3386:         //
        !          3387:         // Skip white space.
        !          3388:         //
        !          3389:         while ((*cptr == ' ') || (*cptr == '\t')) {
        !          3390:             cptr++;
        !          3391:         }
        !          3392: 
        !          3393:         if (*cptr == '\0') {
        !          3394: 
        !          3395:             //
        !          3396:             // Early end of string, return not found
        !          3397:             //
        !          3398:             return 0;
        !          3399:         }
        !          3400: 
        !          3401:         if (*cptr == ';') {
        !          3402: 
        !          3403:             //
        !          3404:             // This isn't it either.
        !          3405:             //
        !          3406:             cptr++;
        !          3407:             goto ContinueSearch;
        !          3408:         }
        !          3409: 
        !          3410:         value = 0;
        !          3411:         if ((*cptr == '0') && (*(cptr + 1) == 'x')) {
        !          3412: 
        !          3413:             //
        !          3414:             // Value is in Hex.  Skip the "0x"
        !          3415:             //
        !          3416:             cptr += 2;
        !          3417:             for (index = 0; *(cptr + index); index++) {
        !          3418: 
        !          3419:                 if (*(cptr + index) == ' ' ||
        !          3420:                     *(cptr + index) == '\t' ||
        !          3421:                     *(cptr + index) == ';') {
        !          3422:                      break;
        !          3423:                 }
        !          3424: 
        !          3425:                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
        !          3426:                     value = (16 * value) + (*(cptr + index) - '0');
        !          3427:                 } else {
        !          3428:                     if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
        !          3429:                         value = (16 * value) + (*(cptr + index) - 'a' + 10);
        !          3430:                     } else {
        !          3431: 
        !          3432:                         //
        !          3433:                         // Syntax error, return not found.
        !          3434:                         //
        !          3435:                         return 0;
        !          3436:                     }
        !          3437:                 }
        !          3438:             }
        !          3439:         } else {
        !          3440: 
        !          3441:             //
        !          3442:             // Value is in Decimal.
        !          3443:             //
        !          3444:             for (index = 0; *(cptr + index); index++) {
        !          3445: 
        !          3446:                 if (*(cptr + index) == ' ' ||
        !          3447:                     *(cptr + index) == '\t' ||
        !          3448:                     *(cptr + index) == ';') {
        !          3449:                      break;
        !          3450:                 }
        !          3451: 
        !          3452:                 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
        !          3453:                     value = (10 * value) + (*(cptr + index) - '0');
        !          3454:                 } else {
        !          3455: 
        !          3456:                     //
        !          3457:                     // Syntax error return not found.
        !          3458:                     //
        !          3459:                     return 0;
        !          3460:                 }
        !          3461:             }
        !          3462:         }
        !          3463: 
        !          3464:         return value;
        !          3465:     } else {
        !          3466: 
        !          3467:         //
        !          3468:         // Not a match check for ';' to continue search.
        !          3469:         //
        !          3470:         while (*cptr) {
        !          3471:             if (*cptr++ == ';') {
        !          3472:                 goto ContinueSearch;
        !          3473:             }
        !          3474:         }
        !          3475: 
        !          3476:         return 0;
        !          3477:     }
        !          3478: }

unix.superglobalmegacorp.com

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