Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3181 lines
77 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 BusLogic, Inc.
  3. Module Name:
  4. Buslogic.c
  5. Abstract:
  6. This is the port driver for the BusLogic SCSI ISA/EISA/MCA Adapters.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "miniport.h"
  13. #include "buslogic.h" // includes scsi.h
  14. //
  15. // The following table specifies the ports to be checked when searching for
  16. // an adapter. A zero entry terminates the search.
  17. //
  18. ULONG AdapterAddresses[] = {0X330, 0X334, 0X234, 0X134, 0X130, 0X230, 0};
  19. ULONG PciAdapterAddresses[] = {0Xfff,0xfff,0xfff,0xfff,0xfff,0xfff,0}; /* dummy entry for PCI */
  20. UCHAR VendorId[4]={'1','0','4','b'};
  21. UCHAR NewDeviceId[4]={'1','0','4','0'};
  22. ULONG InittedEISABoards = 0;
  23. //
  24. // Function declarations
  25. //
  26. // Functions that start with 'BLogic' are entry points
  27. // for the OS port driver.
  28. //
  29. ULONG
  30. DriverEntry(
  31. IN PVOID DriverObject,
  32. IN PVOID Argument2
  33. );
  34. ULONG
  35. BLogicEntry(
  36. IN PVOID DriverObject,
  37. IN PVOID Argument2
  38. );
  39. ULONG
  40. BLogicDetermineInstalled(
  41. IN PCARD_STRUC CardPtr,
  42. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  43. IN OUT PBL_CONTEXT CurrContextPtr,
  44. OUT PBOOLEAN Again
  45. );
  46. ULONG
  47. BLogicFindAdapter (
  48. IN PCARD_STRUC CardPtr,
  49. IN PVOID Context,
  50. IN PVOID BusInformation,
  51. IN PCHAR ArgumentString,
  52. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  53. OUT PBOOLEAN Again
  54. );
  55. BOOLEAN
  56. BLogicAdapterState(
  57. IN PCARD_STRUC CardPtr,
  58. IN PVOID Context,
  59. IN BOOLEAN SaveState
  60. );
  61. BOOLEAN
  62. BLogicHwInitialize(
  63. IN PCARD_STRUC CardPtr
  64. );
  65. BOOLEAN
  66. BLogicStartIo(
  67. IN PCARD_STRUC CardPtr,
  68. IN PSCSI_REQUEST_BLOCK Srb
  69. );
  70. BOOLEAN
  71. BLogicInterrupt(
  72. IN PCARD_STRUC CardPtr
  73. );
  74. BOOLEAN
  75. BLogicResetBus(
  76. IN PCARD_STRUC CardPtr,
  77. IN ULONG PathId
  78. );
  79. BOOLEAN
  80. ResetBus(
  81. IN PCARD_STRUC CardPtr,
  82. IN ULONG PathId
  83. );
  84. // Add the following function back in!
  85. BOOLEAN
  86. ReInitializeHBA(
  87. IN PCARD_STRUC CardPtr,
  88. IN ULONG PathId
  89. );
  90. //
  91. // This function is called from BLogicStartIo.
  92. //
  93. VOID
  94. BuildCcb(
  95. IN PCARD_STRUC CardPtr,
  96. IN PSCSI_REQUEST_BLOCK Srb
  97. );
  98. //
  99. // This function is called from BuildCcb.
  100. //
  101. VOID
  102. BuildSdl(
  103. IN PCARD_STRUC CardPtr,
  104. IN PSCSI_REQUEST_BLOCK Srb
  105. );
  106. //
  107. // This function is called from BLogicInitialize.
  108. //
  109. BOOLEAN
  110. AdapterPresent(
  111. IN PCARD_STRUC CardPtr
  112. );
  113. //
  114. // This function is called from BLogicInterrupt.
  115. //
  116. UCHAR
  117. MapError(
  118. IN PCARD_STRUC CardPtr,
  119. IN PSCSI_REQUEST_BLOCK Srb,
  120. IN PCCB Ccb
  121. );
  122. BOOLEAN
  123. ReadCommandRegister(
  124. IN PCARD_STRUC CardPtr,
  125. OUT PUCHAR DataByte
  126. );
  127. BOOLEAN
  128. WriteCommandRegister(
  129. IN PCARD_STRUC CardPtr,
  130. IN UCHAR AdapterCommand
  131. );
  132. BOOLEAN
  133. AdjustCCBqueue(
  134. PCCB ccbp,
  135. IN PDEV_STRUC devptr
  136. );
  137. PMBI
  138. DoneMbox(
  139. IN PCARD_STRUC CardPtr
  140. );
  141. BOOLEAN
  142. SendCCB(
  143. IN PSCSI_REQUEST_BLOCK Srb,
  144. IN PCARD_STRUC CardPtr,
  145. IN PDEV_STRUC DevStruc
  146. );
  147. BOOLEAN
  148. FinishHBACmd(
  149. IN PCARD_STRUC CardPtr
  150. );
  151. BOOLEAN
  152. CheckInvalid(
  153. IN PCARD_STRUC CardPtr
  154. );
  155. ULONG
  156. FindOurEISAId(
  157. IN PCARD_STRUC CardPtr,
  158. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  159. PBASE_REGISTER baseIoAddress
  160. );
  161. ULONG
  162. DriverEntry (
  163. IN PVOID DriverObject,
  164. IN PVOID Argument2
  165. )
  166. /*++
  167. Routine Description:
  168. Installable driver initialization entry point for system.
  169. Arguments:
  170. Driver Object
  171. Return Value:
  172. Status from ScsiPortInitialize()
  173. --*/
  174. {
  175. return BLogicEntry(DriverObject, Argument2);
  176. } // end DriverEntry()
  177. ULONG
  178. BLogicEntry(
  179. IN PVOID DriverObject,
  180. IN PVOID Argument2
  181. )
  182. /*++
  183. Routine Description:
  184. This routine is called from DriverEntry if this driver is installable
  185. or directly from the system if the driver is built into the kernel.
  186. It calls the OS dependent driver which controls the initialization.
  187. Arguments:
  188. Driver Object
  189. Return Value:
  190. Status return by scsi port intialize.
  191. --*/
  192. {
  193. HW_INITIALIZATION_DATA hwInitializationData;
  194. BL_CONTEXT CurrContext;
  195. PBL_CONTEXT CurrContextPtr = &CurrContext;
  196. ULONG isaStatus;
  197. ULONG mcaStatus;
  198. ULONG EisaStatus;
  199. ULONG i,PCIStatus,LowStatus1,LowStatus2;
  200. DebugPrint((1,"\n\nBusLogic SCSI MiniPort Driver\n"));
  201. //
  202. // Zero out structure.
  203. //
  204. for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) {
  205. ((PUCHAR)&hwInitializationData)[i] = 0;
  206. }
  207. //
  208. // Set size of hwInitializationData.
  209. //
  210. hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
  211. //
  212. // Set entry points.
  213. //
  214. hwInitializationData.HwInitialize = (PHW_INITIALIZE) BLogicHwInitialize;
  215. hwInitializationData.HwResetBus = (PHW_RESET_BUS) BLogicResetBus;
  216. hwInitializationData.HwStartIo = (PHW_STARTIO) BLogicStartIo;
  217. hwInitializationData.HwInterrupt = (PHW_INTERRUPT) BLogicInterrupt;
  218. hwInitializationData.HwFindAdapter = (PHW_FIND_ADAPTER) BLogicFindAdapter;
  219. hwInitializationData.HwAdapterState = BLogicAdapterState;
  220. //
  221. // Indicate no buffer mapping but will need physical addresses.
  222. //
  223. hwInitializationData.NeedPhysicalAddresses = TRUE;
  224. hwInitializationData.AutoRequestSense = TRUE;
  225. hwInitializationData.TaggedQueuing = TRUE;
  226. hwInitializationData.MultipleRequestPerLu = TRUE;
  227. //
  228. // Specify size of extensions.
  229. //
  230. hwInitializationData.DeviceExtensionSize = sizeof(CARD_STRUC);
  231. hwInitializationData.SpecificLuExtensionSize = sizeof(DEV_STRUC);
  232. hwInitializationData.NumberOfAccessRanges = 1;
  233. //
  234. // Ask for SRB extensions for CCBs.
  235. //
  236. hwInitializationData.SrbExtensionSize = sizeof(CCB);
  237. //
  238. // The adapter count is used by the find adapter routine to track how
  239. // which adapter addresses have been tested.
  240. //
  241. CurrContextPtr->AdapterCount = 0;
  242. CurrContextPtr->PCIDevId = 0x1040;
  243. //
  244. // try to configure for the PCI bus, fully-compliant HBA.
  245. // Specify the bus type.
  246. //
  247. hwInitializationData.AdapterInterfaceType = PCIBus;
  248. hwInitializationData.VendorId = VendorId;
  249. hwInitializationData.VendorIdLength = 4;
  250. hwInitializationData.DeviceId = NewDeviceId;
  251. hwInitializationData.DeviceIdLength = 4;
  252. PCIStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, CurrContextPtr);
  253. //
  254. // Now try to configure for the EISA bus.
  255. // Specify the bus type.
  256. //
  257. hwInitializationData.AdapterInterfaceType = Eisa;
  258. CurrContextPtr->AdapterCount = 0;
  259. CurrContextPtr->PCIDevId = 0;
  260. EisaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, CurrContextPtr);
  261. //
  262. // Now try to configure for the Mca bus.
  263. // Specifiy the bus type.
  264. //
  265. hwInitializationData.AdapterInterfaceType = MicroChannel;
  266. CurrContextPtr->AdapterCount = 0;
  267. CurrContextPtr->PCIDevId = 0;
  268. mcaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, CurrContextPtr);
  269. //
  270. // Now try to configure for the ISA bus.
  271. // Specifiy the bus type.
  272. //
  273. hwInitializationData.AdapterInterfaceType = Isa;
  274. CurrContextPtr->AdapterCount = 0;
  275. CurrContextPtr->PCIDevId = 0;
  276. isaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, CurrContextPtr);
  277. //
  278. // Return the smallest status.
  279. //
  280. LowStatus1 = (PCIStatus < EisaStatus ? PCIStatus : EisaStatus);
  281. LowStatus2 = (mcaStatus < isaStatus ? mcaStatus : isaStatus);
  282. return(LowStatus1 < LowStatus2 ? LowStatus1 : LowStatus2);
  283. } // end BLogicEntry()
  284. ULONG
  285. BLogicFindAdapter (
  286. IN PCARD_STRUC CardPtr,
  287. IN PVOID Context,
  288. IN PVOID BusInformation,
  289. IN PCHAR ArgumentString,
  290. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  291. OUT PBOOLEAN Again
  292. )
  293. /*++
  294. Routine Description:
  295. This function is called by the OS-specific port driver after
  296. the necessary storage has been allocated, to gather information
  297. about the adapter's configuration.
  298. Arguments:
  299. CardPtr - HBA miniport driver's adapter data storage
  300. Context - Register base address
  301. ConfigInfo - Configuration information structure describing HBA
  302. This structure is defined in PORT.H.
  303. Return Value:
  304. ULONG
  305. --*/
  306. {
  307. ULONG length;
  308. ULONG status;
  309. ULONG i;
  310. UCHAR adapterTid;
  311. UCHAR dmaChannel;
  312. UCHAR irq;
  313. UCHAR bit;
  314. UCHAR VesaCard = 0;
  315. UCHAR ThrowAway;
  316. PBASE_REGISTER baseIoAddress;
  317. BOOLEAN NoErrorOnWide = TRUE;
  318. PBL_CONTEXT CurrContextPtr = (PBL_CONTEXT)Context;
  319. //
  320. // Determine if there are any adapters installed. Determine installed
  321. // will initialize the BaseIoAddress if an adapter is found.
  322. //
  323. status = BLogicDetermineInstalled(CardPtr,
  324. ConfigInfo,
  325. (PBL_CONTEXT)CurrContextPtr,
  326. Again);
  327. //
  328. // If there are not adapter's found then return.
  329. //
  330. if ((status != SP_RETURN_FOUND) && (status != RETURN_FOUND_VESA)) {
  331. return(status);
  332. }
  333. baseIoAddress = CardPtr->BaseIoAddress;
  334. if (status == RETURN_FOUND_VESA) {
  335. VesaCard = 1;
  336. }
  337. //
  338. // Issue adapter command to get IRQ.
  339. //
  340. // Returns 3 data bytes:
  341. //
  342. // Byte 0 Dma Channel
  343. //
  344. // Byte 1 Interrupt Channel
  345. //
  346. // Byte 2 Adapter SCSI ID
  347. //
  348. if (!WriteCommandRegister(CardPtr, AC_RET_CONFIGURATION_DATA)) {
  349. DebugPrint((1,"BLogicFindAdapter: Get configuration data command failed\n"));
  350. return SP_RETURN_ERROR;
  351. }
  352. //
  353. // Determine DMA channel.
  354. //
  355. if (!ReadCommandRegister(CardPtr,&dmaChannel)) {
  356. DebugPrint((1,"BLogicFindAdapter: Couldn't read dma channel\n"));
  357. return SP_RETURN_ERROR;
  358. }
  359. /* EISA may have DMA channel disabled or MCA byte is not valid */
  360. /* also, vesa card always returns DMA channel 5 */
  361. if ((dmaChannel != 0) && (!VesaCard)
  362. && (ConfigInfo->AdapterInterfaceType != PCIBus)){
  363. WHICH_BIT(dmaChannel,bit);
  364. ConfigInfo->DmaChannel = bit;
  365. }
  366. DebugPrint((2,"BLogicFindAdapter: DMA channel is %x\n",
  367. ConfigInfo->DmaChannel));
  368. //
  369. // Determine hardware interrupt vector.
  370. //
  371. if (!ReadCommandRegister(CardPtr,&irq)) {
  372. DebugPrint((1,"BLogicFindAdapter: Couldn't read adapter irq\n"));
  373. return SP_RETURN_ERROR;
  374. }
  375. WHICH_BIT(irq, bit);
  376. //
  377. // BusInterruptLevel is already provided for us in the ConfigInfo
  378. // structure on the fully-compliant 946C boards - otherwise,
  379. // IRQ assignment from the 0Bh HBA command
  380. //
  381. if (!((ConfigInfo->AdapterInterfaceType == PCIBus) &&
  382. (CurrContextPtr->PCIDevId == 0x1040)))
  383. {
  384. ConfigInfo->BusInterruptLevel = (UCHAR) 9 + bit;
  385. }
  386. //
  387. // Determine what SCSI bus id the adapter is on.
  388. //
  389. if (!ReadCommandRegister(CardPtr,&adapterTid)) {
  390. DebugPrint((1,"BLogicFindAdapter: Couldn't read adapter SCSI id\n"));
  391. return SP_RETURN_ERROR;
  392. }
  393. if (!FinishHBACmd(CardPtr)) {
  394. DebugPrint((1,"BLogicFindAdapter: Setup info cmd failed\n"));
  395. return FALSE;
  396. }
  397. //
  398. // Set number of buses.
  399. //
  400. ConfigInfo->NumberOfBuses = 1;
  401. ConfigInfo->InitiatorBusId[0] = adapterTid;
  402. CardPtr->HostTargetId = adapterTid;
  403. // ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE;
  404. ConfigInfo->ScatterGather = TRUE;
  405. ConfigInfo->Master = TRUE;
  406. ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_DESCRIPTORS - 1;
  407. CardPtr->MailBoxArray = ScsiPortGetUncachedExtension(
  408. CardPtr,
  409. ConfigInfo,
  410. sizeof(NONCACHED_EXTENSION));
  411. if (CardPtr->MailBoxArray == NULL) {
  412. //
  413. // Log error.
  414. //
  415. ScsiPortLogError(
  416. CardPtr,
  417. NULL,
  418. 0,
  419. 0,
  420. 0,
  421. SP_INTERNAL_ADAPTER_ERROR,
  422. 6 << 16
  423. );
  424. return(SP_RETURN_ERROR);
  425. }
  426. //
  427. // Convert virtual to physical mailbox address.
  428. //
  429. CardPtr->MailBoxArray->MailboxPA =
  430. ScsiPortConvertPhysicalAddressToUlong(
  431. ScsiPortGetPhysicalAddress(CardPtr,
  432. NULL,
  433. CardPtr->MailBoxArray->Mbo,
  434. &length));
  435. //
  436. // Assume that physical address is below 16M
  437. //
  438. ASSERT(CardPtr->MailBoxArray->MailboxPA < 0x1000000);
  439. // check for wide support ONLY if on NT 3.5 platform */
  440. if (ConfigInfo->Length == CONFIG_INFO_VERSION_2)
  441. {
  442. CardPtr->Flags |= OS_SUPPORTS_WIDE;
  443. // default to non-wide support
  444. ConfigInfo->MaximumNumberOfTargets = 8;
  445. // turn on wide support if available
  446. NoErrorOnWide = TRUE;
  447. if (!WriteCommandRegister(CardPtr, AC_WIDE_SUPPORT)) {
  448. CardPtr->Flags &= ~WIDE_ENABLED;
  449. NoErrorOnWide = FALSE;
  450. }
  451. else if (!CheckInvalid(CardPtr)) {
  452. CardPtr->Flags &= ~WIDE_ENABLED;
  453. // DebugPrint((0,"BLogicFindAdapter: check invalid failed \n"));
  454. NoErrorOnWide = FALSE;
  455. }
  456. else if (!WriteCommandRegister(CardPtr, 0x01)) {
  457. CardPtr->Flags &= ~WIDE_ENABLED;
  458. NoErrorOnWide = FALSE;
  459. }
  460. if (!FinishHBACmd(CardPtr)) {
  461. CardPtr->Flags &= ~WIDE_ENABLED;
  462. NoErrorOnWide = FALSE;
  463. }
  464. else if (NoErrorOnWide) {
  465. CardPtr->Flags |= WIDE_ENABLED;
  466. ConfigInfo->MaximumNumberOfTargets = 16;
  467. }
  468. } /* end if NT 3.5, then check for wide support */
  469. DebugPrint((3,"BLogicFindAdapter: Configuration completed\n"));
  470. //
  471. // enable generation on interrupts to the host on HBAs that support
  472. // the 0x25 command used previously to disable generation of ints
  473. // during this routine's call to DetermineInstalled
  474. //
  475. if (!WriteCommandRegister(CardPtr,AC_INT_GENERATION_STATE)){
  476. DebugPrint((1,"BLogicFindAdapter: ints enable/disable cmd failed\n"));
  477. }
  478. else if (!CheckInvalid(CardPtr)) {
  479. DebugPrint((1,"BLogicDetInstalled: ints enable/disable cmd failed\n")); DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  480. }
  481. else{
  482. ThrowAway = ENABLE_INTS;
  483. if (!WriteCommandRegister(CardPtr,ThrowAway)){
  484. DebugPrint((1,"BLogicFindAdapter: ints enable/disable cmd failed\n"));
  485. }
  486. }
  487. if (!FinishHBACmd(CardPtr)) {
  488. // this cmd DOES NOT generate an interrupt - so
  489. // just check for command complete!
  490. if (!(ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)
  491. & (IOP_SCSI_HBA_IDLE))) {
  492. DebugPrint((1,"BLogicFindAdapter: ints enable/disable cmd failed\n"));
  493. }
  494. }
  495. //
  496. // Set up DMA type based on bus type
  497. //
  498. ConfigInfo->Dma32BitAddresses =
  499. (ConfigInfo->AdapterInterfaceType == Isa) ? FALSE : TRUE;
  500. return SP_RETURN_FOUND;
  501. } // end BLogicFindAdapter()
  502. BOOLEAN
  503. BLogicAdapterState(
  504. IN PCARD_STRUC CardPtr,
  505. IN PVOID Context,
  506. IN BOOLEAN SaveState
  507. )
  508. /*++
  509. Routine Description:
  510. The Buslogic adapters will take advantage of work done in the past to
  511. support Novell networks. This means any MSDOS mode driver will be set
  512. up to run without using mailboxes. This will save the work of having
  513. to save/restore mailbox locations for the MSDOS driver in this routine.
  514. Arguments:
  515. CardPtr - HBA miniport driver's adapter data storage
  516. Context - Register base address
  517. SaveState - TRUE == Save real mode state ; FALSE == Restore real mode state
  518. Return Value:
  519. TRUE - Save/Restore operation was successful.
  520. --*/
  521. {
  522. return TRUE;
  523. } // end BLogicAdapterState()
  524. BOOLEAN
  525. BLIsCloneIDByte(
  526. IN PCARD_STRUC CardPtr
  527. )
  528. /*++
  529. Routine Description:
  530. This routine performs the adapter ID command and determines if the
  531. adapter is potentially a BusLogic adapter.
  532. Arguments:
  533. CardPtr - HBA miniport data storage
  534. Return Value:
  535. TRUE if it looks like the adapter is a clone or if the command fails.
  536. FALSE otherwise.
  537. --*/
  538. {
  539. UCHAR byte;
  540. UCHAR specialOptions;
  541. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  542. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,
  543. IOP_INTERRUPT_RESET);
  544. if (!WriteCommandRegister(CardPtr, AC_ADAPTER_INQUIRY)) {
  545. return TRUE;
  546. }
  547. //
  548. // Byte 0.
  549. //
  550. if ((ReadCommandRegister(CardPtr, &byte)) == FALSE) {
  551. return TRUE;
  552. }
  553. //
  554. // Get the special options byte.
  555. //
  556. if ((ReadCommandRegister(CardPtr, &specialOptions)) == FALSE) {
  557. return TRUE;
  558. }
  559. //
  560. // Get the last two bytes and clear the interrupt.
  561. //
  562. if ((ReadCommandRegister(CardPtr, &byte)) == FALSE) {
  563. return TRUE;
  564. }
  565. if ((ReadCommandRegister(CardPtr, &byte)) == FALSE) {
  566. return TRUE;
  567. }
  568. if (!FinishHBACmd(CardPtr)) {
  569. DebugPrint((1,"BLogicIsClone: Setup info cmd failed\n"));
  570. return FALSE;
  571. }
  572. if ((specialOptions == 0x30) || (specialOptions == 0x42)) {
  573. //
  574. // This is an adaptec or AMI adapter.
  575. //
  576. return TRUE;
  577. }
  578. return FALSE;
  579. } // end BLIsCloneIDByte()
  580. ULONG
  581. BLogicDetermineInstalled(
  582. IN PCARD_STRUC CardPtr,
  583. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  584. IN OUT PBL_CONTEXT CurrContextPtr,
  585. OUT PBOOLEAN Again
  586. )
  587. /*++
  588. Routine Description:
  589. Determine if BusLogic SCSI adapter is installed in system
  590. by reading the status register as each base I/O address
  591. and looking for a pattern. If an adapter is found, the BaseIoAddres is
  592. initialized.
  593. Arguments:
  594. CardPtr - HBA miniport driver's adapter data storage
  595. ConfigInfo - Supplies the known configuraiton information.
  596. CurrContextPtr - Supplies the count of adapter slots which have been
  597. tested and, in the case of PCI, the Device ID.
  598. Again - Returns whehter the OS specific driver should call again.
  599. Return Value:
  600. Returns a status indicating whether a driver is present or not.
  601. --*/
  602. {
  603. PBASE_REGISTER baseIoAddress;
  604. PUCHAR ioSpace;
  605. UCHAR ThrowAway,TaggedQueueSupport,EISAConfigReg;
  606. UCHAR i;
  607. BOOLEAN configProvided = FALSE;
  608. UCHAR FoundVesaCard = 0;
  609. ULONG *AdapterAddrPtr;
  610. ULONG length;
  611. SCSI_PHYSICAL_ADDRESS PhysAddr;
  612. if (ConfigInfo->AdapterInterfaceType == Eisa)
  613. InittedEISABoards = 1;
  614. //
  615. // Get the system physical address for this card. The card uses I/O space.
  616. //
  617. AdapterAddrPtr = (ConfigInfo->AdapterInterfaceType == PCIBus) ?
  618. PciAdapterAddresses : AdapterAddresses;
  619. //
  620. // Scan though the adapter address looking for adapters.
  621. //
  622. ioSpace = NULL;
  623. while (AdapterAddrPtr[CurrContextPtr->AdapterCount] != 0) {
  624. //
  625. // Free any previously allocated ioSpace.
  626. //
  627. if (ioSpace) {
  628. ScsiPortFreeDeviceBase(
  629. CardPtr,
  630. ioSpace
  631. );
  632. }
  633. //
  634. // If the calling operating system has configuration information
  635. // already established for the driver then the RangeLength will be
  636. // set to zero instead of SP_UNINITIALIZED_VALUE. This is used
  637. // to indicate the condition and this routine will search for an
  638. // adapter based on the information provided.
  639. //
  640. configProvided = ((*ConfigInfo->AccessRanges)[0].RangeLength == 0) ? FALSE : TRUE;
  641. if (configProvided) {
  642. ioSpace = ScsiPortGetDeviceBase(
  643. CardPtr, // CardPtr
  644. ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType
  645. ConfigInfo->SystemIoBusNumber, // SystemIoBusNumber
  646. (*ConfigInfo->AccessRanges)[0].RangeStart,
  647. 0x16, // NumberOfBytes
  648. TRUE // InIoSpace
  649. );
  650. if (!ioSpace) {
  651. return SP_RETURN_NOT_FOUND;
  652. }
  653. } else {
  654. ioSpace = ScsiPortGetDeviceBase(
  655. CardPtr, // CardPtr
  656. ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType
  657. ConfigInfo->SystemIoBusNumber, // SystemIoBusNumber
  658. ScsiPortConvertUlongToPhysicalAddress(AdapterAddrPtr[CurrContextPtr->AdapterCount]),
  659. 0x16, // NumberOfBytes
  660. TRUE // InIoSpace
  661. );
  662. if (!ioSpace) {
  663. continue;
  664. }
  665. }
  666. baseIoAddress = (PBASE_REGISTER)ioSpace;
  667. //
  668. // Check to see if adapter present in system.
  669. //
  670. CardPtr->BaseIoAddress = baseIoAddress;
  671. DebugPrint((1,"BLogic: Base IO address is %x\n", baseIoAddress));
  672. //
  673. // Update the adapter count.
  674. //
  675. (CurrContextPtr->AdapterCount)++;
  676. //
  677. // Check to make sure the I/O range is not already in use
  678. //
  679. PhysAddr = ScsiPortConvertUlongToPhysicalAddress((ULONG)baseIoAddress);
  680. if (!(ScsiPortValidateRange(
  681. CardPtr, // CardPtr
  682. ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType
  683. ConfigInfo->SystemIoBusNumber, // SystemIoBusNumber
  684. PhysAddr,
  685. 4, // NumberOfBytes
  686. TRUE // InIoSpace
  687. ))) {
  688. continue;
  689. }
  690. if (((ScsiPortReadPortUchar((PUCHAR)baseIoAddress)) & (~0x2C)) == 0x10) {
  691. //
  692. // Before sending any other host adapter commands, try to disable
  693. // generation of interrupts to the host (HBA command 0x25).
  694. // On f.w. that support this command, we will be able
  695. // to initialize an HBA that is sharing an IRQ level with a
  696. // previously-initialized HBA on the same IRQ without winding up
  697. // in the ISR for the first HBA in an endless "not our interrupt"
  698. // loop due to level-triggered int generated by second HBA (not yet
  699. // registered by the OS for any ISR). This should allow us to share
  700. // interrupts on critical platforms such as PCI.
  701. //
  702. if (!WriteCommandRegister(CardPtr,AC_INT_GENERATION_STATE)){
  703. DebugPrint((1,"BLogicDetInstalled: ints enable/disable cmd failed\n"));
  704. }
  705. else if (!CheckInvalid(CardPtr)) {
  706. DebugPrint((1,"BLogicDetInstalled: ints enable/disable cmd failed\n")); DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  707. }
  708. else{
  709. ThrowAway = DISABLE_INTS;
  710. if (!WriteCommandRegister(CardPtr,ThrowAway)){
  711. DebugPrint((1,"BLogicDetInstalled: ints enable/disable cmd failed\n"));
  712. }
  713. }
  714. if (!FinishHBACmd(CardPtr)) {
  715. // this cmd DOES NOT generate an interrupt - so
  716. // just check for command complete!
  717. if (!(ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)
  718. & (IOP_SCSI_HBA_IDLE))) {
  719. DebugPrint((1,"BLogicDetInstalled: ints enable/disable cmd failed\n"));
  720. }
  721. }
  722. //
  723. // Check adapter inquiry to get rid of clones.
  724. //
  725. if (BLIsCloneIDByte(CardPtr)) {
  726. DebugPrint((1, "BLogicDetermineInstalled: Clone byte not BusLogic\n"));
  727. continue;
  728. }
  729. //
  730. // Send BusLogic Internal cmd (84h) to distinguish from clones
  731. //
  732. if (!WriteCommandRegister(CardPtr,AC_EXTENDED_FWREV)) {
  733. DebugPrint((1,"BLogicDetermineInstalled: Extended FW Rev command failed\n"));
  734. continue;
  735. }
  736. if (!ReadCommandRegister(CardPtr,&ThrowAway)) {
  737. DebugPrint((1,"BLogicDetermineInstalled: Extended FW Rev cmd failed\n"));
  738. continue;
  739. }
  740. if (!FinishHBACmd(CardPtr)) {
  741. DebugPrint((1,"BLogicDetermineInstalled: Extended FW Rev cmd failed\n"));
  742. continue;
  743. }
  744. //
  745. // Send Extended Setup Info cmd (8dh)
  746. //
  747. if (!WriteCommandRegister(CardPtr,
  748. AC_EXTENDED_SETUP_INFO)) {
  749. DebugPrint((1,"BLogicDetermineInstalled: Get Extended Setup Info cmd failed\n"));
  750. continue;
  751. }
  752. if (!WriteCommandRegister(CardPtr,
  753. 11)) { /* ask for 11 bytes */
  754. DebugPrint((1,"BLogicDetermineInstalled: Get Extended Setup Info cmd failed\n"));
  755. continue;
  756. }
  757. if (!ReadCommandRegister(CardPtr,&CardPtr->BusType)) {
  758. DebugPrint((1,"BLogicDetermineInstalled: Couldn't read parameter byte\n"));
  759. continue;
  760. }
  761. //
  762. // Throw away next 8 bytes
  763. //
  764. for (i = 0; i < 8; i ++)
  765. {
  766. if (!ReadCommandRegister(CardPtr,&ThrowAway)) {
  767. DebugPrint((1,"BLogicDetermineInstalled: Couldn't read parameter byte\n"));
  768. break;
  769. }
  770. }
  771. if (i != 8)
  772. continue;
  773. /* read EISA config reg - throw away byte for ISA and MCA */
  774. if (!ReadCommandRegister(CardPtr,&EISAConfigReg)) {
  775. DebugPrint((1,"BLogicDetermineInstalled: Couldn't read parameter byte\n"));
  776. continue;
  777. }
  778. if (!ReadCommandRegister(CardPtr,&TaggedQueueSupport)) {
  779. DebugPrint((1,"BLogicDetermineInstalled: Couldn't read parameter byte\n"));
  780. continue;
  781. }
  782. if (!FinishHBACmd(CardPtr)) {
  783. DebugPrint((1,"BLogicDetermineInstalled: Extended Setup info cmd failed\n"));
  784. continue;
  785. }
  786. if (TaggedQueueSupport != 0) {
  787. CardPtr->Flags |= TAGGED_QUEUING;
  788. }
  789. switch (CardPtr->BusType) {
  790. case ISA_HBA:
  791. if (ConfigInfo->AdapterInterfaceType != Isa)
  792. continue;
  793. break;
  794. case EISA_HBA:
  795. // EISA, VESA, and PCI HBAs all , reporting back as bus type
  796. // EISA, will always reflect accurate edge\level info in
  797. // in "EISAConfigReg" below - I checked with FW group on this
  798. ConfigInfo->InterruptMode = EISAConfigReg & LEVEL_TRIG ? LevelSensitive : Latched;
  799. if (ConfigInfo->AdapterInterfaceType == Eisa)
  800. {
  801. if (!(FindOurEISAId(CardPtr,ConfigInfo,baseIoAddress)))
  802. {
  803. FoundVesaCard = 1;
  804. }
  805. break;
  806. }
  807. else if (ConfigInfo->AdapterInterfaceType == Isa)
  808. {
  809. /* if we already reported this HBA as an EISA board */
  810. /* don't double report. Otherwise, this must be a VESA */
  811. /* board on an ISA-VESA motherboard. */
  812. if (InittedEISABoards)
  813. continue;
  814. else
  815. {
  816. FoundVesaCard = 1;
  817. break;
  818. }
  819. }
  820. else if (ConfigInfo->AdapterInterfaceType == PCIBus)
  821. break;
  822. case MCA_HBA:
  823. if (ConfigInfo->AdapterInterfaceType != MicroChannel)
  824. continue;
  825. break;
  826. } /* end switch */
  827. //
  828. // turn off ISA-compatible I/O mapping on compliant PCI HBAs.
  829. //
  830. if (ConfigInfo->AdapterInterfaceType == PCIBus)
  831. {
  832. //
  833. // Turn off ISA-compatible I/O mapping for this HBA
  834. //
  835. if (!WriteCommandRegister(CardPtr,AC_ISA_COMPATIBLE_SUPPORT)) {
  836. DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  837. continue;
  838. }
  839. else if (!CheckInvalid(CardPtr)) {
  840. DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  841. continue;
  842. }
  843. else{
  844. ThrowAway = DISABLE_ISA_MAPPING;
  845. if (!WriteCommandRegister(CardPtr,ThrowAway)){
  846. DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  847. continue;
  848. }
  849. }
  850. if (!FinishHBACmd(CardPtr)) {
  851. // this cmd DOES NOT generate an interrupt - so
  852. // just check for command complete!
  853. if (!(ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)
  854. & (IOP_SCSI_HBA_IDLE))) {
  855. DebugPrint((1,"BLogicDetermineInstalled: ISA Compatible Support Mode cmd failed\n"));
  856. continue;
  857. }
  858. }
  859. } // turn off ISA- compatible I/O mapping on PCI-compliant 946C cards
  860. //
  861. // An adapter has been found. Set the base address in the device
  862. // extension, and request another call.
  863. //
  864. *Again = TRUE;
  865. //
  866. // Fill in the access array information.
  867. //
  868. if (!configProvided) {
  869. (*ConfigInfo->AccessRanges)[0].RangeStart =
  870. ScsiPortConvertUlongToPhysicalAddress(
  871. AdapterAddresses[(CurrContextPtr->AdapterCount) - 1]);
  872. }
  873. (*ConfigInfo->AccessRanges)[0].RangeLength = 4;
  874. (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
  875. return(FoundVesaCard ? RETURN_FOUND_VESA : SP_RETURN_FOUND);
  876. } /* end if ((baseIoAddress) & (~0x2C)) == 0x10) */
  877. } /* end adapter count loop */
  878. //
  879. // The entire table has been searched and no adapters have been found.
  880. // There is no need to call again and the device base can now be freed.
  881. // Clear the adapter count for the next bus.
  882. //
  883. *Again = FALSE;
  884. CurrContextPtr->AdapterCount = 0;
  885. return(SP_RETURN_NOT_FOUND);
  886. } // end BLogicDetermineInstalled()
  887. ULONG
  888. FindOurEISAId(
  889. IN PCARD_STRUC CardPtr,
  890. IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  891. PBASE_REGISTER baseIoAddress
  892. )
  893. /*++
  894. Routine Description:
  895. Determine if BusLogic HBA is an EISA or VESA board. Try to match both
  896. our EISA ID and the base port of the board in question. If both match
  897. this is an EISA board. If not, this must be our VESA board.
  898. Arguments:
  899. CardPtr - HBA miniport driver's adapter data storage
  900. ConfigInfo - Supplies the known configuration information.
  901. baseIoAddress - Base IO port address for this HBA
  902. Return Value:
  903. Returns one if successful - means the card in question is an EISA card.
  904. Returns zero if unsuccessful - means the card in question is a VESA card.
  905. --*/
  906. {
  907. PEISA_ID eisaID;
  908. ULONG eisaSlotNumber;
  909. PVOID eisaAddress;
  910. UCHAR Port;
  911. //
  912. // Clear any high order base address bits.
  913. //
  914. baseIoAddress = (PBASE_REGISTER)((ULONG) baseIoAddress & 0xFFF);
  915. //
  916. // Check to see if adapter EISA ID can be found
  917. //
  918. for (eisaSlotNumber= 1; eisaSlotNumber<MAXIMUM_EISA_SLOTS; eisaSlotNumber++)
  919. {
  920. //
  921. // Get the system address for this card.
  922. // The card uses I/O space.
  923. //
  924. eisaAddress = ScsiPortGetDeviceBase(CardPtr,
  925. ConfigInfo->AdapterInterfaceType,
  926. ConfigInfo->SystemIoBusNumber,
  927. ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber),
  928. 0x1000,
  929. TRUE);
  930. eisaID =
  931. (PEISA_ID)((PUCHAR)eisaAddress + EISA_ADDRESS_BASE);
  932. if ((ScsiPortReadPortUchar(&eisaID->BoardId[0]) == 0x0A) &&
  933. (ScsiPortReadPortUchar(&eisaID->BoardId[1]) == 0xB3) &&
  934. ((ScsiPortReadPortUchar(&eisaID->BoardId[2]) == 0x42) ||
  935. (ScsiPortReadPortUchar(&eisaID->BoardId[2]) == 0x47)))
  936. {
  937. /* still need to look for IO port match because we could */
  938. /* have VESA and EISA BusLogic cards in same machine */
  939. Port = (ScsiPortReadPortUchar(&eisaID->IOPort[0]) & PORTMASK);
  940. switch (Port) {
  941. case 0:
  942. if ((ULONG)baseIoAddress == 0x330)
  943. {
  944. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  945. eisaSlotNumber,baseIoAddress));
  946. return(1);
  947. }
  948. break;
  949. case 1:
  950. if ((ULONG)baseIoAddress == 0x334)
  951. {
  952. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  953. eisaSlotNumber,baseIoAddress));
  954. return(1);
  955. }
  956. break;
  957. case 2:
  958. if ((ULONG)baseIoAddress == 0x230)
  959. {
  960. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  961. eisaSlotNumber,baseIoAddress));
  962. return(1);
  963. }
  964. break;
  965. case 3:
  966. if ((ULONG)baseIoAddress == 0x234)
  967. {
  968. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  969. eisaSlotNumber,baseIoAddress));
  970. return(1);
  971. }
  972. break;
  973. case 4:
  974. if ((ULONG)baseIoAddress == 0x130)
  975. {
  976. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  977. eisaSlotNumber,baseIoAddress));
  978. return(1);
  979. }
  980. break;
  981. case 5:
  982. if ((ULONG)baseIoAddress == 0x134)
  983. {
  984. DebugPrint((1,"BusLogic: EISA Adapter found at slot %d,port %x \n",
  985. eisaSlotNumber,baseIoAddress));
  986. return(1);
  987. }
  988. break;
  989. default:
  990. break;
  991. } /* end switch */
  992. } /* end if found BusLogic ID */
  993. } /* end for loop */
  994. DebugPrint((1,"BusLogic: VESA Adapter found at port %x\n",baseIoAddress));
  995. return(0);
  996. }
  997. BOOLEAN
  998. BLogicHwInitialize(
  999. IN PCARD_STRUC CardPtr
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine is a required entry point.
  1004. Arguments:
  1005. CardPtr - HBA miniport driver's adapter data storage
  1006. Return Value:
  1007. TRUE - if initialization successful.
  1008. FALSE - if initialization unsuccessful.
  1009. --*/
  1010. {
  1011. PNONCACHED_EXTENSION MailBoxArray =
  1012. CardPtr->MailBoxArray;
  1013. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  1014. UCHAR status;
  1015. ULONG i;
  1016. PDEV_STRUC DevStruc;
  1017. UCHAR TargID;
  1018. UCHAR Lun;
  1019. DebugPrint((2,"BLogicHwInitialize: Reset BusLogic HBA and SCSI bus\n"));
  1020. //
  1021. // Reset HBA.
  1022. //
  1023. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_SOFT_RESET);
  1024. ScsiPortStallExecution(500*1000);
  1025. //
  1026. // Wait up to 500 microseconds for adapter to initialize.
  1027. //
  1028. for (i = 0; i < 500; i++) {
  1029. ScsiPortStallExecution(1);
  1030. status = ScsiPortReadPortUchar(&CardPtr->BaseIoAddress->StatusRegister);
  1031. if (status & IOP_SCSI_HBA_IDLE) {
  1032. break;
  1033. }
  1034. }
  1035. //
  1036. // Check if reset failed or succeeded.
  1037. //
  1038. if (!(status & IOP_SCSI_HBA_IDLE) || !(status & IOP_MAILBOX_INIT_REQUIRED))
  1039. {
  1040. DebugPrint((0, "BLogicHwInitialize: Soft reset failed.\n"));
  1041. //
  1042. // If the soft reset does not work, try a hard reset.
  1043. //
  1044. if (!BLogicResetBus(CardPtr, 0)) {
  1045. DebugPrint((1,"BLogicHwInitialize: Reset SCSI bus failed\n"));
  1046. return FALSE;
  1047. }
  1048. //
  1049. // Inform the port driver that the bus has been reset.
  1050. //
  1051. ScsiPortNotification(ResetDetected, CardPtr, 0);
  1052. DebugPrint((1,"BLogicHwInitialize: Reset completed\n"));
  1053. }
  1054. else /* soft reset succeeded */
  1055. {
  1056. //
  1057. // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
  1058. //
  1059. ScsiPortCompleteRequest(CardPtr,
  1060. CardPtr->BusNum,
  1061. (UCHAR) -1,
  1062. (UCHAR) -1,
  1063. SRB_STATUS_BUS_RESET);
  1064. //
  1065. // Reinitialize Active CCBS pointer and counter in LUN extensions
  1066. //
  1067. for (TargID= 0; TargID < 8; TargID++)
  1068. for (Lun = 0; Lun < 8; Lun++)
  1069. {
  1070. if (DevStruc= (PDEV_STRUC) (ScsiPortGetLogicalUnit(CardPtr,0,TargID,Lun)))
  1071. {
  1072. DevStruc->CurrentCCB = 0;
  1073. DevStruc->NumActive = 0;
  1074. }
  1075. }
  1076. }
  1077. //
  1078. // Zero out mailboxes.
  1079. //
  1080. for (i=0; i<MB_COUNT; i++) {
  1081. PMBO mailboxOut;
  1082. PMBI mailboxIn;
  1083. mailboxIn = &MailBoxArray->Mbi[i];
  1084. mailboxOut = &MailBoxArray->Mbo[i];
  1085. mailboxOut->Command = mailboxIn->Status = 0;
  1086. }
  1087. CardPtr->StartMBO = (PMBO)(&MailBoxArray->Mbo);
  1088. CardPtr->CurrMBO = (PMBO)(&MailBoxArray->Mbo);
  1089. CardPtr->LastMBO = ((PMBO)(&MailBoxArray->Mbo) + (MB_COUNT - 1));
  1090. CardPtr->StartMBI =(PMBI)( &MailBoxArray->Mbi);
  1091. CardPtr->CurrMBI = (PMBI)(&MailBoxArray->Mbi);
  1092. CardPtr->LastMBI = ((PMBI)(&MailBoxArray->Mbi) + (MB_COUNT - 1));
  1093. DebugPrint((3,"BLogicHwInitialize: Initialize mailbox\n"));
  1094. if (!WriteCommandRegister(CardPtr,AC_MBOX_EXTENDED_INIT)) {
  1095. DebugPrint((1,"BLogicHWInitialize: Couldn't initialize mailboxes\n"));
  1096. return FALSE;
  1097. }
  1098. //
  1099. // Send Adapter number of mailbox locations.
  1100. //
  1101. if (!WriteCommandRegister(CardPtr,MB_COUNT)) {
  1102. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1103. return FALSE;
  1104. }
  1105. if (!WriteCommandRegister(CardPtr,
  1106. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte0)) {
  1107. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1108. return FALSE;
  1109. }
  1110. if (!WriteCommandRegister(CardPtr,
  1111. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte1)) {
  1112. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1113. return FALSE;
  1114. }
  1115. if (!WriteCommandRegister(CardPtr,
  1116. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte2)) {
  1117. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1118. return FALSE;
  1119. }
  1120. if (!WriteCommandRegister(CardPtr,
  1121. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte3)) {
  1122. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1123. return FALSE;
  1124. }
  1125. if (!FinishHBACmd(CardPtr)) {
  1126. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1127. return FALSE;
  1128. }
  1129. //
  1130. // Override default setting for bus on time. This makes floppy
  1131. // drives work better with this adapter.
  1132. //
  1133. if (!WriteCommandRegister(CardPtr, AC_SET_BUS_ON_TIME)) {
  1134. DebugPrint((1,"BlogicHWInitialize:Can't set bus on time\n"));
  1135. return FALSE;
  1136. } else if (!WriteCommandRegister(CardPtr, 0x05)) {
  1137. DebugPrint((1,"BlogicHWInitialize:Can't set bus on time\n"));
  1138. return FALSE;
  1139. }
  1140. if (!FinishHBACmd(CardPtr)) {
  1141. DebugPrint((1,"BLogicHWInitialize: Set BUS On time failed\n"));
  1142. return FALSE;
  1143. }
  1144. /* turn on wide support if available */
  1145. if (CardPtr->Flags & OS_SUPPORTS_WIDE)
  1146. {
  1147. // DebugPrint((0,"BLogicHwInitialize: about to send wide cmd\n"));
  1148. if (!WriteCommandRegister(CardPtr, AC_WIDE_SUPPORT)) {
  1149. CardPtr->Flags &= ~WIDE_ENABLED;
  1150. }
  1151. else if (!CheckInvalid(CardPtr)) {
  1152. CardPtr->Flags &= ~WIDE_ENABLED;
  1153. }
  1154. else if (!WriteCommandRegister(CardPtr, 0x01)) {
  1155. CardPtr->Flags &= ~WIDE_ENABLED;
  1156. }
  1157. if (!FinishHBACmd(CardPtr)) {
  1158. CardPtr->Flags &= ~WIDE_ENABLED;
  1159. }
  1160. else {
  1161. CardPtr->Flags |= WIDE_ENABLED;
  1162. }
  1163. } /* end if OS_SUPPORTS_WIDE */
  1164. return TRUE;
  1165. } // end BLogicHwInitialize()
  1166. BOOLEAN
  1167. BLogicStartIo(
  1168. IN PCARD_STRUC CardPtr,
  1169. IN PSCSI_REQUEST_BLOCK Srb
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. This routine is called from the SCSI port driver synchronized
  1174. with the kernel. The mailboxes are scanned for an empty one and
  1175. the CCB is written to it. Then the doorbell is rung and the
  1176. OS port driver is notified that the adapter can take
  1177. another request, if any are available.
  1178. Arguments:
  1179. CardPtr - HBA miniport driver's adapter data storage
  1180. Srb - IO request packet
  1181. Return Value:
  1182. TRUE
  1183. --*/
  1184. {
  1185. PNONCACHED_EXTENSION MailBoxArray =
  1186. CardPtr->MailBoxArray;
  1187. PCCB ccb;
  1188. PDEV_STRUC DevStruc;
  1189. PCCB ActiveCCB;
  1190. ULONG i = 0;
  1191. UCHAR MaxActive = 0;
  1192. UCHAR j;
  1193. DebugPrint((3,"BLogicStartIo: Enter routine\n"));
  1194. if (CardPtr->Flags & REINIT_REQUIRED)
  1195. {
  1196. if (!ReInitializeHBA(CardPtr,Srb->PathId))
  1197. {
  1198. DebugPrint((1,"BLogicStartIo: HBA reinitialization failed\n"));
  1199. return FALSE;
  1200. }
  1201. CardPtr->Flags &= (~REINIT_REQUIRED);
  1202. }
  1203. //
  1204. // Check if command is an ABORT request.
  1205. //
  1206. if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
  1207. //
  1208. // Get CCB to abort.
  1209. //
  1210. ccb = Srb->NextSrb->SrbExtension;
  1211. MaxActive =(Srb->NextSrb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) ?
  1212. MAXACTIVE_TAGGED : MAXACTIVE;
  1213. //
  1214. // Verify that CCB to abort is still outstanding.
  1215. //
  1216. DevStruc =
  1217. ScsiPortGetLogicalUnit(CardPtr,
  1218. Srb->PathId,
  1219. Srb->TargetId,
  1220. Srb->Lun);
  1221. for (j=DevStruc->NumActive, ActiveCCB = DevStruc->CurrentCCB;
  1222. j > 0; j--)
  1223. {
  1224. if (ActiveCCB != ccb)
  1225. ActiveCCB = ActiveCCB->NxtActiveCCB;
  1226. else
  1227. break;
  1228. }
  1229. if (j == 0)
  1230. {
  1231. DebugPrint((1, "BLogicStartIo: SRB to abort already completed\n"));
  1232. //
  1233. // Complete abort SRB.
  1234. //
  1235. Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
  1236. ScsiPortNotification(RequestComplete,
  1237. CardPtr,
  1238. Srb);
  1239. //
  1240. // Adapter ready for next request.
  1241. //
  1242. if (DevStruc->NumActive < MaxActive)
  1243. ScsiPortNotification(NextLuRequest,CardPtr,Srb->PathId,
  1244. Srb->TargetId,Srb->Lun);
  1245. else
  1246. ScsiPortNotification(NextRequest,CardPtr,NULL);
  1247. return TRUE;
  1248. }
  1249. //
  1250. // Set abort SRB for completion.
  1251. //
  1252. ccb->AbortSrb = Srb;
  1253. SendCCB(Srb,CardPtr,DevStruc);
  1254. if (DevStruc->NumActive < MaxActive)
  1255. ScsiPortNotification(NextLuRequest,CardPtr,Srb->PathId,
  1256. Srb->TargetId,Srb->Lun);
  1257. else
  1258. ScsiPortNotification(NextRequest,CardPtr,NULL);
  1259. return TRUE;
  1260. } /* end ABORT request handling */
  1261. ccb = Srb->SrbExtension;
  1262. ccb->SrbAddress = Srb; /* Save SRB back ptr in CCB */
  1263. MaxActive = (Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) ?
  1264. MAXACTIVE_TAGGED : MAXACTIVE;
  1265. DevStruc = ScsiPortGetLogicalUnit(CardPtr,Srb->PathId,Srb->TargetId,
  1266. Srb->Lun);
  1267. switch (Srb->Function) {
  1268. case SRB_FUNCTION_EXECUTE_SCSI:
  1269. //
  1270. // Get logical unit extension.
  1271. //
  1272. DevStruc->NumActive++;
  1273. //
  1274. // Build CCB.
  1275. //
  1276. BuildCcb(CardPtr, Srb);
  1277. SendCCB(Srb,CardPtr,DevStruc);
  1278. break;
  1279. case SRB_FUNCTION_RESET_BUS:
  1280. //
  1281. // Reset Adapter and SCSI bus.
  1282. //
  1283. DebugPrint((1, "BLogicStartIo: Reset bus request received\n"));
  1284. if (!BLogicResetBus(CardPtr,Srb->PathId)) {
  1285. DebugPrint((1,"BLogicStartIo: Reset bus failed\n"));
  1286. Srb->SrbStatus = SRB_STATUS_ERROR;
  1287. } else {
  1288. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  1289. }
  1290. ScsiPortNotification(RequestComplete,
  1291. CardPtr,
  1292. Srb);
  1293. break;
  1294. case SRB_FUNCTION_RESET_DEVICE:
  1295. DevStruc->NumActive++;
  1296. ccb->OperationCode = RESET_COMMAND;
  1297. ccb->TargID = Srb->TargetId;
  1298. ccb->Lun = Srb->Lun;
  1299. SendCCB(Srb,CardPtr,DevStruc);
  1300. ScsiPortNotification(RequestComplete,
  1301. CardPtr,
  1302. Srb);
  1303. break;
  1304. //
  1305. // Drop through to default.
  1306. //
  1307. default:
  1308. //
  1309. // Set error, complete request
  1310. //
  1311. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  1312. ScsiPortNotification(RequestComplete,CardPtr,Srb);
  1313. } // end switch
  1314. //
  1315. // Adapter ready for next request.
  1316. //
  1317. if (DevStruc->NumActive < MaxActive)
  1318. ScsiPortNotification(NextLuRequest,CardPtr,Srb->PathId,
  1319. Srb->TargetId,Srb->Lun);
  1320. else
  1321. ScsiPortNotification(NextRequest,CardPtr,NULL);
  1322. return TRUE;
  1323. } // end BLogicStartIo()
  1324. BOOLEAN
  1325. BLogicInterrupt(
  1326. IN PCARD_STRUC CardPtr
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. This is the interrupt service routine for the SCSI adapter.
  1331. It reads the interrupt register to determine if the adapter is indeed
  1332. the source of the interrupt and clears the interrupt at the device.
  1333. If the adapter is interrupting because a mailbox is full, the CCB is
  1334. retrieved to complete the request.
  1335. Arguments:
  1336. CardPtr - HBA miniport driver's adapter data storage
  1337. Return Value:
  1338. TRUE if MailboxIn full
  1339. --*/
  1340. {
  1341. PNONCACHED_EXTENSION MailBoxArray =
  1342. CardPtr->MailBoxArray;
  1343. PCCB ccb;
  1344. PSCSI_REQUEST_BLOCK srb,abortsrb;
  1345. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  1346. PMBI mailboxIn;
  1347. ULONG physicalCcb;
  1348. PDEV_STRUC DevStruc;
  1349. UCHAR mbox_compcode;
  1350. UCHAR InterruptFlags;
  1351. UCHAR MaxActive=0;
  1352. UCHAR TargID;
  1353. UCHAR Lun;
  1354. InterruptFlags = ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister);
  1355. DebugPrint((3,"BLogicInterrupt: Interrupt flags %x\n", InterruptFlags));
  1356. if (!(InterruptFlags & IOP_ANY_INTERRUPT)) {
  1357. DebugPrint((4,"BLogicInterrupt: Not our interrupt!\n"));
  1358. return FALSE;
  1359. }
  1360. else
  1361. /* Clear interrupt on adapter. */
  1362. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
  1363. //
  1364. // Determine cause of interrupt.
  1365. //
  1366. if (InterruptFlags & IOP_COMMAND_COMPLETE) {
  1367. //
  1368. // Adapter command completed.
  1369. //
  1370. DebugPrint((2,"BLogicInterrupt: Adapter Command complete\n"));
  1371. DebugPrint((3,"BLogicInterrupt: Status %x\n",
  1372. ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)));
  1373. return TRUE;
  1374. }
  1375. else if (InterruptFlags & IOP_SCSI_RESET_DETECTED) {
  1376. DebugPrint((1,"BLogicInterrupt: SCSI Reset detected\n"));
  1377. //
  1378. // Notify of reset.
  1379. //
  1380. //
  1381. // Reset HBA because firmware may be in confused state with
  1382. // respect to outstanding CCBs.
  1383. //
  1384. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_SOFT_RESET);
  1385. //
  1386. // Notify OS of SCSI bus reset.
  1387. //
  1388. ScsiPortNotification(ResetDetected,CardPtr,NULL);
  1389. // Complete all active requests for specified unit
  1390. ScsiPortCompleteRequest(CardPtr,
  1391. (UCHAR) 0,
  1392. (UCHAR) -1,
  1393. (UCHAR) -1,
  1394. SRB_STATUS_BUS_RESET);
  1395. //
  1396. // Reinitialize Active CCBS pointer and counter in LUN extensions
  1397. //
  1398. for (TargID= 0; TargID < 8; TargID++)
  1399. for (Lun = 0; Lun < 8; Lun++)
  1400. {
  1401. if (DevStruc=ScsiPortGetLogicalUnit(CardPtr,0,TargID,Lun))
  1402. {
  1403. DevStruc->CurrentCCB = 0;
  1404. DevStruc->NumActive = 0;
  1405. }
  1406. }
  1407. //
  1408. // Set flag indicating HBA reinitialization will be required before
  1409. // any new requests can be serviced (due to soft reset above).
  1410. //
  1411. CardPtr->Flags |= REINIT_REQUIRED;
  1412. }
  1413. else if (InterruptFlags & IOP_MBI_FULL) {
  1414. DebugPrint((3,"BLogicInterrupt: MBI Full\n"));
  1415. while (mailboxIn = DoneMbox(CardPtr))
  1416. {
  1417. physicalCcb = mailboxIn->Address;
  1418. DebugPrint((3, "BLogicInterrupt: Physical CCB %lx\n", physicalCcb));
  1419. /* Check if physical CCB is zero. ( to cover for hardware errs) */
  1420. if (!physicalCcb) {
  1421. DebugPrint((1,"BLogicInterrupt: Physical CCB address is 0\n"));
  1422. return TRUE;
  1423. }
  1424. //
  1425. // Convert Physical CCB to Virtual.
  1426. //
  1427. ccb = ScsiPortGetVirtualAddress(CardPtr, ScsiPortConvertUlongToPhysicalAddress(physicalCcb));
  1428. DebugPrint((3, "BLogicInterrupt: Virtual CCB %lx\n", ccb));
  1429. //
  1430. // Make sure the virtual address was found.
  1431. //
  1432. if (ccb == NULL) {
  1433. //
  1434. // A bad physcial address was return by the adapter.
  1435. // Log it as an error.
  1436. //
  1437. ScsiPortLogError(
  1438. CardPtr,
  1439. NULL,
  1440. 0,
  1441. CardPtr->HostTargetId,
  1442. 0,
  1443. SP_INTERNAL_ADAPTER_ERROR,
  1444. 5 << 8
  1445. );
  1446. return(TRUE);
  1447. }
  1448. mbox_compcode = mailboxIn->Status;
  1449. mailboxIn->Status = MBI_FREE; /* free this In Mailbox */
  1450. //
  1451. // Get SRB from CCB.
  1452. //
  1453. srb = ccb->SrbAddress;
  1454. //
  1455. // Get logical unit extension.
  1456. //
  1457. DevStruc =
  1458. ScsiPortGetLogicalUnit(CardPtr,
  1459. srb->PathId,
  1460. srb->TargetId,
  1461. srb->Lun);
  1462. if (mbox_compcode == MBI_NOT_FOUND) {
  1463. DebugPrint((1, "BLogicInterrupt: aborted CCB not found %lx\n", ccb));
  1464. continue;
  1465. }
  1466. if (!AdjustCCBqueue (ccb,DevStruc)) {
  1467. //
  1468. // We have no record of the CCB returned by the adapter.
  1469. // Log it as an error.
  1470. //
  1471. ScsiPortLogError(
  1472. CardPtr,
  1473. NULL,
  1474. 0,
  1475. CardPtr->HostTargetId,
  1476. 0,
  1477. SP_INTERNAL_ADAPTER_ERROR,
  1478. (7 << 8) | mbox_compcode
  1479. );
  1480. continue;
  1481. }
  1482. srb->ScsiStatus = ccb->TargetStatus;
  1483. DebugPrint((2, "BLogicInterrupt: SCSI Status %x\n", srb->ScsiStatus));
  1484. DebugPrint((2, "BLogicInterrupt: Adapter Status %x\n", ccb->HostStatus));
  1485. //
  1486. // Check MBI status.
  1487. //
  1488. switch (mbox_compcode) {
  1489. case MBI_SUCCESS:
  1490. srb->SrbStatus = SRB_STATUS_SUCCESS;
  1491. ASSERT(DevStruc->CurrentCCB);
  1492. break;
  1493. case MBI_ABORT:
  1494. DebugPrint((1, "BLogicInterrupt: CCB aborted\n"));
  1495. srb->SrbStatus = SRB_STATUS_ABORTED;
  1496. //
  1497. // Get the abort SRB (requested the abort) from CCB.
  1498. //
  1499. abortsrb = ccb->AbortSrb;
  1500. //
  1501. // Call notification routine for the aborted SRB.
  1502. //
  1503. ScsiPortNotification(RequestComplete,
  1504. CardPtr,
  1505. srb);
  1506. //
  1507. // Set status for completing abort request itself.
  1508. //
  1509. abortsrb->SrbStatus = SRB_STATUS_SUCCESS;
  1510. srb = abortsrb;
  1511. break;
  1512. case MBI_ERROR:
  1513. DebugPrint((2, "BLogicInterrupt: Error occurred\n"));
  1514. srb->SrbStatus = MapError(CardPtr, srb, ccb);
  1515. if (ccb->TargetStatus == 2)
  1516. if (ccb->RequestSenseLength != 1)
  1517. srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1518. break;
  1519. default:
  1520. //
  1521. // Log the error.
  1522. //
  1523. ScsiPortLogError(
  1524. CardPtr,
  1525. NULL,
  1526. 0,
  1527. CardPtr->HostTargetId,
  1528. 0,
  1529. SP_INTERNAL_ADAPTER_ERROR,
  1530. (1 << 8) | mbox_compcode
  1531. );
  1532. DebugPrint((1, "BLogicInterrupt: Unrecognized mailbox status\n"));
  1533. continue;
  1534. } // end switch on mailbox-in completion status
  1535. DevStruc->NumActive--;
  1536. MaxActive = (srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) ?
  1537. MAXACTIVE_TAGGED : MAXACTIVE;
  1538. ScsiPortNotification(RequestComplete,CardPtr,srb);
  1539. //
  1540. // Notify that we are ready for another request
  1541. //
  1542. if (DevStruc->NumActive == (MaxActive - 1))
  1543. ScsiPortNotification(NextLuRequest,CardPtr,srb->PathId,
  1544. srb->TargetId,srb->Lun);
  1545. else /* assume we already asked for req for this LUN */
  1546. ScsiPortNotification(NextRequest,CardPtr,NULL);
  1547. } /* while done MBI */
  1548. } /* end if MBI full */
  1549. else
  1550. { /* unexpected interrupt status */
  1551. ScsiPortLogError(
  1552. CardPtr,
  1553. NULL,
  1554. 0,
  1555. CardPtr->HostTargetId,
  1556. 0,
  1557. SP_INTERNAL_ADAPTER_ERROR,
  1558. (8 << 8)
  1559. );
  1560. DebugPrint((1, "BLogicInterrupt: Spurious Interrupt\n"));
  1561. }
  1562. return TRUE;
  1563. } // end BLogicInterrupt()
  1564. VOID
  1565. BuildCcb(
  1566. IN PCARD_STRUC CardPtr,
  1567. IN PSCSI_REQUEST_BLOCK Srb
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. Build CCB
  1572. Arguments:
  1573. DeviceExtenson
  1574. SRB
  1575. Return Value:
  1576. Nothing.
  1577. --*/
  1578. {
  1579. PCCB ccb = Srb->SrbExtension;
  1580. UCHAR *pchar;
  1581. USHORT i;
  1582. ULONG physReqSensePtr;
  1583. ULONG length;
  1584. DebugPrint((3,"BuildCcb: Enter routine\n"));
  1585. // zero-fill the CCB
  1586. pchar = (UCHAR *) ccb;
  1587. for (i=0; i < sizeof(CCB); i++)
  1588. *pchar++= 0;
  1589. ccb->SrbAddress = Srb; /* Save SRB back ptr in CCB */
  1590. //
  1591. // Set CCB Operation Code.
  1592. //
  1593. if (Srb->DataTransferLength > 0)
  1594. ccb->OperationCode = SCATTER_GATHER_COMMAND;
  1595. else
  1596. ccb->OperationCode = SCSI_INITIATOR_COMMAND;
  1597. //
  1598. // Set target id and LUN.
  1599. //
  1600. ccb->TargID = Srb->TargetId;
  1601. ccb->Lun = Srb->Lun;
  1602. if ((CardPtr->Flags & TAGGED_QUEUING) &&
  1603. (Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE))
  1604. {
  1605. if (CardPtr->Flags & WIDE_ENABLED)
  1606. ccb->ControlByte |= ENABLE_TQ;
  1607. else
  1608. ccb->Lun |= ENABLE_TQ;
  1609. switch (Srb->QueueAction) {
  1610. case ORDERED_TAG:
  1611. ccb->Lun |= ORDERED;
  1612. break;
  1613. case SIMPLE_TAG:
  1614. ccb->Lun |= SIMPLE;
  1615. break;
  1616. case HEAD_OF_QUEUE:
  1617. ccb->Lun |= QUEUEHEAD;
  1618. break;
  1619. } /* end switch */
  1620. }
  1621. //
  1622. // Set transfer direction bit.
  1623. //
  1624. switch (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) {
  1625. case SRB_FLAGS_DATA_OUT:
  1626. ccb->ControlByte |= CCB_DATA_XFER_OUT;
  1627. break;
  1628. case SRB_FLAGS_DATA_IN:
  1629. ccb->ControlByte |= CCB_DATA_XFER_IN;
  1630. break;
  1631. case SRB_FLAGS_NO_DATA_TRANSFER:
  1632. ccb->ControlByte |= CCB_DATA_XFER_IN | CCB_DATA_XFER_OUT;
  1633. break;
  1634. }
  1635. if (!(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) &&
  1636. Srb->SenseInfoBufferLength != 0) {
  1637. ccb->RequestSenseLength = Srb->SenseInfoBufferLength;
  1638. physReqSensePtr = ScsiPortConvertPhysicalAddressToUlong(
  1639. ScsiPortGetPhysicalAddress(CardPtr, Srb,
  1640. Srb->SenseInfoBuffer, &length));
  1641. ccb->SensePointer = physReqSensePtr;
  1642. }
  1643. else
  1644. //
  1645. // 01h disables auto request sense.
  1646. //
  1647. ccb->RequestSenseLength = 1;
  1648. //
  1649. // Set CDB length and copy to CCB.
  1650. //
  1651. ccb->CdbLength = (UCHAR)Srb->CdbLength;
  1652. ScsiPortMoveMemory(ccb->Cdb, Srb->Cdb, ccb->CdbLength);
  1653. //
  1654. // Build SDL in CCB if data transfer.
  1655. //
  1656. if (Srb->DataTransferLength > 0) {
  1657. BuildSdl(CardPtr, Srb);
  1658. }
  1659. //
  1660. // Move -1 to Target Status to indicate
  1661. // CCB has not completed.
  1662. //
  1663. ccb->TargetStatus = 0xff;
  1664. return;
  1665. } // end BuildCcb()
  1666. VOID
  1667. BuildSdl(
  1668. IN PCARD_STRUC CardPtr,
  1669. IN PSCSI_REQUEST_BLOCK Srb
  1670. )
  1671. /*++
  1672. Routine Description:
  1673. This routine builds a scatter/gather descriptor list for the CCB.
  1674. Arguments:
  1675. CardPtr
  1676. Srb
  1677. Return Value:
  1678. None
  1679. --*/
  1680. {
  1681. PVOID dataPointer = Srb->DataBuffer;
  1682. ULONG bytesLeft = Srb->DataTransferLength;
  1683. PCCB ccb = Srb->SrbExtension;
  1684. PSDL sdl = &ccb->Sdl;
  1685. PSGD sgd;
  1686. ULONG physicalSdl;
  1687. ULONG physicalAddress;
  1688. ULONG length;
  1689. ULONG i = 0;
  1690. DebugPrint((3,"BuildSdl: Enter routine\n"));
  1691. //
  1692. // Get physical SDL address.
  1693. //
  1694. physicalSdl = ScsiPortConvertPhysicalAddressToUlong(
  1695. ScsiPortGetPhysicalAddress(CardPtr, NULL,
  1696. sdl, &length));
  1697. //
  1698. // Assume physical memory contiguous for sizeof(SDL) bytes.
  1699. //
  1700. ASSERT(length >= sizeof(SDL));
  1701. sgd = sdl->Sgd;
  1702. //
  1703. // Create SDL segment descriptors.
  1704. //
  1705. do {
  1706. DebugPrint((3, "BuildSdl: Data buffer %lx\n", dataPointer));
  1707. //
  1708. // Get physical address and length of contiguous
  1709. // physical buffer.
  1710. //
  1711. physicalAddress =
  1712. ScsiPortConvertPhysicalAddressToUlong(
  1713. ScsiPortGetPhysicalAddress(CardPtr,
  1714. Srb,
  1715. dataPointer,
  1716. &length));
  1717. DebugPrint((3, "BuildSdl: Physical address %lx\n", physicalAddress));
  1718. DebugPrint((3, "BuildSdl: Data length %lx\n", length));
  1719. DebugPrint((3, "BuildSdl: Bytes left %lx\n", bytesLeft));
  1720. //
  1721. // If length of physical memory is more
  1722. // than bytes left in transfer, use bytes
  1723. // left as final length.
  1724. //
  1725. if (length > bytesLeft) {
  1726. length = bytesLeft;
  1727. }
  1728. sgd->Length = length;
  1729. sgd->Address = physicalAddress;
  1730. sgd++;
  1731. i++;
  1732. //
  1733. // Adjust counts.
  1734. //
  1735. dataPointer = (PUCHAR)dataPointer + length;
  1736. bytesLeft -= length;
  1737. } while (bytesLeft);
  1738. //
  1739. // Write Scatter/Gather Descriptor List length to CCB.
  1740. //
  1741. ccb->DataLength = i * sizeof(SGD);
  1742. DebugPrint((3,"BuildSdl: S/G list length is %d\n", ccb->DataLength));
  1743. if (ccb->DataLength > 8)
  1744. DebugPrint((3,"BuildSdl: Multiple elements in S/G list"));
  1745. //
  1746. // Write SDL address to CCB.
  1747. //
  1748. ccb->DataPointer = (PVOID) physicalSdl;
  1749. DebugPrint((3,"BuildSdl: SDL address is %lx\n", sdl));
  1750. DebugPrint((3,"BuildSdl: CCB address is %lx\n", ccb));
  1751. return;
  1752. } // end BuildSdl()
  1753. BOOLEAN
  1754. BLogicResetBus(
  1755. IN PCARD_STRUC CardPtr,
  1756. IN ULONG PathId
  1757. )
  1758. /*++
  1759. Routine Description:
  1760. Reset BusLogic SCSI adapter and SCSI bus.
  1761. Initialize adapter mailbox.
  1762. Arguments:
  1763. CardPtr - HBA miniport driver's adapter data storage
  1764. Return Value:
  1765. Nothing.
  1766. --*/
  1767. {
  1768. UCHAR TargID,Lun;
  1769. PDEV_STRUC DevStruc;
  1770. DebugPrint((2,"BLogicResetBus: Reset BusLogic HBA and SCSI bus\n"));
  1771. if (!ResetBus(CardPtr,PathId)) {
  1772. DebugPrint((1,"BLogicResetBus: Reset bus failed\n"));
  1773. return FALSE;
  1774. }
  1775. //
  1776. // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
  1777. //
  1778. ScsiPortCompleteRequest(CardPtr,
  1779. (UCHAR) PathId,
  1780. (UCHAR) -1,
  1781. (UCHAR) -1,
  1782. SRB_STATUS_BUS_RESET);
  1783. //
  1784. // Reinitialize Active CCBS pointer and counter in LUN extensions
  1785. //
  1786. for (TargID= 0; TargID < 8; TargID++)
  1787. for (Lun = 0; Lun < 8; Lun++)
  1788. {
  1789. if (DevStruc=ScsiPortGetLogicalUnit(CardPtr,0,TargID,Lun))
  1790. {
  1791. DevStruc->CurrentCCB = 0;
  1792. DevStruc->NumActive = 0;
  1793. }
  1794. }
  1795. return TRUE;
  1796. } // end BLogicResetBus()
  1797. BOOLEAN
  1798. ResetBus(
  1799. IN PCARD_STRUC CardPtr,
  1800. IN ULONG PathId
  1801. )
  1802. /*++
  1803. Routine Description:
  1804. Reset BusLogic SCSI adapter and SCSI bus.
  1805. Initialize adapter mailbox.
  1806. Don't do callback on outstanding SRBs
  1807. Arguments:
  1808. CardPtr - HBA miniport driver's adapter data storage
  1809. Return Value:
  1810. Nothing.
  1811. --*/
  1812. {
  1813. PNONCACHED_EXTENSION MailBoxArray =
  1814. CardPtr->MailBoxArray;
  1815. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  1816. ULONG i;
  1817. PMBO mailboxOut;
  1818. PMBI mailboxIn;
  1819. UCHAR status;
  1820. DebugPrint((2,"ResetBus: Reset BusLogic HBA and SCSI bus\n"));
  1821. //
  1822. // Reset SCSI chip.
  1823. //
  1824. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET);
  1825. // Separated out the previously-removed routine ReInitializeHBA
  1826. // because it is now called by StartIO as well
  1827. if (!ReInitializeHBA(CardPtr,PathId)) {
  1828. DebugPrint((1,"ResetBus: Reset bus failed\n"));
  1829. return FALSE;
  1830. }
  1831. return TRUE;
  1832. } // end ResetBus()
  1833. BOOLEAN
  1834. ReInitializeHBA(
  1835. IN PCARD_STRUC CardPtr,
  1836. IN ULONG PathId
  1837. )
  1838. /*++
  1839. Routine Description:
  1840. Wait for HBA to reinitialize.
  1841. Initialize adapter mailbox.
  1842. Arguments:
  1843. CardPtr - HBA miniport driver's adapter data storage
  1844. Return Value:
  1845. Nothing.
  1846. --*/
  1847. {
  1848. PNONCACHED_EXTENSION MailBoxArray =
  1849. CardPtr->MailBoxArray;
  1850. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  1851. ULONG i;
  1852. PMBO mailboxOut;
  1853. PMBI mailboxIn;
  1854. UCHAR status;
  1855. ScsiPortStallExecution(500 * 1000);
  1856. //
  1857. // Wait up to 500 microseconds for adapter to initialize.
  1858. //
  1859. for (i = 0; i < 500; i++) {
  1860. ScsiPortStallExecution(1);
  1861. status = ScsiPortReadPortUchar(&CardPtr->BaseIoAddress->StatusRegister);
  1862. if (status & IOP_SCSI_HBA_IDLE) {
  1863. break;
  1864. }
  1865. }
  1866. if (!(status & IOP_SCSI_HBA_IDLE)) {
  1867. return(FALSE);
  1868. }
  1869. //
  1870. // Zero out mailboxes.
  1871. //
  1872. for (i=0,mailboxIn = MailBoxArray->Mbi,mailboxOut = MailBoxArray->Mbo;
  1873. i<MB_COUNT; i++, mailboxIn++,mailboxOut++) {
  1874. mailboxOut->Command = mailboxIn->Status = 0;
  1875. }
  1876. CardPtr->StartMBO = (PMBO)(&MailBoxArray->Mbo);
  1877. CardPtr->CurrMBO = (PMBO)(&MailBoxArray->Mbo);
  1878. CardPtr->LastMBO = ((PMBO)(&MailBoxArray->Mbo) + (MB_COUNT - 1));
  1879. CardPtr->StartMBI =(PMBI)( &MailBoxArray->Mbi);
  1880. CardPtr->CurrMBI = (PMBI)(&MailBoxArray->Mbi);
  1881. CardPtr->LastMBI = ((PMBI)(&MailBoxArray->Mbi) + (MB_COUNT - 1));
  1882. DebugPrint((3,"ReInitializeHBA: Initialize mailbox\n"));
  1883. if (!WriteCommandRegister(CardPtr,AC_MBOX_EXTENDED_INIT)) {
  1884. DebugPrint((1,"ReInitializeHBA: Couldn't initialize mailboxes\n"));
  1885. return FALSE;
  1886. }
  1887. //
  1888. // Send Adapter number of mailbox locations.
  1889. //
  1890. if (!WriteCommandRegister(CardPtr,MB_COUNT)) {
  1891. DebugPrint((1,"ReInitializeHBA: Extended InitMboxes failed\n"));
  1892. return FALSE;
  1893. }
  1894. if (!WriteCommandRegister(CardPtr,
  1895. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte0)) {
  1896. DebugPrint((1,"ReInitializeHBA: Extended InitMboxes failed\n"));
  1897. return FALSE;
  1898. }
  1899. if (!WriteCommandRegister(CardPtr,
  1900. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte1)) {
  1901. DebugPrint((1,"ReInitializeHBA: Extended InitMboxes failed\n"));
  1902. return FALSE;
  1903. }
  1904. if (!WriteCommandRegister(CardPtr,
  1905. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte2)) {
  1906. DebugPrint((1,"ReInitializeHBA: Extended InitMboxes failed\n"));
  1907. return FALSE;
  1908. }
  1909. if (!WriteCommandRegister(CardPtr,
  1910. ((PFOUR_BYTE)&MailBoxArray->MailboxPA)->Byte3)) {
  1911. DebugPrint((1,"ReInitializeHBA: Extended InitMboxes failed\n"));
  1912. return FALSE;
  1913. }
  1914. if (!FinishHBACmd(CardPtr)) {
  1915. DebugPrint((1,"BLogicHWInitialize: Extended InitMboxes failed\n"));
  1916. return FALSE;
  1917. }
  1918. /* turn on wide support if available */
  1919. if (CardPtr->Flags & OS_SUPPORTS_WIDE)
  1920. {
  1921. // DebugPrint((0,"ReInitializeHBA: about to send wide cmd\n"));
  1922. if (!WriteCommandRegister(CardPtr, AC_WIDE_SUPPORT)) {
  1923. CardPtr->Flags &= ~WIDE_ENABLED;
  1924. }
  1925. else if (!CheckInvalid(CardPtr)) {
  1926. CardPtr->Flags &= ~WIDE_ENABLED;
  1927. }
  1928. else if (!WriteCommandRegister(CardPtr, 0x01)) {
  1929. CardPtr->Flags &= ~WIDE_ENABLED;
  1930. }
  1931. if (!FinishHBACmd(CardPtr)) {
  1932. CardPtr->Flags &= ~WIDE_ENABLED;
  1933. }
  1934. else {
  1935. CardPtr->Flags |= WIDE_ENABLED;
  1936. }
  1937. } /* end if OS_SUPPORTS_WIDE */
  1938. return TRUE;
  1939. } // end ReInitializeHBA()
  1940. UCHAR
  1941. MapError(
  1942. IN PCARD_STRUC CardPtr,
  1943. IN PSCSI_REQUEST_BLOCK Srb,
  1944. IN PCCB Ccb
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. Translate BusLogic error to SRB error, and log an error if necessary.
  1949. Arguments:
  1950. CardPtr - The hardware device extension.
  1951. Srb - The failing Srb.
  1952. Ccb - Command Control Block contains error.
  1953. Return Value:
  1954. SRB Error
  1955. --*/
  1956. {
  1957. UCHAR status;
  1958. ULONG logError = 0;
  1959. switch (Ccb->HostStatus) {
  1960. case CCB_COMPLETE:
  1961. return SRB_STATUS_ERROR;
  1962. case CCB_SELECTION_TIMEOUT:
  1963. return SRB_STATUS_SELECTION_TIMEOUT;
  1964. case CCB_DATA_OVER_UNDER_RUN:
  1965. status = SRB_STATUS_DATA_OVERRUN;
  1966. //
  1967. // Don't log the protocol error anymore. it floods the system
  1968. // for underruns as well
  1969. //
  1970. // logError = SP_PROTOCOL_ERROR;
  1971. //
  1972. break;
  1973. case CCB_UNEXPECTED_BUS_FREE:
  1974. status = SRB_STATUS_UNEXPECTED_BUS_FREE;
  1975. logError = SP_UNEXPECTED_DISCONNECT;
  1976. break;
  1977. case CCB_PHASE_SEQUENCE_FAIL:
  1978. case CCB_INVALID_DIRECTION:
  1979. status = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
  1980. logError = SP_PROTOCOL_ERROR;
  1981. break;
  1982. case CCB_BAD_MBO_COMMAND:
  1983. case CCB_INVALID_OP_CODE:
  1984. case CCB_BAD_LINKED_LUN:
  1985. case CCB_DUPLICATE_CCB:
  1986. case CCB_INVALID_CCB:
  1987. status = SRB_STATUS_INVALID_REQUEST;
  1988. logError = SP_INTERNAL_ADAPTER_ERROR;
  1989. break;
  1990. default:
  1991. status = SRB_STATUS_ERROR;
  1992. logError = SP_INTERNAL_ADAPTER_ERROR;
  1993. break;
  1994. }
  1995. if(logError) {
  1996. ScsiPortLogError(
  1997. CardPtr,
  1998. Srb,
  1999. Srb->PathId,
  2000. Srb->TargetId,
  2001. Srb->Lun,
  2002. logError,
  2003. (2 << 8) | Ccb->HostStatus
  2004. );
  2005. }
  2006. return(status);
  2007. } // end MapError()
  2008. BOOLEAN
  2009. ReadCommandRegister(
  2010. IN PCARD_STRUC CardPtr,
  2011. OUT PUCHAR DataByte
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. Read command register.
  2016. Arguments:
  2017. DeviceExtesion - Pointer to adapder extension
  2018. DataByte - Byte read from register
  2019. Return Value:
  2020. TRUE if command register read.
  2021. FALSE if timed out waiting for adapter.
  2022. --*/
  2023. {
  2024. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  2025. ULONG i;
  2026. //
  2027. // Wait up to 500 microseconds for adapter to be ready.
  2028. //
  2029. for (i=0; i<500; i++) {
  2030. if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
  2031. IOP_DATA_IN_PORT_FULL) {
  2032. //
  2033. // Adapter ready. Break out of loop.
  2034. //
  2035. break;
  2036. } else {
  2037. //
  2038. // Stall 1 microsecond before
  2039. // trying again.
  2040. //
  2041. ScsiPortStallExecution(1);
  2042. }
  2043. }
  2044. if (i==500) {
  2045. ScsiPortLogError(
  2046. CardPtr,
  2047. NULL,
  2048. 0,
  2049. CardPtr->HostTargetId,
  2050. 0,
  2051. SP_INTERNAL_ADAPTER_ERROR,
  2052. 3 << 8
  2053. );
  2054. DebugPrint((1, "BLogic:ReadCommandRegister: Read command timed out\n"));
  2055. return FALSE;
  2056. }
  2057. *DataByte = ScsiPortReadPortUchar(&baseIoAddress->CommandRegister);
  2058. return TRUE;
  2059. } // end ReadCommandRegister()
  2060. BOOLEAN
  2061. WriteCommandRegister(
  2062. IN PCARD_STRUC CardPtr,
  2063. IN UCHAR AdapterCommand
  2064. )
  2065. /*++
  2066. Routine Description:
  2067. Write operation code to command register.
  2068. Arguments:
  2069. DeviceExtesion - Pointer to adapter extension
  2070. AdapterCommand - Value to be written to register
  2071. Return Value:
  2072. TRUE if command sent.
  2073. FALSE if timed out waiting for adapter.
  2074. --*/
  2075. {
  2076. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  2077. ULONG i;
  2078. //
  2079. // Wait up to 500 microseconds for adapter to be ready.
  2080. //
  2081. for (i=0; i<500; i++) {
  2082. if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
  2083. IOP_COMMAND_DATA_OUT_FULL) {
  2084. //
  2085. // Stall 1 microsecond before
  2086. // trying again.
  2087. //
  2088. ScsiPortStallExecution(1);
  2089. } else {
  2090. //
  2091. // Adapter ready. Break out of loop.
  2092. //
  2093. break;
  2094. }
  2095. }
  2096. if (i==500) {
  2097. ScsiPortLogError(
  2098. CardPtr,
  2099. NULL,
  2100. 0,
  2101. CardPtr->HostTargetId,
  2102. 0,
  2103. SP_INTERNAL_ADAPTER_ERROR,
  2104. 4 << 8
  2105. );
  2106. DebugPrint((1, "BLogic:WriteCommandRegister: Write command timed out\n"));
  2107. return FALSE;
  2108. }
  2109. ScsiPortWritePortUchar(&baseIoAddress->CommandRegister, AdapterCommand);
  2110. return TRUE;
  2111. } // end WriteCommandRegister()
  2112. BOOLEAN
  2113. FinishHBACmd(
  2114. IN PCARD_STRUC CardPtr
  2115. )
  2116. /*++
  2117. Routine Description:
  2118. Wait for command complete interrupt, clear interrupt, chk cmd status.
  2119. Arguments:
  2120. CardPtr - Pointer to adapter extension
  2121. Return Value:
  2122. TRUE if command completed successfully.
  2123. FALSE if timed out waiting for adapter or invalid command.
  2124. --*/
  2125. {
  2126. ULONG i;
  2127. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  2128. for (i=0; i<500; i++) {
  2129. if (!((ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) &
  2130. (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))==
  2131. (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))) {
  2132. //
  2133. // Stall 1 microsecond before
  2134. // trying again.
  2135. //
  2136. ScsiPortStallExecution(1);
  2137. } else {
  2138. //
  2139. // Adapter ready. Break out of loop.
  2140. //
  2141. break;
  2142. }
  2143. }
  2144. if (i==500) {
  2145. DebugPrint((1, "BLogic:FinishHBACmd: Wait for CmdCmplt & AnyIntr failed\n"));
  2146. return FALSE;
  2147. }
  2148. ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET);
  2149. if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
  2150. (IOP_INVALID_COMMAND)) {
  2151. return FALSE;
  2152. }
  2153. return TRUE;
  2154. } // end FinishHBACmd()
  2155. BOOLEAN
  2156. CheckInvalid(
  2157. IN PCARD_STRUC CardPtr
  2158. )
  2159. /*++
  2160. Routine Description:
  2161. Read status register to check for invalid command.
  2162. Arguments:
  2163. DeviceExtesion - Pointer to adapder extension
  2164. DataByte - Byte read from register
  2165. Return Value:
  2166. FALSE if invalid command bit on or timed out waiting for adapter.
  2167. TRUE if everything's o.k.
  2168. --*/
  2169. {
  2170. PBASE_REGISTER baseIoAddress = CardPtr->BaseIoAddress;
  2171. ULONG i;
  2172. ScsiPortStallExecution(500 * 1000);
  2173. //
  2174. // Wait up to 500 microseconds for adapter to be ready.
  2175. //
  2176. for (i=0; i<500; i++) {
  2177. if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) &
  2178. IOP_COMMAND_COMPLETE) {
  2179. //
  2180. // Adapter command complete. Break out of loop.
  2181. //
  2182. break;
  2183. } else {
  2184. //
  2185. // Stall 1 microsecond before
  2186. // trying again.
  2187. //
  2188. ScsiPortStallExecution(1);
  2189. }
  2190. }
  2191. if (i==500) {
  2192. // if command not complete, must not be invalid
  2193. return TRUE;
  2194. }
  2195. if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) &
  2196. IOP_INVALID_COMMAND)
  2197. return FALSE;
  2198. else
  2199. return TRUE;
  2200. } // end CheckInvalid()
  2201. BOOLEAN
  2202. SendCCB(
  2203. IN PSCSI_REQUEST_BLOCK Srb,
  2204. IN PCARD_STRUC CardPtr,
  2205. IN PDEV_STRUC DevStruc
  2206. )
  2207. /*++
  2208. Routine Description:
  2209. Finds empty outgoing Mbox, stuffs CCB into it and sends start command.
  2210. Arguments:
  2211. CardPtr - Pointer to adapter extension
  2212. Srb - Pointer to SCSI Request Block
  2213. DevStruc - Pointer to device (TAR/LUN) structure
  2214. Return Value:
  2215. TRUE if command completed successfully.
  2216. --*/
  2217. {
  2218. PMBO mboxOut;
  2219. ULONG physicalCCB;
  2220. PCCB ccb;
  2221. ULONG length;
  2222. USHORT i;
  2223. while (1) /* wait for free mbox out */
  2224. {
  2225. for (i=0, mboxOut = CardPtr->CurrMBO ; i< MB_COUNT; i++,mboxOut++)
  2226. { /* look for an open slot */
  2227. if (mboxOut > CardPtr->LastMBO)
  2228. mboxOut = CardPtr->StartMBO;
  2229. if (mboxOut->Command == MBO_FREE)
  2230. {
  2231. /* Insert Phys addr of CCB into MBO */
  2232. if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND)
  2233. ccb = (PCCB)(Srb->SrbExtension);
  2234. else
  2235. ccb = (PCCB)(Srb->NextSrb->SrbExtension);
  2236. physicalCCB = ScsiPortConvertPhysicalAddressToUlong(
  2237. ScsiPortGetPhysicalAddress(CardPtr, NULL, ccb, &length));
  2238. //
  2239. // Assume physical address is contiguous for size of CCB.
  2240. //
  2241. ASSERT(length >= sizeof(CCB));
  2242. mboxOut->Address = physicalCCB;
  2243. if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND) {
  2244. /* insert this SRB into active queue for this device */
  2245. ccb->NxtActiveCCB = DevStruc->CurrentCCB;
  2246. DevStruc->CurrentCCB = ccb;
  2247. mboxOut->Command = MBO_START;
  2248. }
  2249. else
  2250. mboxOut->Command = MBO_ABORT;
  2251. CardPtr->CurrMBO = mboxOut + 1;
  2252. if (!WriteCommandRegister(CardPtr,AC_START_SCSI_COMMAND)) {
  2253. DebugPrint((1,"BLogicStartIo: Can't write command to adapter\n"));
  2254. }
  2255. return TRUE;
  2256. } /* end for found a free MBO */
  2257. } /* end for 0 to mbox count */
  2258. } /* end while forever */
  2259. } /* end SendCCB() */
  2260. PMBI
  2261. DoneMbox(
  2262. IN PCARD_STRUC CardPtr
  2263. )
  2264. /*++
  2265. Routine Description:
  2266. Finds Full incoming Mbox
  2267. Arguments:
  2268. CardPtr - Pointer to adapter extension
  2269. Return Value:
  2270. Pointer to full MBI if full found, FALSE if not
  2271. --*/
  2272. {
  2273. register PMBI mboxp;
  2274. int i;
  2275. mboxp = CardPtr->CurrMBI;
  2276. for (i = 0; i < MB_COUNT; i++, mboxp++)
  2277. {
  2278. if (mboxp > CardPtr->LastMBI)
  2279. mboxp = CardPtr->StartMBI;
  2280. if (mboxp->Status != MBI_FREE)
  2281. {
  2282. CardPtr->CurrMBI = mboxp + 1;
  2283. return (mboxp);
  2284. }
  2285. }
  2286. return ((PMBI) NULL);
  2287. } /* end DoneMbox() */
  2288. BOOLEAN
  2289. AdjustCCBqueue(
  2290. PCCB ccbp,
  2291. IN PDEV_STRUC devptr
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. Removes newly-completed CCB from outstanding CCB queue for a given
  2296. device.
  2297. Arguments:
  2298. ccbp - Pointer to the completed CCB
  2299. devptr - Pointer to device (TAR/LUN) structure
  2300. Return Value:
  2301. TRUE if matching CCB was found in active queue
  2302. FALSE if no match could be found
  2303. --*/
  2304. {
  2305. PCCB tempCCB = devptr->CurrentCCB; /* ptr to head of active CCBS */
  2306. if (tempCCB == 0)
  2307. {
  2308. return FALSE;
  2309. }
  2310. if (ccbp == tempCCB) /* match with head of active CCB queue */
  2311. {
  2312. devptr->CurrentCCB = tempCCB->NxtActiveCCB;
  2313. ccbp->NxtActiveCCB = (PCCB) 0;
  2314. return TRUE;
  2315. }
  2316. while (tempCCB->NxtActiveCCB != 0 )
  2317. {
  2318. if (ccbp == tempCCB->NxtActiveCCB)
  2319. {
  2320. tempCCB->NxtActiveCCB = ccbp->NxtActiveCCB;
  2321. ccbp->NxtActiveCCB = (PCCB) 0;
  2322. return TRUE;
  2323. }
  2324. tempCCB = tempCCB->NxtActiveCCB;
  2325. }
  2326. return FALSE; /* no match found */
  2327. } /* end function AdjustCCBQueue */