Leaked source code of windows server 2003
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.

2373 lines
72 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 2001
  3. Module Name:
  4. sbp2scsi.c
  5. Abstract:
  6. module for the SBP-2 SCSI interface routines
  7. Author:
  8. George Chrysanthakopoulos January-1997 (started)
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "sbp2port.h"
  14. NTSTATUS
  15. Sbp2ScsiRequests(
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP Irp
  18. )
  19. /*++
  20. Routine Description:
  21. This routine handles all IRP_MJ_SCSI requests and queues them on
  22. our device queue. Then it calls StartNextPacket so our StartIo
  23. will run and process the request.
  24. Arguments:
  25. DeviceObject - this driver's device object
  26. Irp - the class driver request
  27. Return Value:
  28. NTSTATUS
  29. --*/
  30. {
  31. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  32. PSCSI_REQUEST_BLOCK srb;
  33. NTSTATUS status;
  34. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  35. KIRQL cIrql;
  36. status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, NULL);
  37. //
  38. // Get a pointer to the SRB.
  39. //
  40. srb = irpStack->Parameters.Scsi.Srb;
  41. if (!NT_SUCCESS (status)) {
  42. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  43. srb->InternalStatus = status;
  44. Irp->IoStatus.Status = status;
  45. Irp->IoStatus.Information = 0;
  46. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  47. return status;
  48. }
  49. switch (srb->Function) {
  50. case SRB_FUNCTION_EXECUTE_SCSI:
  51. if (TEST_FLAG(
  52. deviceExtension->DeviceFlags,
  53. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_PNP_STOPPED |
  54. DEVICE_FLAG_DEVICE_FAILED)
  55. )) {
  56. //
  57. // we got a REMOVE/STOP, we can't accept any more requests...
  58. //
  59. status = STATUS_DEVICE_DOES_NOT_EXIST;
  60. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  61. srb->InternalStatus = status;
  62. DEBUGPRINT2((
  63. "Sbp2Port: ScsiReq: ext=x%p rmv/stop (fl=x%x), status=x%x\n",
  64. deviceExtension,
  65. deviceExtension->DeviceFlags,
  66. status
  67. ));
  68. Irp->IoStatus.Status = srb->InternalStatus;
  69. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  70. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  71. return status;
  72. }
  73. //
  74. // check if this is a request that can be failed if we are powered down..
  75. //
  76. if (TEST_FLAG(srb->SrbFlags,SRB_FLAGS_NO_KEEP_AWAKE)) {
  77. //
  78. // if we are in d3 punt this irp...
  79. //
  80. if (deviceExtension->DevicePowerState == PowerDeviceD3) {
  81. DEBUGPRINT2((
  82. "Sbp2Port: ScsiReq: ext=x%p power down, punt irp=x%p\n",
  83. deviceExtension,
  84. Irp
  85. ));
  86. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  87. srb->SrbStatus = SRB_STATUS_NOT_POWERED;
  88. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  89. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  90. return STATUS_UNSUCCESSFUL;
  91. }
  92. }
  93. IoMarkIrpPending (Irp);
  94. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_QUEUE_LOCKED) &&
  95. TEST_FLAG(srb->SrbFlags,SRB_FLAGS_BYPASS_LOCKED_QUEUE)) {
  96. //
  97. // by pass queueing, this guy has to be processed immediately.
  98. // Since queue is locked, no other requests are being processed
  99. //
  100. if (TEST_FLAG(deviceExtension->DeviceFlags,(DEVICE_FLAG_LOGIN_IN_PROGRESS | DEVICE_FLAG_RECONNECT))){
  101. //
  102. // we are in the middle of a bus reset reconnect..
  103. // defere this until after we have established a connection again
  104. //
  105. Sbp2DeferPendingRequest (deviceExtension, Irp);
  106. } else {
  107. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  108. Sbp2StartIo (DeviceObject, Irp);
  109. KeLowerIrql (cIrql);
  110. }
  111. } else {
  112. Sbp2StartPacket (DeviceObject, Irp, &srb->QueueSortKey);
  113. }
  114. return STATUS_PENDING;
  115. break;
  116. case SRB_FUNCTION_CLAIM_DEVICE:
  117. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  118. if (TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_CLAIMED)) {
  119. status = STATUS_DEVICE_BUSY;
  120. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  121. srb->InternalStatus = STATUS_DEVICE_BUSY;
  122. } else {
  123. SET_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_CLAIMED);
  124. srb->DataBuffer = DeviceObject;
  125. srb->SrbStatus = SRB_STATUS_SUCCESS;
  126. status = STATUS_SUCCESS;
  127. }
  128. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  129. break;
  130. case SRB_FUNCTION_RELEASE_DEVICE:
  131. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  132. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_CLAIMED);
  133. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  134. srb->SrbStatus = SRB_STATUS_SUCCESS;
  135. status = STATUS_SUCCESS;
  136. break;
  137. case SRB_FUNCTION_FLUSH_QUEUE:
  138. case SRB_FUNCTION_FLUSH:
  139. DEBUGPRINT3(("Sbp2Port: ScsiReq: Flush Queue/ORB list\n" ));
  140. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_STOPPED)) {
  141. CleanupOrbList(deviceExtension,STATUS_REQUEST_ABORTED);
  142. srb->SrbStatus = SRB_STATUS_SUCCESS;
  143. status = STATUS_SUCCESS;
  144. } else {
  145. //
  146. // ISSUE-georgioc-2000/02/20 FLUSH_QUEUE should be failed if they
  147. // cannot be handled.
  148. //
  149. DEBUGPRINT3(("Sbp2Port: ScsiReq: Cannot Flush active queue\n" ));
  150. srb->SrbStatus = SRB_STATUS_SUCCESS;
  151. status = STATUS_SUCCESS;
  152. }
  153. break;
  154. case SRB_FUNCTION_RESET_BUS:
  155. status = Sbp2Issue1394BusReset(deviceExtension);
  156. DEBUGPRINT3(("Sbp2Port: ScsiReq: Issuing a 1394 bus reset. \n" ));
  157. if (!NT_SUCCESS(status)) {
  158. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  159. srb->InternalStatus = status;
  160. } else {
  161. srb->SrbStatus = SRB_STATUS_SUCCESS;
  162. }
  163. break;
  164. case SRB_FUNCTION_LOCK_QUEUE:
  165. //
  166. // lock the queue
  167. //
  168. if (TEST_FLAG(deviceExtension->DeviceFlags,(DEVICE_FLAG_REMOVED | DEVICE_FLAG_STOPPED)) ) {
  169. status = STATUS_DEVICE_DOES_NOT_EXIST;
  170. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  171. srb->InternalStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  172. } else {
  173. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  174. SET_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_QUEUE_LOCKED);
  175. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  176. status = STATUS_SUCCESS;
  177. srb->SrbStatus = SRB_STATUS_SUCCESS;
  178. DEBUGPRINT2(("Sbp2Port: ScsiReq: ext=x%p, LOCK_QUEUE\n", deviceExtension));
  179. }
  180. break;
  181. case SRB_FUNCTION_UNLOCK_QUEUE:
  182. //
  183. // re-enable the device queue...
  184. //
  185. DEBUGPRINT2(("Sbp2Port: ScsiReq: ext=x%p, UNLOCK_QUEUE\n", deviceExtension));
  186. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  187. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_QUEUE_LOCKED);
  188. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  189. //
  190. // check if there was a request that was deferred until we were powerd up..
  191. //
  192. //
  193. if (deviceExtension->PowerDeferredIrp) {
  194. PIRP tIrp = deviceExtension->PowerDeferredIrp;
  195. DEBUGPRINT2((
  196. "Sbp2Port: ScsiReq: restart powerDeferredIrp=x%p\n",
  197. tIrp
  198. ));
  199. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  200. deviceExtension->PowerDeferredIrp = NULL;
  201. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  202. Sbp2StartPacket (DeviceObject, tIrp, NULL);
  203. }
  204. if (deviceExtension->DevicePowerState == PowerDeviceD0) {
  205. //
  206. // the queue was just unlocked and we are in D0, which means we can resume
  207. // packet processing...
  208. //
  209. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  210. Sbp2StartNextPacketByKey(
  211. DeviceObject,
  212. deviceExtension->CurrentKey
  213. );
  214. KeLowerIrql (cIrql);
  215. }
  216. if (TEST_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED)) {
  217. status = STATUS_DEVICE_DOES_NOT_EXIST;
  218. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  219. srb->InternalStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  220. break;
  221. } else if (deviceExtension->DevicePowerState == PowerDeviceD3) {
  222. //
  223. // Clean up any deferred FREEs so we HAVE to use the ORB_POINTER
  224. // write on the next insertion to the pending list
  225. //
  226. KeAcquireSpinLock(&deviceExtension->OrbListSpinLock,&cIrql);
  227. if (deviceExtension->NextContextToFree) {
  228. FreeAsyncRequestContext(deviceExtension,deviceExtension->NextContextToFree);
  229. deviceExtension->NextContextToFree = NULL;
  230. }
  231. KeReleaseSpinLock (&deviceExtension->OrbListSpinLock,cIrql);
  232. if (deviceExtension->SystemPowerState != PowerSystemWorking) {
  233. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  234. //
  235. // we need to invalidate our generation because on resume we might try to issue
  236. // a request BEFORE we get the bus reset notification..
  237. //
  238. deviceExtension->CurrentGeneration = 0xFFFFFFFF;
  239. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  240. }
  241. srb->SrbStatus = SRB_STATUS_SUCCESS;
  242. Irp->IoStatus.Status = STATUS_SUCCESS;
  243. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  244. if (deviceExtension->SystemPowerState == PowerSystemWorking) {
  245. #if DBG
  246. if (!IsListEmpty (&DeviceObject->DeviceQueue.DeviceListHead)) {
  247. DEBUGPRINT2((
  248. "\nSbp2Port: ScsiReq: ext=x%p, RESTARTING NON-EMPTY " \
  249. "DEV_Q AT D3!\n",
  250. deviceExtension
  251. ));
  252. }
  253. #endif
  254. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  255. Sbp2StartNextPacketByKey(
  256. DeviceObject,
  257. deviceExtension->CurrentKey
  258. );
  259. KeLowerIrql (cIrql);
  260. }
  261. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  262. return STATUS_SUCCESS;
  263. }
  264. status = STATUS_SUCCESS;
  265. srb->SrbStatus = SRB_STATUS_SUCCESS;
  266. break;
  267. default:
  268. status = STATUS_NOT_SUPPORTED;
  269. srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  270. srb->InternalStatus = STATUS_NOT_SUPPORTED;
  271. DEBUGPRINT3(("Sbp2Port: ScsiReq: SRB Function not handled, srb->CdbLength %x, Exiting.\n",srb->CdbLength ));
  272. break;
  273. }
  274. if (!NT_SUCCESS(status)) {
  275. //
  276. // it'll either have gone to the StartIo routine or have been
  277. // failed before hitting the device. Therefore ensure that
  278. // srb->InternalStatus is set correctly.
  279. //
  280. ASSERT(srb->SrbStatus == SRB_STATUS_INTERNAL_ERROR);
  281. ASSERT((LONG)srb->InternalStatus == status);
  282. }
  283. Irp->IoStatus.Status = status;
  284. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  285. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  286. return status;
  287. }
  288. VOID
  289. Sbp2StartIo(
  290. IN PDEVICE_OBJECT DeviceObject,
  291. IN PIRP Irp
  292. )
  293. /*++
  294. Routine Description:
  295. Takes incoming, queued requests, and sends them down to the 1394 bus
  296. Arguments:
  297. DeviceObject - Our device object
  298. Irp - Request from class drivers,
  299. Return Value:
  300. --*/
  301. {
  302. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  303. PSCSI_REQUEST_BLOCK srb;
  304. NTSTATUS status;
  305. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  306. PASYNC_REQUEST_CONTEXT context;
  307. //
  308. // Get a pointer to the SRB.
  309. //
  310. srb = irpStack->Parameters.Scsi.Srb;
  311. Irp->IoStatus.Status = STATUS_PENDING;
  312. srb->SrbStatus = SRB_STATUS_PENDING;
  313. if (TEST_FLAG(
  314. deviceExtension->DeviceFlags,
  315. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_PNP_STOPPED |
  316. DEVICE_FLAG_DEVICE_FAILED | DEVICE_FLAG_ABSENT_ON_POWER_UP)
  317. )) {
  318. //
  319. // Removed, stopped, or absent, so can't accept any more requests
  320. //
  321. status = STATUS_DEVICE_DOES_NOT_EXIST;
  322. srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  323. Irp->IoStatus.Status = status;
  324. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  325. DEBUGPRINT2((
  326. "Sbp2Port: StartIo: dev stopped/removed/absent, fail irp=x%p\n",
  327. Irp
  328. ));
  329. Sbp2StartNextPacketByKey (DeviceObject, 0);
  330. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  331. return;
  332. }
  333. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_QUEUE_LOCKED)) {
  334. if (!TEST_FLAG(srb->SrbFlags,SRB_FLAGS_BYPASS_LOCKED_QUEUE)) {
  335. if (!Sbp2InsertByKeyDeviceQueue(
  336. &DeviceObject->DeviceQueue,
  337. &Irp->Tail.Overlay.DeviceQueueEntry,
  338. srb->QueueSortKey)) {
  339. //
  340. // ISSUE-georgioc-2000/02/20 deadlock possible because
  341. // queue is now busy and noone has called StartIo().
  342. // should instead queue the request and then later,
  343. // after an UNLOCK arrives, process this queue of
  344. // requests that occurred when the queue was locked.
  345. // OR should comment why this is not a deadlock
  346. //
  347. DEBUGPRINT2((
  348. "Sbp2Port: StartIo: insert failed, compl irp=x%p\n",
  349. Irp
  350. ));
  351. srb->SrbStatus = SRB_STATUS_BUSY;
  352. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  353. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  354. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  355. }
  356. return;
  357. }
  358. } else {
  359. //
  360. // CASE 1: Device powered Down, but system running.
  361. //
  362. // Queue this request, Power up device, then when done start
  363. // processing requests
  364. //
  365. if ((deviceExtension->DevicePowerState == PowerDeviceD3) &&
  366. (deviceExtension->SystemPowerState == PowerSystemWorking)) {
  367. BOOLEAN queued;
  368. POWER_STATE state;
  369. queued = Sbp2InsertByKeyDeviceQueue(
  370. &DeviceObject->DeviceQueue,
  371. &Irp->Tail.Overlay.DeviceQueueEntry,
  372. srb->QueueSortKey
  373. );
  374. if (!queued) {
  375. DEBUGPRINT2((
  376. "Sbp2Port: StartIo: dev q not busy, defer irp=x%p\n",
  377. Irp
  378. ));
  379. ASSERT(deviceExtension->PowerDeferredIrp == NULL);
  380. KeAcquireSpinLockAtDpcLevel(
  381. &deviceExtension->ExtensionDataSpinLock
  382. );
  383. deviceExtension->PowerDeferredIrp = Irp;
  384. KeReleaseSpinLockFromDpcLevel(
  385. &deviceExtension->ExtensionDataSpinLock
  386. );
  387. }
  388. //
  389. // We need to send our own stack a d0 irp, so the device
  390. // powers up and can process this request.
  391. // Block until the Start_STOP_UNIT to start, is called.
  392. // This has to happen in two steps:
  393. // 1: Send D Irp to stack, which might power up the controller
  394. // 2: Wait for completion of START UNIT send by class driver,
  395. // if success start processing requests...
  396. //
  397. DEBUGPRINT2((
  398. "Sbp2Port: StartIo: dev powered down, q(%x) irp=x%p " \
  399. "til power up\n",
  400. queued,
  401. Irp
  402. ));
  403. state.DeviceState = PowerDeviceD0;
  404. DEBUGPRINT1((
  405. "Sbp2Port: StartIo: sending D irp for state %x\n",
  406. state
  407. ));
  408. status = PoRequestPowerIrp(
  409. deviceExtension->DeviceObject,
  410. IRP_MN_SET_POWER,
  411. state,
  412. NULL,
  413. NULL,
  414. NULL);
  415. if (!NT_SUCCESS(status)) {
  416. //
  417. // not good, we cant power up the device..
  418. //
  419. DEBUGPRINT1(("Sbp2Port: StartIo: D irp err=x%x\n", status));
  420. if (!queued) {
  421. KeAcquireSpinLockAtDpcLevel(
  422. &deviceExtension->ExtensionDataSpinLock
  423. );
  424. if (deviceExtension->PowerDeferredIrp == Irp) {
  425. deviceExtension->PowerDeferredIrp = NULL;
  426. } else {
  427. Irp = NULL;
  428. }
  429. KeReleaseSpinLockFromDpcLevel(
  430. &deviceExtension->ExtensionDataSpinLock
  431. );
  432. } else {
  433. //
  434. // If the irp is still in the device queue then remove it.
  435. // Don't worry about the queue's busy flag - if irp found
  436. // then queue gets restarted by StartNextPacket below,
  437. // else another thread processed the irp, thereby
  438. // restarting the queue.
  439. //
  440. PIRP qIrp = NULL;
  441. PLIST_ENTRY entry;
  442. PKDEVICE_QUEUE queue = &DeviceObject->DeviceQueue;
  443. KeAcquireSpinLockAtDpcLevel (&queue->Lock);
  444. for(
  445. entry = queue->DeviceListHead.Flink;
  446. entry != &queue->DeviceListHead;
  447. entry = entry->Flink
  448. ) {
  449. qIrp = CONTAINING_RECORD(
  450. entry,
  451. IRP,
  452. Tail.Overlay.DeviceQueueEntry.DeviceListEntry
  453. );
  454. if (qIrp == Irp) {
  455. RemoveEntryList (entry);
  456. break;
  457. }
  458. }
  459. KeReleaseSpinLockFromDpcLevel (&queue->Lock);
  460. if (qIrp != Irp) {
  461. Irp = NULL;
  462. }
  463. }
  464. if (Irp) {
  465. srb->SrbStatus = SRB_STATUS_ERROR;
  466. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  467. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  468. Sbp2StartNextPacketByKey (DeviceObject, 0);
  469. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  470. } else {
  471. //
  472. // Another thread processed this irp, it will take
  473. // care of the cleanup
  474. //
  475. DEBUGPRINT1(("Sbp2Port: StartIo: ... irp NOT FOUND!\n"));
  476. }
  477. }
  478. return;
  479. }
  480. //
  481. // case 2: Reset in progress (either reconnect or login in progress)
  482. //
  483. // Queue request until we are done. When reset over, start
  484. // processing again.
  485. //
  486. if (TEST_FLAG(
  487. deviceExtension->DeviceFlags,
  488. DEVICE_FLAG_RESET_IN_PROGRESS
  489. )) {
  490. //
  491. // Queue request (twice, in case queue wasn't busy the 1st time).
  492. // We acquire the spinlock to prevent the case where we try to
  493. // insert to a non-busy queue, then a 2nd thread completing
  494. // the reset calls StartNextPacket (which would reset the q busy
  495. // flag), then we try to insert again and fail - the result
  496. // being deadlock since no one will restart the queue.
  497. //
  498. KeAcquireSpinLockAtDpcLevel(
  499. &deviceExtension->ExtensionDataSpinLock
  500. );
  501. if (TEST_FLAG(
  502. deviceExtension->DeviceFlags,
  503. DEVICE_FLAG_RESET_IN_PROGRESS
  504. )) {
  505. if (Sbp2InsertByKeyDeviceQueue(
  506. &DeviceObject->DeviceQueue,
  507. &Irp->Tail.Overlay.DeviceQueueEntry,
  508. srb->QueueSortKey
  509. ) ||
  510. Sbp2InsertByKeyDeviceQueue(
  511. &DeviceObject->DeviceQueue,
  512. &Irp->Tail.Overlay.DeviceQueueEntry,
  513. srb->QueueSortKey
  514. )) {
  515. KeReleaseSpinLockFromDpcLevel(
  516. &deviceExtension->ExtensionDataSpinLock
  517. );
  518. DEBUGPRINT2((
  519. "Sbp2Port: StartIo: ext=x%p resetting, q irp=x%p\n",
  520. deviceExtension,
  521. Irp
  522. ));
  523. return;
  524. }
  525. KeReleaseSpinLockFromDpcLevel(
  526. &deviceExtension->ExtensionDataSpinLock
  527. );
  528. DEBUGPRINT1((
  529. "Sbp2Port: StartIo: ext=x%p 2xQ err, fail irp=x%p\n",
  530. deviceExtension,
  531. Irp
  532. ));
  533. ASSERT (FALSE); // should never get here
  534. srb->SrbStatus = SRB_STATUS_BUSY;
  535. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  536. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  537. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  538. return;
  539. }
  540. KeReleaseSpinLockFromDpcLevel(
  541. &deviceExtension->ExtensionDataSpinLock
  542. );
  543. }
  544. //
  545. // CASE 3: System is powered down, and so is device (better be).
  546. // Queue all requests until system comes up from sleep
  547. //
  548. if ((deviceExtension->DevicePowerState != PowerDeviceD0) &&
  549. (deviceExtension->SystemPowerState != PowerSystemWorking)) {
  550. //
  551. // our device is powered down AND the system is powered down.
  552. // just queue this request...
  553. //
  554. if (!Sbp2InsertByKeyDeviceQueue(
  555. &DeviceObject->DeviceQueue,
  556. &Irp->Tail.Overlay.DeviceQueueEntry,
  557. srb->QueueSortKey)) {
  558. ASSERT(deviceExtension->PowerDeferredIrp == NULL);
  559. KeAcquireSpinLockAtDpcLevel(
  560. &deviceExtension->ExtensionDataSpinLock
  561. );
  562. deviceExtension->PowerDeferredIrp = Irp;
  563. KeReleaseSpinLockFromDpcLevel(
  564. &deviceExtension->ExtensionDataSpinLock
  565. );
  566. DEBUGPRINT2((
  567. "Sbp2Port: StartIo: powered down, defer irp=x%p\n",
  568. Irp
  569. ));
  570. } else {
  571. DEBUGPRINT2((
  572. "Sbp2Port: StartIo: powered down, q irp=%p\n",
  573. Irp
  574. ));
  575. }
  576. return;
  577. }
  578. }
  579. if (!TEST_FLAG (srb->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE)) {
  580. if (deviceExtension->IdleCounter) {
  581. PoSetDeviceBusy (deviceExtension->IdleCounter);
  582. }
  583. }
  584. //
  585. // create a context ,a CMD orb and the appropriate data descriptor
  586. //
  587. Create1394TransactionForSrb (deviceExtension, srb, &context);
  588. return;
  589. }
  590. VOID
  591. Create1394TransactionForSrb(
  592. IN PDEVICE_EXTENSION DeviceExtension,
  593. IN PSCSI_REQUEST_BLOCK Srb,
  594. IN OUT PASYNC_REQUEST_CONTEXT *RequestContext
  595. )
  596. /*++
  597. Routine Description:
  598. Always called at DPC level...
  599. This routine is responsible for allocating all the data structures and
  600. getting all the 1394 addresses required for incoming scsi requests.
  601. It will fill in Command ORBs, create page table if necessery, and
  602. most importantly setup a request Context, so when the status callback
  603. is called, we can find the srb Associated with completed ORB. Since we
  604. have a FreeList, this request will always use pre-allocated contexts
  605. and page tables, so we dont have to do it dynamically...
  606. Arguments:
  607. DeviceObject - Our device object
  608. Srb - SRB from class drivers,
  609. RequestContext - Pointer To Context used for this request.
  610. Mdl - MDL with data buffer for this request
  611. Return Value:
  612. --*/
  613. {
  614. NTSTATUS status= STATUS_SUCCESS;
  615. PMDL requestMdl;
  616. PASYNC_REQUEST_CONTEXT callbackContext;
  617. PVOID mdlVa;
  618. //
  619. // Allocate a context for this requestfrom our freeList
  620. //
  621. callbackContext = (PASYNC_REQUEST_CONTEXT) ExInterlockedPopEntrySList(
  622. &DeviceExtension->FreeContextListHead,
  623. &DeviceExtension->FreeContextLock
  624. );
  625. if (callbackContext) {
  626. callbackContext = RETRIEVE_CONTEXT(callbackContext,LookasideList);
  627. } else {
  628. DEBUGPRINT1((
  629. "Sbp2Port: Create1394XactForSrb: ERROR! ext=x%p, no ctx's\n",
  630. DeviceExtension
  631. ));
  632. status = STATUS_INSUFFICIENT_RESOURCES;
  633. Srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  634. Srb->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  635. Sbp2CreateRequestErrorLog(DeviceExtension->DeviceObject,NULL,status);
  636. goto exitCreate1394ReqForSrb;
  637. }
  638. //
  639. // Acquire the OrbListSpinLock to serialize this OrbListDepth
  640. // change & save with those done in Sbp2GlobalStatusCallback
  641. // (when freeing async requests), to insure we won't make too
  642. // many or too few calls to StartNextPacket
  643. //
  644. KeAcquireSpinLockAtDpcLevel (&DeviceExtension->OrbListSpinLock);
  645. callbackContext->OrbListDepth = InterlockedIncrement(
  646. &DeviceExtension->OrbListDepth
  647. );
  648. KeReleaseSpinLockFromDpcLevel (&DeviceExtension->OrbListSpinLock);
  649. *RequestContext = callbackContext;
  650. //
  651. // Initialize srb-related entries in our context
  652. //
  653. callbackContext->OriginalSrb = NULL;
  654. callbackContext->DataMappingHandle = NULL;
  655. callbackContext->Packet = NULL;
  656. callbackContext->Tag = SBP2_ASYNC_CONTEXT_TAG;
  657. callbackContext->Srb = Srb;
  658. callbackContext->DeviceObject = DeviceExtension->DeviceObject;
  659. callbackContext->Flags = 0;
  660. //
  661. // filter commands so they conform to RBC..
  662. //
  663. status = Sbp2_SCSI_RBC_Conversion(callbackContext);
  664. if (status != STATUS_PENDING){
  665. //
  666. // the call was handled immediately. Complete the irp here...
  667. //
  668. callbackContext->Srb = NULL;
  669. FreeAsyncRequestContext(DeviceExtension,callbackContext);
  670. if (NT_SUCCESS(status)) {
  671. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  672. ((PIRP) Srb->OriginalRequest)->IoStatus.Information = Srb->DataTransferLength;
  673. } else {
  674. DEBUGPRINT1((
  675. "Sbp2Port: Create1394XactForSrb: RBC translation failed!!!\n"
  676. ));
  677. //
  678. // since translation errors are always internal errors,
  679. // set SRB_STATUS to reflect an internal (not device) error
  680. //
  681. Srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  682. Srb->InternalStatus = status;
  683. ((PIRP)Srb->OriginalRequest)->IoStatus.Information = 0;
  684. }
  685. ((PIRP)Srb->OriginalRequest)->IoStatus.Status = status;
  686. IoCompleteRequest (((PIRP) Srb->OriginalRequest), IO_NO_INCREMENT);
  687. Sbp2StartNextPacketByKey(
  688. DeviceExtension->DeviceObject,
  689. DeviceExtension->CurrentKey
  690. );
  691. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, NULL);
  692. return;
  693. }
  694. status = STATUS_SUCCESS;
  695. //
  696. // Figure the maximum number of different 1394 addresses we need to span this request's data buffer
  697. //
  698. if ((Srb->DataTransferLength == 0) || (Srb->SrbFlags == SRB_FLAGS_NO_DATA_TRANSFER)) {
  699. //
  700. // No need to get a 1394 address for data, since there is none
  701. //
  702. Sbp2InitializeOrb (DeviceExtension, callbackContext);
  703. } else {
  704. //
  705. // if this request is apart of split request, we need to make our own mdl...
  706. //
  707. requestMdl = ((PIRP) Srb->OriginalRequest)->MdlAddress;
  708. mdlVa = MmGetMdlVirtualAddress (requestMdl);
  709. if (mdlVa != (PVOID) Srb->DataBuffer) {
  710. //
  711. // split request
  712. //
  713. callbackContext->PartialMdl = IoAllocateMdl(Srb->DataBuffer,Srb->DataTransferLength,FALSE,FALSE,NULL);
  714. if (!callbackContext->PartialMdl) {
  715. status = STATUS_INSUFFICIENT_RESOURCES;
  716. Srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  717. Srb->InternalStatus = STATUS_INSUFFICIENT_RESOURCES;
  718. DEBUGPRINT1((
  719. "Sbp2Port: Create1394XactForSrb: REQ_ALLOC addr err!\n"
  720. ));
  721. goto exitCreate1394ReqForSrb;
  722. }
  723. IoBuildPartialMdl(requestMdl,callbackContext->PartialMdl,Srb->DataBuffer, Srb->DataTransferLength );
  724. requestMdl = callbackContext->PartialMdl;
  725. DEBUGPRINT4(("Sbp2Port: Create1394TransactionForSrb: Allocating Partial Mdl %p\n",requestMdl));
  726. } else {
  727. callbackContext->PartialMdl = NULL;
  728. }
  729. callbackContext->RequestMdl = requestMdl;
  730. //
  731. // according to what the port driver can handle, map the data buffer to 1394 addresses and create
  732. // an sbp2 page table if necessery
  733. //
  734. status = Sbp2BusMapTransfer(DeviceExtension,callbackContext);
  735. //
  736. // NOTE: On success, above returns STATUS_PENDING
  737. // all errors are internal errors.
  738. //
  739. if (!NT_SUCCESS(status)) {
  740. DEBUGPRINT1(("\n Sbp2Create1394TransactionForSrb failed %x\n",status));
  741. if (callbackContext->PartialMdl) {
  742. IoFreeMdl(callbackContext->PartialMdl);
  743. callbackContext->PartialMdl = NULL;
  744. }
  745. }
  746. }
  747. exitCreate1394ReqForSrb:
  748. if (status == STATUS_PENDING) {
  749. //
  750. // Sbp2StartNextPacketByKey will be called when the
  751. // notification alloc callback is called
  752. //
  753. return;
  754. } else if (status == STATUS_SUCCESS) { // ISSUE-geogioc-2000/02/20 - NT_SUCCESS(status) should be used
  755. //
  756. // SUCCESS, place
  757. //
  758. Sbp2InsertTailList(DeviceExtension,callbackContext);
  759. return;
  760. } else {
  761. //
  762. // since the request could not have actually been processed by
  763. // the device, this is an internal error and should be propogated
  764. // up the stack as such.
  765. //
  766. if (callbackContext) {
  767. callbackContext->Srb = NULL;
  768. FreeAsyncRequestContext(DeviceExtension,callbackContext);
  769. }
  770. Srb->SrbStatus = SRB_STATUS_INTERNAL_ERROR;
  771. Srb->InternalStatus = status;
  772. ((PIRP)Srb->OriginalRequest)->IoStatus.Status = status;
  773. ((PIRP)Srb->OriginalRequest)->IoStatus.Information = 0;
  774. IoCompleteRequest(((PIRP)Srb->OriginalRequest),IO_NO_INCREMENT);
  775. Sbp2StartNextPacketByKey (DeviceExtension->DeviceObject, 0);
  776. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, NULL);
  777. return;
  778. }
  779. return;
  780. }
  781. NTSTATUS
  782. Sbp2_SCSI_RBC_Conversion(
  783. IN PASYNC_REQUEST_CONTEXT Context
  784. )
  785. /*++
  786. Routine Description:
  787. Always called at DPC level...
  788. It translates scsi commands to their RBC equivalents, ONLY if they differ in each spec
  789. The translation is done before request is issued and in some cases, after the request is
  790. completed
  791. Arguments:
  792. DeviceExtension - Sbp2 extension
  793. RequestContext - Pointer To Context used for this request.
  794. Return Value:
  795. --*/
  796. {
  797. PCDB cdb;
  798. if (TEST_FLAG(Context->Flags, ASYNC_CONTEXT_FLAG_COMPLETED)) {
  799. //
  800. // completed request translation
  801. //
  802. if ( ((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->InquiryData.DeviceType == \
  803. RBC_DEVICE){
  804. return Rbc_Scsi_Conversion(Context->Srb,
  805. &(PSCSI_REQUEST_BLOCK)Context->OriginalSrb,
  806. &((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->DeviceModeHeaderAndPage,
  807. FALSE,
  808. ((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->InquiryData.RemovableMedia
  809. );
  810. }
  811. } else {
  812. //
  813. // outgoing request translation
  814. //
  815. if (((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->InquiryData.DeviceType == \
  816. RBC_DEVICE){
  817. return Rbc_Scsi_Conversion(Context->Srb,
  818. &(PSCSI_REQUEST_BLOCK)Context->OriginalSrb,
  819. &((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->DeviceModeHeaderAndPage,
  820. TRUE,
  821. ((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->InquiryData.RemovableMedia
  822. );
  823. } else if (((PDEVICE_EXTENSION)Context->DeviceObject->DeviceExtension)->InquiryData.DeviceType == \
  824. READ_ONLY_DIRECT_ACCESS_DEVICE){
  825. switch (Context->Srb->Cdb[0]) {
  826. case SCSIOP_MODE_SENSE10:
  827. //
  828. // mmc2 type of device..
  829. //
  830. cdb = (PCDB) &Context->Srb->Cdb[0];
  831. cdb->MODE_SENSE10.Dbd = 1;
  832. break;
  833. }
  834. }
  835. }
  836. return STATUS_PENDING;
  837. }
  838. NTSTATUS
  839. Sbp2BusMapTransfer(
  840. PDEVICE_EXTENSION DeviceExtension,
  841. PASYNC_REQUEST_CONTEXT CallbackContext
  842. )
  843. /*++
  844. Routine Description:
  845. Always called at DPC level...
  846. It calls the port driver to map the data buffer to physical/1394 addresses
  847. Arguments:
  848. DeviceExtension - Sbp2 extension
  849. RequestContext - Pointer To Context used for this request.
  850. Mdl - MDL with data buffer for this request
  851. Return Value:
  852. --*/
  853. {
  854. NTSTATUS status;
  855. #if DBG
  856. ULONG maxNumberOfPages;
  857. maxNumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  858. CallbackContext->Srb->DataBuffer,
  859. CallbackContext->Srb->DataTransferLength
  860. );
  861. ASSERT (CallbackContext->PageTableContext.PageTable != NULL);
  862. ASSERT (maxNumberOfPages <= SBP2_NUM_PAGE_TABLE_ENTRIES);
  863. #endif
  864. //
  865. // Do the DATA alloc.
  866. //
  867. SET_FLAG(CallbackContext->Flags, ASYNC_CONTEXT_FLAG_PAGE_ALLOC);
  868. CallbackContext->Packet = NULL;
  869. Sbp2AllocComplete (CallbackContext);
  870. DEBUGPRINT4((
  871. "Sbp2Port: Sbp2MapAddress: alloc done, ctx=x%p, dataHandle=x%p\n",
  872. CallbackContext,
  873. CallbackContext->DataMappingHandle
  874. ));
  875. if (TEST_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC_FAILED)) {
  876. CLEAR_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC);
  877. CLEAR_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC_FAILED);
  878. DEBUGPRINT1((
  879. "Sbp2Port: Sbp2MapAddress: (page table present) REQ_ALLOC data " \
  880. "err, ctx=x%p\n",
  881. CallbackContext
  882. ));
  883. return STATUS_INSUFFICIENT_RESOURCES;
  884. }
  885. return STATUS_PENDING;
  886. }
  887. VOID
  888. Sbp2AllocComplete(
  889. IN PASYNC_REQUEST_CONTEXT CallbackContext
  890. )
  891. {
  892. PDEVICE_EXTENSION deviceExtension = CallbackContext->DeviceObject->DeviceExtension;
  893. PIRBIRP packet = CallbackContext->Packet;
  894. PPORT_PHYS_ADDR_ROUTINE routine = deviceExtension->HostRoutineAPI.PhysAddrMappingRoutine;
  895. PSCSI_REQUEST_BLOCK srb;
  896. NTSTATUS status;
  897. BOOLEAN bDirectCall = FALSE;
  898. DEBUGPRINT4(("Sbp2AllocateComplete: ctx=x%p, flags=x%x\n",CallbackContext,CallbackContext->Flags));
  899. //
  900. // this same function is used for the alloc complete notification of a pagetable
  901. // AND of the actuall data tranfser. So we have to check which case this is
  902. // This is a simple state machine with two states:
  903. // startIo-> A: PAGE TABLE ALLOC -> B
  904. // B: DATA ALLOC ->exit
  905. //
  906. if (TEST_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_PAGE_ALLOC)) {
  907. CLEAR_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_PAGE_ALLOC);
  908. if (CallbackContext->Packet) {
  909. //
  910. // we have just received the page table alloc...
  911. //
  912. ASSERT (FALSE); // should never get here any more
  913. } else {
  914. //
  915. // We were called directly since a sufficient page table was
  916. // already in the context
  917. //
  918. AllocateIrpAndIrb (deviceExtension,&packet);
  919. if (!packet) {
  920. return;
  921. }
  922. CallbackContext->Packet = packet;
  923. bDirectCall = TRUE;
  924. }
  925. //
  926. // indicate that now we are in the DATA transfer alloc case
  927. //
  928. SET_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC);
  929. //
  930. // reuse the same irb/irp
  931. // prepare the irb for calling the 1394 bus/port driver synchronously
  932. //
  933. packet->Irb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
  934. //
  935. // we only want a call back when we get a status from the target
  936. // Now allocate 1394 addresses for the data buffer with no notification
  937. //
  938. packet->Irb->u.AllocateAddressRange.nLength = CallbackContext->Srb->DataTransferLength;
  939. packet->Irb->u.AllocateAddressRange.fulNotificationOptions = NOTIFY_FLAGS_NEVER;
  940. if (TEST_FLAG(CallbackContext->Srb->SrbFlags,SRB_FLAGS_DATA_IN)) {
  941. packet->Irb->u.AllocateAddressRange.fulAccessType = ACCESS_FLAGS_TYPE_WRITE;
  942. } else {
  943. packet->Irb->u.AllocateAddressRange.fulAccessType = ACCESS_FLAGS_TYPE_READ;
  944. }
  945. packet->Irb->u.AllocateAddressRange.fulFlags = ALLOCATE_ADDRESS_FLAGS_USE_BIG_ENDIAN;
  946. //
  947. // the callback for physical address is used to notify that the async allocate request
  948. // is now complete..
  949. //
  950. packet->Irb->u.AllocateAddressRange.Callback= Sbp2AllocComplete;
  951. packet->Irb->u.AllocateAddressRange.Context= CallbackContext;
  952. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_High = 0;
  953. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_Low = 0;
  954. packet->Irb->u.AllocateAddressRange.FifoSListHead = NULL;
  955. packet->Irb->u.AllocateAddressRange.FifoSpinLock = NULL;
  956. packet->Irb->u.AllocateAddressRange.AddressesReturned = 0;
  957. packet->Irb->u.AllocateAddressRange.DeviceExtension = deviceExtension;
  958. packet->Irb->u.AllocateAddressRange.p1394AddressRange = (PADDRESS_RANGE) &(CallbackContext->PageTableContext.PageTable[0]);
  959. packet->Irb->u.AllocateAddressRange.Mdl = CallbackContext->RequestMdl; //MDL from original request
  960. packet->Irb->u.AllocateAddressRange.MaxSegmentSize = (SBP2_MAX_DIRECT_BUFFER_SIZE)/2;
  961. CallbackContext->Packet = packet;
  962. //
  963. // Send allocateRange request to bus driver , indicating that we dont want the irp to be freed
  964. // If the port driver supports a direct mapping routine, call that instead
  965. //
  966. status = (*routine) (deviceExtension->HostRoutineAPI.Context,packet->Irb);
  967. if (status == STATUS_SUCCESS) {
  968. return;
  969. } else {
  970. DEBUGPRINT1(("Sbp2Port: Sbp2AllocComplete: REQUEST_ALLOCATE Address failed, ctx=x%p, direct=%x!!\n",CallbackContext,bDirectCall));
  971. DeAllocateIrpAndIrb(deviceExtension,packet);
  972. CallbackContext->Packet = NULL;
  973. CallbackContext->DataMappingHandle = NULL;
  974. SET_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC_FAILED);
  975. if (bDirectCall) {
  976. return;
  977. } else {
  978. //
  979. // we were indirectly called, so the irp has already been marked pending..
  980. // we must abort it here and complete the context with error...
  981. //
  982. srb = CallbackContext->Srb;
  983. CallbackContext->Srb = NULL;
  984. FreeAsyncRequestContext(deviceExtension,CallbackContext);
  985. srb->SrbStatus = SRB_STATUS_ERROR;
  986. ((PIRP)srb->OriginalRequest)->IoStatus.Status = status;
  987. ((PIRP)srb->OriginalRequest)->IoStatus.Information = 0;
  988. IoCompleteRequest(((PIRP)srb->OriginalRequest),IO_NO_INCREMENT);
  989. Sbp2StartNextPacketByKey (deviceExtension->DeviceObject, 0);
  990. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  991. return;
  992. }
  993. }
  994. }
  995. if (TEST_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC)) {
  996. //
  997. // we have a page table so this means we just been notified that the DATA alloc is over
  998. // Save the handle to the data descriptor's memory range
  999. //
  1000. CLEAR_FLAG(CallbackContext->Flags,ASYNC_CONTEXT_FLAG_DATA_ALLOC);
  1001. CallbackContext->DataMappingHandle = CallbackContext->Packet->Irb->u.AllocateAddressRange.hAddressRange;
  1002. //
  1003. // number of page table elements required
  1004. //
  1005. CallbackContext->PageTableContext.NumberOfPages = CallbackContext->Packet->Irb->u.AllocateAddressRange.AddressesReturned;
  1006. DeAllocateIrpAndIrb(deviceExtension,CallbackContext->Packet);
  1007. CallbackContext->Packet = NULL;
  1008. Sbp2InitializeOrb(deviceExtension,CallbackContext);
  1009. Sbp2InsertTailList(deviceExtension,CallbackContext);
  1010. }
  1011. return;
  1012. }
  1013. VOID
  1014. Sbp2InitializeOrb(
  1015. IN PDEVICE_EXTENSION DeviceExtension,
  1016. PASYNC_REQUEST_CONTEXT CallbackContext
  1017. )
  1018. {
  1019. ULONG i, size;
  1020. //
  1021. // zero the ORB CDB and ORB Flags fields
  1022. //
  1023. CallbackContext->CmdOrb->OrbInfo.QuadPart = 0;
  1024. if (!CallbackContext->DataMappingHandle) {
  1025. CallbackContext->PageTableContext.NumberOfPages = 0;
  1026. CallbackContext->CmdOrb->DataDescriptor.OctletPart = 0xFFFFFFFFFFFFFFFF;
  1027. } else {
  1028. if (CallbackContext->PageTableContext.NumberOfPages > 1) {
  1029. CallbackContext->CmdOrb->DataDescriptor.BusAddress = \
  1030. CallbackContext->PageTableContext.AddressContext.Address.BusAddress;
  1031. octbswap(CallbackContext->CmdOrb->DataDescriptor);
  1032. //
  1033. // If the host does not convert the table to big endian (or
  1034. // there's an associated scatter gather list), do it here
  1035. //
  1036. if ((DeviceExtension->HostRoutineAPI.PhysAddrMappingRoutine == NULL)
  1037. || (CallbackContext->RequestMdl == NULL)) {
  1038. for (i=0;i<CallbackContext->PageTableContext.NumberOfPages;i++) {
  1039. octbswap(CallbackContext->PageTableContext.PageTable[i]); // convert to big endian
  1040. }
  1041. }
  1042. //
  1043. // setup the cmd orb for a page table
  1044. //
  1045. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= ORB_PAGE_TABLE_BIT_MASK;
  1046. //
  1047. // we define a data size equal (since we are in page table mode)
  1048. // to number of pages. The page table has already been allocated .
  1049. //
  1050. CallbackContext->CmdOrb->OrbInfo.u.LowPart = (USHORT) CallbackContext->PageTableContext.NumberOfPages;
  1051. } else {
  1052. CallbackContext->CmdOrb->DataDescriptor = CallbackContext->PageTableContext.PageTable[0];
  1053. //
  1054. // If the host does not convert the table to big endian (or
  1055. // there's an associated scatter gather list), do it here
  1056. //
  1057. if ((DeviceExtension->HostRoutineAPI.PhysAddrMappingRoutine == NULL)
  1058. || (CallbackContext->RequestMdl == NULL)) {
  1059. CallbackContext->CmdOrb->DataDescriptor.BusAddress.NodeId = DeviceExtension->InitiatorAddressId;
  1060. octbswap(CallbackContext->CmdOrb->DataDescriptor);
  1061. } else {
  1062. //
  1063. // address already in big endian, just put the NodeID in the proper place
  1064. //
  1065. CallbackContext->CmdOrb->DataDescriptor.ByteArray.Byte0 = *((PUCHAR)&DeviceExtension->InitiatorAddressId+1);
  1066. CallbackContext->CmdOrb->DataDescriptor.ByteArray.Byte1 = *((PUCHAR)&DeviceExtension->InitiatorAddressId);
  1067. }
  1068. //
  1069. // Data size of buffer data descriptor points to
  1070. //
  1071. CallbackContext->CmdOrb->OrbInfo.u.LowPart = (USHORT) CallbackContext->Srb->DataTransferLength;
  1072. }
  1073. }
  1074. //
  1075. // Start building the ORB used to carry this srb
  1076. // By default notify bit, rq_fmt field and page_size field are all zero..
  1077. // Also the nextOrbAddress is NULL ( which is 0xFFFF..F)
  1078. //
  1079. CallbackContext->CmdOrb->NextOrbAddress.OctletPart = 0xFFFFFFFFFFFFFFFF;
  1080. //
  1081. // Max speed supported
  1082. //
  1083. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= (0x0700 & ((DeviceExtension->MaxControllerPhySpeed) << 8));
  1084. //
  1085. // set notify bit for this command ORB
  1086. //
  1087. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= ORB_NOTIFY_BIT_MASK;
  1088. if (TEST_FLAG(CallbackContext->Srb->SrbFlags,SRB_FLAGS_DATA_IN)) {
  1089. //
  1090. // Read request. Set direction bit to 1
  1091. //
  1092. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= ORB_DIRECTION_BIT_MASK;
  1093. // Max payload size, (its entered in the orb, in the form of 2^(size+2)
  1094. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= DeviceExtension->OrbReadPayloadMask ;
  1095. } else {
  1096. //
  1097. // Write request, direction bit is zero
  1098. //
  1099. CallbackContext->CmdOrb->OrbInfo.u.HighPart &= ~ORB_DIRECTION_BIT_MASK;
  1100. CallbackContext->CmdOrb->OrbInfo.u.HighPart |= DeviceExtension->OrbWritePayloadMask ;
  1101. }
  1102. //
  1103. // Now copy the CDB from the SRB to our ORB
  1104. //
  1105. ASSERT (CallbackContext->Srb->CdbLength >= 6);
  1106. ASSERT (CallbackContext->Srb->CdbLength <= SBP2_MAX_CDB_SIZE);
  1107. size = min (SBP2_MAX_CDB_SIZE, CallbackContext->Srb->CdbLength);
  1108. RtlZeroMemory(&CallbackContext->CmdOrb->Cdb, SBP2_MAX_CDB_SIZE);
  1109. RtlCopyMemory(&CallbackContext->CmdOrb->Cdb, CallbackContext->Srb->Cdb,size);
  1110. //
  1111. // we are done here.... convert command ORB to Big Endian...
  1112. //
  1113. CallbackContext->CmdOrb->OrbInfo.QuadPart = bswap(CallbackContext->CmdOrb->OrbInfo.QuadPart);
  1114. }
  1115. VOID
  1116. Sbp2InsertTailList(
  1117. IN PDEVICE_EXTENSION DeviceExtension,
  1118. IN PASYNC_REQUEST_CONTEXT Context
  1119. )
  1120. {
  1121. ULONG orbListDepth, timeOutValue;
  1122. OCTLET newAddr ;
  1123. NTSTATUS status;
  1124. PASYNC_REQUEST_CONTEXT prevCtx;
  1125. orbListDepth = Context->OrbListDepth;
  1126. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->OrbListSpinLock);
  1127. DeviceExtension->CurrentKey = Context->Srb->QueueSortKey+1;
  1128. if (IsListEmpty (&DeviceExtension->PendingOrbList)) {
  1129. //
  1130. // Empty list, this is the first request
  1131. // This ORB is now at end-of-list, its next_ORB address is set to NULL
  1132. //
  1133. Context->CmdOrb->NextOrbAddress.OctletPart = 0xFFFFFFFFFFFFFFFF;
  1134. //
  1135. // start the timer tracking this request
  1136. // If the list is non empty, only the head of the list is timed...
  1137. //
  1138. timeOutValue = Context->Srb->TimeOutValue;
  1139. DeviceExtension->DueTime.QuadPart =
  1140. ((LONGLONG) timeOutValue) * (-10*1000*1000);
  1141. SET_FLAG(Context->Flags, ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1142. KeSetTimer(
  1143. &Context->Timer,
  1144. DeviceExtension->DueTime,
  1145. &Context->TimerDpc
  1146. );
  1147. InsertTailList (&DeviceExtension->PendingOrbList,&Context->OrbList);
  1148. newAddr = Context->CmdOrbAddress;
  1149. //
  1150. // ISSUE: Seems like we should always be able to write to the
  1151. // dev's orb pointer at this point, but we were seeing
  1152. // timeouts on some devices if we did that (notably
  1153. // hd's with Oxford Semiconductor silicon doing dv cam
  1154. // captures), so am sticking with the piggyback logic
  1155. // for WinXP. This is a perf hit, because dev has to
  1156. // read in the old orb to get the next orb addr, then
  1157. // fetch the new orb. DanKn 25-Jun-2001
  1158. //
  1159. if (DeviceExtension->NextContextToFree &&
  1160. DeviceExtension->AppendToNextContextToFree) {
  1161. DeviceExtension->AppendToNextContextToFree = FALSE;
  1162. //
  1163. // There is an end-of-list ORB, just piggy back on it
  1164. //
  1165. octbswap (newAddr);
  1166. DeviceExtension->NextContextToFree->CmdOrb->NextOrbAddress =
  1167. newAddr;
  1168. DeviceExtension->NextContextToFree->CmdOrb->NextOrbAddress.
  1169. ByteArray.Byte0 = 0; // make Null bit zero
  1170. DeviceExtension->NextContextToFree->CmdOrb->NextOrbAddress.
  1171. ByteArray.Byte1 = 0; // make Null bit zero
  1172. //
  1173. // The guy that was the end of the list cannot be freed
  1174. // until this ORB is fetched
  1175. //
  1176. KeReleaseSpinLockFromDpcLevel (&DeviceExtension->OrbListSpinLock);
  1177. DEBUGPRINT3((
  1178. "Sbp2Port: InsertTailList: empty, ring bell, ctx=x%p\n",
  1179. Context
  1180. ));
  1181. status = Sbp2AccessRegister(
  1182. DeviceExtension,
  1183. &DeviceExtension->Reserved,
  1184. DOORBELL_REG | REG_WRITE_ASYNC
  1185. );
  1186. } else {
  1187. //
  1188. // list is empty, write directly to orb_pointer
  1189. //
  1190. KeReleaseSpinLockFromDpcLevel (&DeviceExtension->OrbListSpinLock);
  1191. DEBUGPRINT3((
  1192. "Sbp2Port: InsertTailList: write ORB_PTR, ctx=x%p\n",
  1193. Context
  1194. ));
  1195. status = Sbp2AccessRegister(
  1196. DeviceExtension,
  1197. &newAddr,
  1198. ORB_POINTER_REG | REG_WRITE_ASYNC
  1199. );
  1200. }
  1201. //
  1202. // The following handles the case where a device is removed
  1203. // while machine is on standby, and then machine is resumed.
  1204. // In the storage case, classpnp.sys sends down a start unit
  1205. // srb (in reponse to the power D-irp) with a timeout of
  1206. // 240 seconds. The problem is that sbp2port.sys does not get
  1207. // notified of the remove until *after* the start unit has
  1208. // timed out (the power irp blocks the pnp irp), and the user
  1209. // gets a bad 240-second wait experience.
  1210. //
  1211. // So what we do here in the case of an invalid generation error
  1212. // & a lengthy timeout is to reset the timer with a more reasonable
  1213. // timeout value. If the device is still around the bus reset
  1214. // notification routine should get called & clean everything up
  1215. // anyway, and same goes for normal remove (while machine is not
  1216. // hibernated).
  1217. //
  1218. if (status == STATUS_INVALID_GENERATION) {
  1219. KeAcquireSpinLockAtDpcLevel (&DeviceExtension->OrbListSpinLock);
  1220. if ((DeviceExtension->PendingOrbList.Flink == &Context->OrbList) &&
  1221. (timeOutValue > 5)) {
  1222. KeCancelTimer (&Context->Timer);
  1223. DeviceExtension->DueTime.QuadPart = (-5 * 10 * 1000 * 1000);
  1224. KeSetTimer(
  1225. &Context->Timer,
  1226. DeviceExtension->DueTime,
  1227. &Context->TimerDpc
  1228. );
  1229. #if DBG
  1230. timeOutValue = 1;
  1231. } else {
  1232. timeOutValue = 0;
  1233. #endif
  1234. }
  1235. KeReleaseSpinLockFromDpcLevel (&DeviceExtension->OrbListSpinLock);
  1236. if (timeOutValue) {
  1237. DEBUGPRINT1((
  1238. "Sbp2port: InsertTailList: ext=x%p, lowered req timeout\n",
  1239. DeviceExtension
  1240. ));
  1241. }
  1242. }
  1243. } else {
  1244. //
  1245. // We have already a list in memory. Append this request to list,
  1246. // modify last request's ORB to point to this ORB.
  1247. //
  1248. newAddr = Context->CmdOrbAddress;
  1249. //
  1250. // Init the list pointer for this request context
  1251. //
  1252. Context->CmdOrb->NextOrbAddress.OctletPart = 0xFFFFFFFFFFFFFFFF;
  1253. //
  1254. // Modify the previous request's command ORB next_ORB address,
  1255. // to point to this ORB. Convert our address to BigEndian first,
  1256. // since the prev command ORB is stored in BigEndian.
  1257. //
  1258. // Note that the previous end-of-list orb may be the completed
  1259. // one pointed at by NextContextToFree (rather the last one in
  1260. // the PendingOrbList), and AppendToNextContextToFree will tell
  1261. // whether that is really the case.
  1262. //
  1263. octbswap (newAddr);
  1264. if (DeviceExtension->NextContextToFree &&
  1265. DeviceExtension->AppendToNextContextToFree) {
  1266. prevCtx = DeviceExtension->NextContextToFree;
  1267. DeviceExtension->AppendToNextContextToFree = FALSE;
  1268. } else {
  1269. prevCtx = (PASYNC_REQUEST_CONTEXT)
  1270. DeviceExtension->PendingOrbList.Blink;
  1271. }
  1272. prevCtx->CmdOrb->NextOrbAddress = newAddr;
  1273. prevCtx->CmdOrb->NextOrbAddress.ByteArray.Byte0 = 0; //make addr active
  1274. prevCtx->CmdOrb->NextOrbAddress.ByteArray.Byte1 = 0;
  1275. //
  1276. // update the end of list
  1277. //
  1278. InsertTailList (&DeviceExtension->PendingOrbList, &Context->OrbList);
  1279. KeReleaseSpinLockFromDpcLevel (&DeviceExtension->OrbListSpinLock);
  1280. DEBUGPRINT3((
  1281. "Sbp2Port: InsertTailList: ring bell, !empty, dep=%d, ctx=x%p\n",
  1282. DeviceExtension->OrbListDepth,
  1283. Context
  1284. ));
  1285. //
  1286. // Ring the door bell to notify the target that our linked list
  1287. // of ORB's has changed
  1288. //
  1289. Sbp2AccessRegister(
  1290. DeviceExtension,
  1291. &DeviceExtension->Reserved,
  1292. DOORBELL_REG | REG_WRITE_ASYNC
  1293. );
  1294. }
  1295. if (orbListDepth < DeviceExtension->MaxOrbListDepth) {
  1296. Sbp2StartNextPacketByKey(
  1297. DeviceExtension->DeviceObject,
  1298. DeviceExtension->CurrentKey
  1299. );
  1300. }
  1301. }
  1302. NTSTATUS
  1303. Sbp2IssueInternalCommand(
  1304. IN PDEVICE_EXTENSION DeviceExtension,
  1305. IN UCHAR Scsiop
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. This routine will a SCSI inquiry command to the target, so we can retireve information about the device
  1310. It should be called only after login and BEFORE we start issueing requests to the device
  1311. It copies the inquiry data into the device extension, for future use
  1312. Arguments:
  1313. DeviceExtension - extension for sbp2 driver
  1314. Return Value:
  1315. --*/
  1316. {
  1317. PSCSI_REQUEST_BLOCK srb;
  1318. PCDB cdb;
  1319. PSENSE_DATA senseInfoBuffer;
  1320. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  1321. ULONG retryCount = 0;
  1322. PREQUEST_CONTEXT context = NULL;
  1323. PMDL inquiryMdl;
  1324. PIRP irp;
  1325. PIO_STACK_LOCATION irpStack;
  1326. PMDL modeMdl;
  1327. KEVENT event;
  1328. LARGE_INTEGER waitValue;
  1329. ULONG i;
  1330. //
  1331. // Sense buffer is in non-paged pool.
  1332. //
  1333. context = ExAllocateFromNPagedLookasideList(&DeviceExtension->BusRequestContextPool);
  1334. if (!context) {
  1335. DEBUGPRINT1(("Sbp2Port: IssueIntl: can't allocate request context\n"));
  1336. return status;
  1337. }
  1338. context->RequestType = SYNC_1394_REQUEST;
  1339. context->DeviceExtension = DeviceExtension;
  1340. context->Packet = NULL;
  1341. senseInfoBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned,
  1342. SENSE_BUFFER_SIZE,'2pbs');
  1343. if (senseInfoBuffer == NULL) {
  1344. DEBUGPRINT1(("Sbp2Port: IssueIntl: can't allocate request sense buffer\n"));
  1345. return status;
  1346. }
  1347. srb = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
  1348. sizeof(SCSI_REQUEST_BLOCK),'2pbs');
  1349. if (srb == NULL) {
  1350. ExFreePool(senseInfoBuffer);
  1351. ExFreeToNPagedLookasideList(&DeviceExtension->BusRequestContextPool, context);
  1352. DEBUGPRINT1(("Sbp2Port: IssueIntl: can't allocate request sense buffer\n"));
  1353. return status;
  1354. }
  1355. irp = IoAllocateIrp((CCHAR)(DeviceExtension->DeviceObject->StackSize), FALSE);
  1356. if (irp == NULL) {
  1357. ExFreePool(senseInfoBuffer);
  1358. ExFreePool(srb);
  1359. ExFreeToNPagedLookasideList(&DeviceExtension->BusRequestContextPool, context);
  1360. DEBUGPRINT1(("Sbp2Port: IssueIntl: can't allocate IRP\n"));
  1361. return status;
  1362. }
  1363. do {
  1364. //
  1365. // Construct the IRP stack for the lower level driver.
  1366. //
  1367. irpStack = IoGetNextIrpStackLocation(irp);
  1368. irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1369. irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
  1370. irpStack->Parameters.Scsi.Srb = srb;
  1371. //
  1372. // Fill in SRB fieldsthat Create1394RequestFromSrb needs.
  1373. //
  1374. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  1375. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  1376. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  1377. //
  1378. // Set flags to disable synchronous negociation.
  1379. //
  1380. srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  1381. srb->SrbStatus = srb->ScsiStatus = 0;
  1382. //
  1383. // Set timeout to 12 seconds.
  1384. //
  1385. srb->TimeOutValue = 24;
  1386. srb->CdbLength = 6;
  1387. //
  1388. // Enable auto request sense.
  1389. //
  1390. srb->SenseInfoBuffer = senseInfoBuffer;
  1391. srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
  1392. cdb = (PCDB)srb->Cdb;
  1393. switch (Scsiop) {
  1394. case SCSIOP_INQUIRY:
  1395. srb->DataBuffer = &DeviceExtension->InquiryData;
  1396. srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
  1397. //
  1398. // Set CDB LUN.
  1399. //
  1400. cdb->CDB6INQUIRY.LogicalUnitNumber = (UCHAR) DeviceExtension->DeviceInfo->Lun.u.LowPart;
  1401. cdb->CDB6INQUIRY.Reserved1 = 0;
  1402. cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
  1403. //
  1404. // Zero reserve field and
  1405. // Set EVPD Page Code to zero.
  1406. // Set Control field to zero.
  1407. // (See SCSI-II Specification.)
  1408. //
  1409. cdb->CDB6INQUIRY.PageCode = 0;
  1410. cdb->CDB6INQUIRY.IReserved = 0;
  1411. cdb->CDB6INQUIRY.Control = 0;
  1412. if (!retryCount) {
  1413. inquiryMdl = IoAllocateMdl(&DeviceExtension->InquiryData, INQUIRYDATABUFFERSIZE,FALSE,FALSE,NULL);
  1414. if (!inquiryMdl) {
  1415. goto exitSbp2Internal;
  1416. }
  1417. MmBuildMdlForNonPagedPool(inquiryMdl);
  1418. }
  1419. irp->MdlAddress = inquiryMdl;
  1420. break;
  1421. case SCSIOP_MODE_SENSE:
  1422. srb->DataBuffer = &DeviceExtension->DeviceModeHeaderAndPage;
  1423. srb->DataTransferLength = sizeof(DeviceExtension->DeviceModeHeaderAndPage);
  1424. //
  1425. // Setup CDB.
  1426. //
  1427. cdb->MODE_SENSE.Dbd = 1; // disable block descriptors
  1428. cdb->MODE_SENSE.PageCode = MODE_PAGE_RBC_DEVICE_PARAMETERS;
  1429. cdb->MODE_SENSE.Pc = 0; // get current values
  1430. cdb->MODE_SENSE.AllocationLength = sizeof(DeviceExtension->DeviceModeHeaderAndPage);
  1431. if (!retryCount) {
  1432. modeMdl = IoAllocateMdl(
  1433. &DeviceExtension->DeviceModeHeaderAndPage,
  1434. sizeof (DeviceExtension->DeviceModeHeaderAndPage),
  1435. FALSE,
  1436. FALSE,
  1437. NULL
  1438. );
  1439. if (!modeMdl) {
  1440. goto exitSbp2Internal;
  1441. }
  1442. MmBuildMdlForNonPagedPool(modeMdl);
  1443. }
  1444. irp->MdlAddress = modeMdl;
  1445. break;
  1446. }
  1447. //
  1448. // Set CDB operation code.
  1449. //
  1450. cdb->CDB6GENERIC.OperationCode = Scsiop;
  1451. srb->OriginalRequest = irp;
  1452. KeInitializeEvent(&context->Event,
  1453. NotificationEvent,
  1454. FALSE);
  1455. IoSetCompletionRoutine(irp,
  1456. Sbp2RequestCompletionRoutine,
  1457. context,
  1458. TRUE,
  1459. TRUE,
  1460. TRUE);
  1461. DEBUGPRINT2(("Sbp2Port: IssueIntl: sending scsiop x%x, irp=x%p\n", Scsiop, irp));
  1462. status = IoCallDriver(DeviceExtension->DeviceObject, irp);
  1463. if(!NT_SUCCESS(irp->IoStatus.Status) && status!=STATUS_PENDING) {
  1464. status = irp->IoStatus.Status;
  1465. DEBUGPRINT1(("Sbp2Port: IssueIntl: scsiop=x%x irp=x%p err, sts=x%x srbSts=x%x\n",Scsiop,irp, status,srb->SrbStatus));
  1466. break;
  1467. }
  1468. KeWaitForSingleObject (&context->Event, Executive, KernelMode, FALSE, NULL);
  1469. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
  1470. DEBUGPRINT3(("Sbp2Port: IssueIntl: scsiop=x%x err, srbSts=%x\n",Scsiop, srb->SrbStatus));
  1471. if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
  1472. DEBUGPRINT1(("Sbp2Port: IssueIntl: Data underrun \n"));
  1473. status = STATUS_SUCCESS;
  1474. } else if ((srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
  1475. senseInfoBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST){
  1476. //
  1477. // A sense key of illegal request was recieved. This indicates
  1478. // that the logical unit number of not valid but there is a
  1479. // target device out there.
  1480. //
  1481. status = STATUS_INVALID_DEVICE_REQUEST;
  1482. retryCount++;
  1483. } else {
  1484. //
  1485. // If the device timed out the request chances are the
  1486. // irp will have been completed by CleanupOrbList with
  1487. // and SRB...FLUSHED error, and we don't want to
  1488. // entertain any devices which are timing out requests
  1489. //
  1490. if ((SRB_STATUS(srb->SrbStatus) ==
  1491. SRB_STATUS_REQUEST_FLUSHED) &&
  1492. (retryCount > 0)) {
  1493. status = STATUS_DEVICE_BUSY;
  1494. break;
  1495. }
  1496. retryCount++;
  1497. DEBUGPRINT1((
  1498. "Sbp2Port: IssueIntl: ext=x%p, cdb=x%x, retry %d\n",
  1499. DeviceExtension,
  1500. Scsiop,
  1501. retryCount
  1502. ));
  1503. status = STATUS_UNSUCCESSFUL;
  1504. }
  1505. //
  1506. // If unsuccessful & a reset is in progress & retries not max'd
  1507. // then give things some time to settle before retry. Check at
  1508. // one second intervals for a few seconds to give soft & hard
  1509. // resets time to complete :
  1510. //
  1511. // SBP2_RESET_TIMEOUT + SBP2_HARD_RESET_TIMEOUT + etc
  1512. //
  1513. if ((status != STATUS_SUCCESS) &&
  1514. (DeviceExtension->DeviceFlags &
  1515. DEVICE_FLAG_RESET_IN_PROGRESS) &&
  1516. (retryCount < 3)) {
  1517. DEBUGPRINT1((
  1518. "Sbp2Port: IssueIntl: ext=x%p, reset in progress, " \
  1519. "so wait...\n",
  1520. DeviceExtension,
  1521. Scsiop,
  1522. retryCount
  1523. ));
  1524. for (i = 0; i < 6; i++) {
  1525. ASSERT(InterlockedIncrement(&DeviceExtension->ulInternalEventCount) == 1);
  1526. KeInitializeEvent (&event, NotificationEvent, FALSE);
  1527. waitValue.QuadPart = -1 * 1000 * 1000 * 10;
  1528. KeWaitForSingleObject(
  1529. &event,
  1530. Executive,
  1531. KernelMode,
  1532. FALSE,
  1533. &waitValue
  1534. );
  1535. ASSERT(InterlockedDecrement(&DeviceExtension->ulInternalEventCount) == 0);
  1536. if (!(DeviceExtension->DeviceFlags &
  1537. DEVICE_FLAG_RESET_IN_PROGRESS)) {
  1538. break;
  1539. }
  1540. }
  1541. }
  1542. } else {
  1543. status = STATUS_SUCCESS;
  1544. }
  1545. } while ((retryCount < 3) && (status != STATUS_SUCCESS));
  1546. exitSbp2Internal:
  1547. //
  1548. // Free request sense buffer.
  1549. //
  1550. ExFreePool(senseInfoBuffer);
  1551. ExFreePool(srb);
  1552. IoFreeMdl(irp->MdlAddress);
  1553. IoFreeIrp(irp);
  1554. ExFreeToNPagedLookasideList(&DeviceExtension->BusRequestContextPool, context);
  1555. return status;
  1556. }
  1557. NTSTATUS
  1558. Sbp2_ScsiPassThrough(
  1559. IN PDEVICE_OBJECT DeviceObject,
  1560. IN PIRP Irp,
  1561. IN BOOLEAN Direct
  1562. )
  1563. {
  1564. PDEVICE_EXTENSION PdoExtension = DeviceObject->DeviceExtension;
  1565. NTSTATUS ntStatus;
  1566. PIO_SCSI_CAPABILITIES ioCapabilities;
  1567. PAGED_CODE();
  1568. TRACE(TL_SCSI_INFO, ("DeviceObject = 0x%x PdoExtension = 0x%x", DeviceObject, PdoExtension));
  1569. if (TEST_FLAG(PdoExtension->DeviceFlags, DEVICE_FLAG_CLAIMED)) {
  1570. TRACE(TL_SCSI_WARNING, ("Sbp2_ScsiPassThrough: device is claimed."));
  1571. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  1572. goto Exit_Sbp2_ScsiPassThrough;
  1573. }
  1574. // TODO: save this in the device extension
  1575. ioCapabilities = ExAllocatePool(NonPagedPool, sizeof(IO_SCSI_CAPABILITIES));
  1576. if (!ioCapabilities) {
  1577. TRACE(TL_SCSI_ERROR, ("Failed to allocate ioCapabilities!"));
  1578. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1579. goto Exit_Sbp2_ScsiPassThrough;
  1580. }
  1581. RtlZeroMemory(ioCapabilities, sizeof(IO_SCSI_CAPABILITIES));
  1582. ioCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
  1583. ioCapabilities->MaximumTransferLength = PdoExtension->DeviceInfo->MaxClassTransferSize;
  1584. ioCapabilities->MaximumPhysicalPages = ioCapabilities->MaximumTransferLength/PAGE_SIZE;
  1585. ioCapabilities->SupportedAsynchronousEvents = 0; // ??
  1586. ioCapabilities->AlignmentMask = DeviceObject->AlignmentRequirement;
  1587. ioCapabilities->TaggedQueuing = FALSE; // ??
  1588. ioCapabilities->AdapterScansDown = FALSE;
  1589. ioCapabilities->AdapterUsesPio = FALSE;
  1590. ntStatus = PortSendPassThrough( DeviceObject,
  1591. Irp,
  1592. Direct,
  1593. 0,
  1594. ioCapabilities
  1595. );
  1596. if (!NT_SUCCESS(ntStatus)) {
  1597. TRACE(TL_SCSI_ERROR, ("PortSendPassThrough Failed = 0x%x", ntStatus));
  1598. }
  1599. ExFreePool(ioCapabilities);
  1600. Exit_Sbp2_ScsiPassThrough:
  1601. Irp->IoStatus.Status = ntStatus;
  1602. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1603. return(ntStatus);
  1604. } // Sbp2_ScsiPassThrough
  1605. BOOLEAN
  1606. ConvertSbp2SenseDataToScsi(
  1607. IN PSTATUS_FIFO_BLOCK StatusBlock,
  1608. OUT PUCHAR SenseBuffer,
  1609. ULONG SenseBufferLength
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. This routine will convert the sense information returned in an SBP-2 status block, to SCSI-2/3 sense data
  1614. and put them the translated on the SenseBuffer passed as an argument
  1615. Arguments:
  1616. StatusBlock - Sbp2 staus for completed ORB
  1617. SenseBuffer - Buffer to fill in with translated Sense Data. This buffer comes with the original SRB
  1618. Return Value:
  1619. --*/
  1620. {
  1621. BOOLEAN validSense = FALSE;
  1622. if (!SenseBuffer || (SenseBufferLength < 0xE) ) {
  1623. return FALSE;
  1624. }
  1625. RtlZeroMemory(SenseBuffer,SenseBufferLength);
  1626. //
  1627. // determine sense error code
  1628. //
  1629. if ((StatusBlock->Contents[0].ByteArray.Byte0 & STATUS_BLOCK_SFMT_MASK) == SENSE_DATA_STATUS_BLOCK ) {
  1630. SenseBuffer[0] = 0x70;
  1631. validSense = TRUE;
  1632. } else if ((StatusBlock->Contents[0].ByteArray.Byte0 & STATUS_BLOCK_SFMT_MASK) == SENSE_DATA_DEFF_STATUS_BLOCK){
  1633. SenseBuffer[0] = 0x71;
  1634. validSense = TRUE;
  1635. }
  1636. if (validSense) {
  1637. SenseBuffer[0] |= 0x80 & StatusBlock->Contents[0].ByteArray.Byte1; // valid bit
  1638. SenseBuffer[1] = 0; // segment number not supported in sbp2
  1639. SenseBuffer[2] = (0x70 & StatusBlock->Contents[0].ByteArray.Byte1) << 1; // filemark bit, eom bit, ILI bit
  1640. SenseBuffer[2] |= 0x0f & StatusBlock->Contents[0].ByteArray.Byte1; // sense key
  1641. SenseBuffer[3] = StatusBlock->Contents[0].ByteArray.Byte4; // Information field
  1642. SenseBuffer[4] = StatusBlock->Contents[0].ByteArray.Byte5;
  1643. SenseBuffer[5] = StatusBlock->Contents[0].ByteArray.Byte6;
  1644. SenseBuffer[6] = StatusBlock->Contents[0].ByteArray.Byte7;
  1645. SenseBuffer[7] = 0xb; // additional sense length
  1646. SenseBuffer[8] = StatusBlock->Contents[1].ByteArray.Byte0; // Command Block dependent bytes
  1647. SenseBuffer[9] = StatusBlock->Contents[1].ByteArray.Byte1;
  1648. SenseBuffer[10] = StatusBlock->Contents[1].ByteArray.Byte2;
  1649. SenseBuffer[11] = StatusBlock->Contents[1].ByteArray.Byte3;
  1650. SenseBuffer[12] = StatusBlock->Contents[0].ByteArray.Byte2; // sense code
  1651. SenseBuffer[13] = StatusBlock->Contents[0].ByteArray.Byte3; // additional sense code qualifier
  1652. if (SenseBufferLength >= SENSE_BUFFER_SIZE ) {
  1653. // FRU byte
  1654. SenseBuffer[14] |= StatusBlock->Contents[1].ByteArray.Byte4;
  1655. // Sense key dependent bytes
  1656. SenseBuffer[15] = StatusBlock->Contents[1].ByteArray.Byte5;
  1657. SenseBuffer[16] = StatusBlock->Contents[1].ByteArray.Byte6;
  1658. SenseBuffer[17] = StatusBlock->Contents[1].ByteArray.Byte7;
  1659. }
  1660. }
  1661. return validSense;
  1662. }