Annotation of ntddk/src/scsi/aha154x/aha154x.c, revision 1.1.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.