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.

1897 lines
47 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 2001
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Utility functions for the SBP-2 port driver
  7. Author:
  8. George Chrysanthakopoulos January-1997
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "sbp2port.h"
  14. VOID
  15. AllocateIrpAndIrb(
  16. IN PDEVICE_EXTENSION DeviceExtension,
  17. IN PIRBIRP *Packet
  18. )
  19. {
  20. PIRBIRP pkt;
  21. if (DeviceExtension->Type == SBP2_PDO) {
  22. *Packet = (PIRBIRP) ExInterlockedPopEntrySList (&DeviceExtension->BusRequestIrpIrbListHead,
  23. &DeviceExtension->BusRequestLock);
  24. } else {
  25. *Packet = NULL;
  26. }
  27. if (*Packet == NULL) {
  28. //
  29. // run out , allocate a new one
  30. //
  31. pkt = ExAllocatePoolWithTag(NonPagedPool,sizeof(IRBIRP),'2pbs');
  32. if (pkt) {
  33. pkt->Irb = NULL;
  34. pkt->Irb = ExAllocatePoolWithTag(NonPagedPool,sizeof(IRB),'2pbs');
  35. if (!pkt->Irb) {
  36. ExFreePool(pkt);
  37. return;
  38. }
  39. pkt->Irp = NULL;
  40. pkt->Irp = IoAllocateIrp(DeviceExtension->LowerDeviceObject->StackSize,FALSE);
  41. if (!pkt->Irp) {
  42. ExFreePool(pkt->Irb);
  43. ExFreePool(pkt);
  44. return;
  45. }
  46. DEBUGPRINT3((
  47. "Sbp2Port: AllocPkt: %sdo, new irp=x%p, irb=x%p\n",
  48. (DeviceExtension->Type == SBP2_PDO ? "p" : "f"),
  49. pkt->Irp,
  50. pkt->Irb
  51. ));
  52. } else {
  53. return;
  54. }
  55. *Packet = pkt;
  56. }
  57. pkt = *Packet;
  58. }
  59. VOID
  60. DeAllocateIrpAndIrb(
  61. IN PDEVICE_EXTENSION DeviceExtension,
  62. IN PIRBIRP Packet
  63. )
  64. {
  65. if (DeviceExtension->Type == SBP2_PDO) {
  66. ExInterlockedPushEntrySList (&DeviceExtension->BusRequestIrpIrbListHead,
  67. &Packet->ListPointer,
  68. &DeviceExtension->BusRequestLock);
  69. } else {
  70. IoFreeIrp(Packet->Irp);
  71. ExFreePool(Packet->Irb);
  72. ExFreePool(Packet);
  73. }
  74. }
  75. NTSTATUS
  76. AllocateSingle1394Address(
  77. IN PDEVICE_OBJECT DeviceObject,
  78. IN PVOID Buffer,
  79. IN ULONG Length,
  80. IN ULONG AccessType,
  81. IN OUT PADDRESS_CONTEXT Context
  82. )
  83. /*++
  84. Routine Description:
  85. A wrapper to the bus driver AllocateAddressRange call, for Async Requests
  86. or ORB's that dont use callbacks.
  87. Arguments:
  88. DeviceObject - Sbp2 device object
  89. Buffer - Data buffer to mapped to 1394 address space
  90. Length - Size of buffer in bytes
  91. AccessType - 1394 bus access to allocated range
  92. Address - Returned Address, from 1394 address space
  93. AddressHanle - Handle associated with the 1394 address
  94. RequestMedl - Mdl associated with this range
  95. Return Value:
  96. NTSTATUS
  97. --*/
  98. {
  99. ULONG finalTransferMode;
  100. PIRBIRP packet;
  101. NTSTATUS status;
  102. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  103. AllocateIrpAndIrb (deviceExtension, &packet);
  104. if (!packet) {
  105. return STATUS_INSUFFICIENT_RESOURCES;
  106. }
  107. packet->Irb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
  108. packet->Irb->Flags = 0;
  109. packet->Irb->u.AllocateAddressRange.MaxSegmentSize = 0;
  110. packet->Irb->u.AllocateAddressRange.nLength = Length;
  111. packet->Irb->u.AllocateAddressRange.fulAccessType = AccessType;
  112. packet->Irb->u.AllocateAddressRange.fulNotificationOptions = NOTIFY_FLAGS_NEVER;
  113. packet->Irb->u.AllocateAddressRange.Callback = NULL;
  114. packet->Irb->u.AllocateAddressRange.Context = NULL;
  115. packet->Irb->u.AllocateAddressRange.FifoSListHead = NULL;
  116. packet->Irb->u.AllocateAddressRange.FifoSpinLock = NULL;
  117. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_High = 0;
  118. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_Low = 0;
  119. packet->Irb->u.AllocateAddressRange.AddressesReturned = 0;
  120. packet->Irb->u.AllocateAddressRange.DeviceExtension = deviceExtension;
  121. packet->Irb->u.AllocateAddressRange.p1394AddressRange = (PADDRESS_RANGE) &Context->Address;
  122. if (Buffer) {
  123. packet->Irb->u.AllocateAddressRange.fulFlags = 0;
  124. Context->RequestMdl = IoAllocateMdl (Buffer, Length, FALSE, FALSE, NULL);
  125. if (!Context->RequestMdl) {
  126. DeAllocateIrpAndIrb (deviceExtension,packet);
  127. return STATUS_INSUFFICIENT_RESOURCES;
  128. }
  129. MmBuildMdlForNonPagedPool (Context->RequestMdl);
  130. packet->Irb->u.AllocateAddressRange.Mdl = Context->RequestMdl;
  131. } else {
  132. packet->Irb->u.AllocateAddressRange.fulFlags =
  133. ALLOCATE_ADDRESS_FLAGS_USE_COMMON_BUFFER;
  134. packet->Irb->u.AllocateAddressRange.Mdl = NULL;
  135. }
  136. status = Sbp2SendRequest (deviceExtension, packet, SYNC_1394_REQUEST);
  137. if (NT_SUCCESS(status)) {
  138. Context->AddressHandle =
  139. packet->Irb->u.AllocateAddressRange.hAddressRange;
  140. Context->Address.BusAddress.NodeId =
  141. deviceExtension->InitiatorAddressId;
  142. if (!Buffer) {
  143. //
  144. // For common buffers we get an mdl *back* from the
  145. // bus/port driver, & need to retrieve a corresponding VA
  146. //
  147. Context->RequestMdl = packet->Irb->u.AllocateAddressRange.Mdl;
  148. Context->Reserved = MmGetMdlVirtualAddress (Context->RequestMdl);
  149. }
  150. }
  151. DeAllocateIrpAndIrb (deviceExtension, packet);
  152. return status;
  153. }
  154. NTSTATUS
  155. AllocateAddressForStatus(
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PADDRESS_CONTEXT Context,
  158. IN UCHAR StatusType
  159. )
  160. /*++
  161. Routine Description:
  162. A wrapper to 1394 bus IOCTL AllocateAddressRange for status blocks that
  163. need a Callback notification when the device access the 1394 range...
  164. Arguments:
  165. DeviceObject - Device Object for the sbp2 driver
  166. ADDRESS_CONTEXT - Mini Context for an individual 1394 request
  167. Return Value:
  168. NTSTATUS
  169. --*/
  170. {
  171. NTSTATUS status;
  172. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  173. PIRBIRP packet = NULL;
  174. AllocateIrpAndIrb (deviceExtension,&packet);
  175. if (!packet) {
  176. return STATUS_INSUFFICIENT_RESOURCES;
  177. }
  178. packet->Irb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
  179. packet->Irb->Flags = 0;
  180. packet->Irb->u.AllocateAddressRange.nLength = sizeof(STATUS_FIFO_BLOCK);
  181. packet->Irb->u.AllocateAddressRange.fulAccessType = ACCESS_FLAGS_TYPE_WRITE;
  182. packet->Irb->u.AllocateAddressRange.fulNotificationOptions = NOTIFY_FLAGS_AFTER_WRITE;
  183. packet->Irb->u.AllocateAddressRange.FifoSListHead = NULL;
  184. packet->Irb->u.AllocateAddressRange.FifoSpinLock = NULL;
  185. packet->Irb->u.AllocateAddressRange.fulFlags = 0;
  186. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_High = 0;
  187. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_Low = 0;
  188. packet->Irb->u.AllocateAddressRange.AddressesReturned = 0;
  189. packet->Irb->u.AllocateAddressRange.MaxSegmentSize = 0;
  190. packet->Irb->u.AllocateAddressRange.DeviceExtension = deviceExtension;
  191. switch (StatusType) {
  192. case TASK_STATUS_BLOCK:
  193. packet->Irb->u.AllocateAddressRange.Callback = Sbp2TaskOrbStatusCallback;
  194. Context->RequestMdl = IoAllocateMdl(&deviceExtension->TaskOrbStatusBlock, sizeof (STATUS_FIFO_BLOCK),FALSE,FALSE,NULL);
  195. if (!Context->RequestMdl) {
  196. status = STATUS_INSUFFICIENT_RESOURCES;
  197. goto exitAllocateAddress;
  198. }
  199. break;
  200. case MANAGEMENT_STATUS_BLOCK:
  201. packet->Irb->u.AllocateAddressRange.Callback = Sbp2ManagementOrbStatusCallback;
  202. Context->RequestMdl = IoAllocateMdl(&deviceExtension->ManagementOrbStatusBlock, sizeof (STATUS_FIFO_BLOCK),FALSE,FALSE,NULL);
  203. if (!Context->RequestMdl) {
  204. status = STATUS_INSUFFICIENT_RESOURCES;
  205. goto exitAllocateAddress;
  206. }
  207. break;
  208. case CMD_ORB_STATUS_BLOCK:
  209. //
  210. // setup the FIFO list that will receive the status blocks
  211. //
  212. packet->Irb->u.AllocateAddressRange.Callback = Sbp2GlobalStatusCallback;
  213. Context->RequestMdl = packet->Irb->u.AllocateAddressRange.Mdl = NULL;
  214. packet->Irb->u.AllocateAddressRange.FifoSListHead = &deviceExtension->StatusFifoListHead;
  215. packet->Irb->u.AllocateAddressRange.FifoSpinLock = &deviceExtension->StatusFifoLock;
  216. break;
  217. #if PASSWORD_SUPPORT
  218. case PASSWORD_STATUS_BLOCK:
  219. packet->Irb->u.AllocateAddressRange.Callback =
  220. Sbp2SetPasswordOrbStatusCallback;
  221. Context->RequestMdl = IoAllocateMdl(
  222. &deviceExtension->PasswordOrbStatusBlock,
  223. sizeof(STATUS_FIFO_BLOCK),
  224. FALSE,
  225. FALSE,
  226. NULL
  227. );
  228. if (!Context->RequestMdl) {
  229. status = STATUS_INSUFFICIENT_RESOURCES;
  230. goto exitAllocateAddress;
  231. }
  232. break;
  233. #endif
  234. }
  235. if (Context->RequestMdl) {
  236. MmBuildMdlForNonPagedPool(Context->RequestMdl);
  237. }
  238. packet->Irb->u.AllocateAddressRange.Mdl = Context->RequestMdl;
  239. packet->Irb->u.AllocateAddressRange.Context = Context;
  240. packet->Irb->u.AllocateAddressRange.p1394AddressRange = (PADDRESS_RANGE)&Context->Address;
  241. status = Sbp2SendRequest (deviceExtension, packet, SYNC_1394_REQUEST);
  242. if (NT_SUCCESS(status)) {
  243. //
  244. // Setup the address context for the status block
  245. //
  246. Context->AddressHandle = packet->Irb->u.AllocateAddressRange.hAddressRange;
  247. Context->DeviceObject = DeviceObject;
  248. Context->Address.BusAddress.NodeId = deviceExtension->InitiatorAddressId;
  249. }
  250. exitAllocateAddress:
  251. DeAllocateIrpAndIrb (deviceExtension, packet);
  252. return status;
  253. }
  254. VOID
  255. CleanupOrbList(
  256. PDEVICE_EXTENSION DeviceExtension,
  257. NTSTATUS CompletionStatus
  258. )
  259. /*++
  260. Routine Description:
  261. This routine will free a linked list of RequestContexts
  262. and will also free the 1394 addresses associated with the
  263. buffers in the context. If the DEVICE_FLAG_RECONNECT i set
  264. instead of completing pending irps, it will requeue them...
  265. Arguments:
  266. DeviceExtension - Device Extension of the sbp2 device
  267. CompletionSTATUS - If one of the linked requests is not completed,
  268. complete it with this status
  269. Return Value:
  270. None
  271. --*/
  272. {
  273. PIRP requestIrp;
  274. PASYNC_REQUEST_CONTEXT currentListItem;
  275. PASYNC_REQUEST_CONTEXT lastItem,nextItem;
  276. KIRQL oldIrql;
  277. //
  278. // Go through the linked list, complete its original Irp and
  279. // free all the associated memory and 1394 resources...
  280. // Since this function is called when we get a REMOVE irp,
  281. // all irps will be terminated with error status
  282. //
  283. KeAcquireSpinLock(&DeviceExtension->OrbListSpinLock,&oldIrql);
  284. if (DeviceExtension->NextContextToFree) {
  285. FreeAsyncRequestContext(DeviceExtension,DeviceExtension->NextContextToFree);
  286. DeviceExtension->NextContextToFree = NULL;
  287. }
  288. if (IsListEmpty (&DeviceExtension->PendingOrbList)) {
  289. //
  290. // nothing to do
  291. //
  292. KeReleaseSpinLock (&DeviceExtension->OrbListSpinLock,oldIrql);
  293. return;
  294. } else {
  295. nextItem = RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Flink,OrbList);
  296. lastItem = RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Blink,OrbList);
  297. InitializeListHead(&DeviceExtension->PendingOrbList);
  298. KeReleaseSpinLock(&DeviceExtension->OrbListSpinLock,oldIrql);
  299. }
  300. //
  301. // Qe have essentially detached this pending context list from
  302. // the main list so we can now free it without holding the lock
  303. // and allowing other requests to be processed.
  304. //
  305. do {
  306. currentListItem = nextItem;
  307. nextItem = (PASYNC_REQUEST_CONTEXT) currentListItem->OrbList.Flink;
  308. if (!TEST_FLAG(currentListItem->Flags,ASYNC_CONTEXT_FLAG_COMPLETED)) {
  309. SET_FLAG(currentListItem->Flags,ASYNC_CONTEXT_FLAG_COMPLETED);
  310. CLEAR_FLAG(currentListItem->Flags, ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  311. Sbp2_SCSI_RBC_Conversion (currentListItem); // unwind MODE_SENSE hacks
  312. KeCancelTimer(&currentListItem->Timer);
  313. requestIrp =(PIRP)currentListItem->Srb->OriginalRequest;
  314. requestIrp->IoStatus.Status = CompletionStatus;
  315. switch (CompletionStatus) {
  316. case STATUS_DEVICE_DOES_NOT_EXIST:
  317. currentListItem->Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  318. break;
  319. case STATUS_REQUEST_ABORTED:
  320. currentListItem->Srb->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
  321. break;
  322. case STATUS_IO_TIMEOUT:
  323. currentListItem->Srb->SrbStatus = SRB_STATUS_TIMEOUT;
  324. break;
  325. default:
  326. currentListItem->Srb->SrbStatus = SRB_STATUS_ERROR;
  327. break;
  328. }
  329. if (requestIrp->Type == IO_TYPE_IRP) {
  330. if (TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_RECONNECT)) {
  331. Sbp2StartPacket(
  332. DeviceExtension->DeviceObject,
  333. requestIrp,
  334. &currentListItem->Srb->QueueSortKey
  335. );
  336. //
  337. // free everything related to this request
  338. //
  339. currentListItem->Srb = NULL;
  340. FreeAsyncRequestContext (DeviceExtension, currentListItem);
  341. } else {
  342. //
  343. // free everything related to this request
  344. //
  345. currentListItem->Srb = NULL;
  346. FreeAsyncRequestContext (DeviceExtension, currentListItem);
  347. DEBUGPRINT2(("Sbp2Port: CleanupOrbList: aborted irp x%p compl\n", requestIrp));
  348. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, NULL);
  349. IoCompleteRequest (requestIrp, IO_NO_INCREMENT);
  350. }
  351. }
  352. } else {
  353. //
  354. // free everything related to this request
  355. //
  356. FreeAsyncRequestContext (DeviceExtension, currentListItem);
  357. }
  358. } while (lastItem != currentListItem); // while loop
  359. return;
  360. }
  361. VOID
  362. FreeAddressRange(
  363. IN PDEVICE_EXTENSION DeviceExtension,
  364. IN PADDRESS_CONTEXT Context
  365. )
  366. /*++
  367. Routine Description:
  368. 1394 BUS IOCTL call for freeing an address range.
  369. Arguments:
  370. DeviceExtension - Pointer to sbp2 deviceExtension.
  371. context - address context
  372. Return Value:
  373. NTSTATUS
  374. --*/
  375. {
  376. PIRBIRP packet ;
  377. if (Context->AddressHandle == NULL) {
  378. return;
  379. }
  380. AllocateIrpAndIrb (DeviceExtension, &packet);
  381. if (!packet) {
  382. return;
  383. }
  384. //
  385. // FreeAddressRange is synchronous call
  386. //
  387. packet->Irb->FunctionNumber = REQUEST_FREE_ADDRESS_RANGE;
  388. packet->Irb->Flags = 0;
  389. //
  390. // We always free one address handle even it refers to multiple
  391. // 1394 addresses. The mdl associated with the original Allocate
  392. // is freed by the port driver.
  393. //
  394. packet->Irb->u.FreeAddressRange.nAddressesToFree = 1;
  395. packet->Irb->u.FreeAddressRange.p1394AddressRange = (PADDRESS_RANGE) &Context->Address;
  396. packet->Irb->u.FreeAddressRange.pAddressRange = &Context->AddressHandle;
  397. if (Context->RequestMdl) {
  398. if (Context == &DeviceExtension->CommonBufferContext) {
  399. Context->RequestMdl = NULL; // common buffer, we didn't alloc mdl
  400. } else {
  401. packet->Irb->u.FreeAddressRange.p1394AddressRange->AR_Length =
  402. (USHORT) MmGetMdlByteCount(Context->RequestMdl);
  403. }
  404. } else if (Context == (PADDRESS_CONTEXT) &DeviceExtension->GlobalStatusContext) {
  405. packet->Irb->u.FreeAddressRange.p1394AddressRange->AR_Length = sizeof(STATUS_FIFO_BLOCK);
  406. }
  407. packet->Irb->u.FreeAddressRange.DeviceExtension = DeviceExtension;
  408. if ((KeGetCurrentIrql() >= DISPATCH_LEVEL) && !Context->Address.BusAddress.Off_High) {
  409. PPORT_PHYS_ADDR_ROUTINE routine = DeviceExtension->HostRoutineAPI.PhysAddrMappingRoutine;
  410. (*routine) (DeviceExtension->HostRoutineAPI.Context,packet->Irb);
  411. } else {
  412. //
  413. // dont care about the status of this op
  414. //
  415. Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  416. }
  417. Context->AddressHandle = NULL;
  418. if (Context->RequestMdl) {
  419. IoFreeMdl (Context->RequestMdl);
  420. Context->RequestMdl = NULL;
  421. }
  422. DeAllocateIrpAndIrb (DeviceExtension, packet);
  423. }
  424. VOID
  425. Free1394DataMapping(
  426. PDEVICE_EXTENSION DeviceExtension,
  427. PASYNC_REQUEST_CONTEXT Context
  428. )
  429. {
  430. PIRBIRP packet ;
  431. if (Context->DataMappingHandle == NULL) {
  432. return;
  433. }
  434. AllocateIrpAndIrb (DeviceExtension, &packet);
  435. if (!packet) {
  436. return;
  437. }
  438. //
  439. // Free the data buffer's 1394 address range
  440. //
  441. packet->Irb->FunctionNumber = REQUEST_FREE_ADDRESS_RANGE;
  442. packet->Irb->Flags = 0;
  443. packet->Irb->u.FreeAddressRange.nAddressesToFree = 1;
  444. packet->Irb->u.FreeAddressRange.p1394AddressRange = (PADDRESS_RANGE) NULL;
  445. packet->Irb->u.FreeAddressRange.pAddressRange = &Context->DataMappingHandle;
  446. packet->Irb->u.FreeAddressRange.DeviceExtension = DeviceExtension;
  447. if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
  448. PPORT_PHYS_ADDR_ROUTINE routine = DeviceExtension->HostRoutineAPI.PhysAddrMappingRoutine;
  449. (*routine) (DeviceExtension->HostRoutineAPI.Context, packet->Irb);
  450. } else {
  451. //
  452. // dont care about the status of this op
  453. //
  454. Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  455. }
  456. if (Context->PartialMdl) {
  457. IoFreeMdl (Context->PartialMdl);
  458. Context->PartialMdl = NULL;
  459. }
  460. Context->DataMappingHandle = NULL;
  461. DeAllocateIrpAndIrb (DeviceExtension, packet);
  462. }
  463. ULONG
  464. FreeAsyncRequestContext(
  465. PDEVICE_EXTENSION DeviceExtension,
  466. PASYNC_REQUEST_CONTEXT Context
  467. )
  468. /*++
  469. Routine Description:
  470. This routine will free a single RequestContext and will cleanup all
  471. its buffers and 1394 ranges, ONLY of the device is marked as STOPPED.
  472. Otherwise it will add the context to the FreeList, so it can be reused
  473. later one by another request. This way we are drastically speeding up
  474. each request.
  475. Arguments:
  476. DeviceExtension - Device Extension of the sbp2 device
  477. Context - Context to freed or returned to FreeList
  478. Return Value:
  479. None - The result of the decrement of DeviceExtension->OrbListDepth
  480. --*/
  481. {
  482. //
  483. // This ORB can now be freed along with its data descriptor,
  484. // page tables and context
  485. //
  486. if (!Context || (Context->Tag != SBP2_ASYNC_CONTEXT_TAG)) {
  487. DEBUGPRINT2((
  488. "Sbp2Port: FreeAsyncReqCtx: attempt to push freed ctx=x%p\n",
  489. Context
  490. ));
  491. ASSERT(FALSE);
  492. return 0;
  493. }
  494. ASSERT(Context->Srb == NULL);
  495. if (Context->DataMappingHandle) {
  496. Free1394DataMapping(DeviceExtension,Context);
  497. ASSERT(Context->DataMappingHandle==NULL);
  498. }
  499. //
  500. // Re-initiliaze this context so it can be reused
  501. // This context is still part on our FreeAsyncContextPool
  502. // All we have to do is initialize some flags, so next time
  503. // we try to retrieve it, we think its empty
  504. //
  505. Context->Flags |= ASYNC_CONTEXT_FLAG_COMPLETED;
  506. Context->Tag = 0;
  507. if (Context->OriginalSrb) {
  508. ExFreePool(Context->OriginalSrb);
  509. Context->OriginalSrb = NULL;
  510. }
  511. DEBUGPRINT3(("Sbp2Port: FreeAsyncReqCtx: push ctx=x%p on free list\n",Context));
  512. ExInterlockedPushEntrySList(&DeviceExtension->FreeContextListHead,
  513. &Context->LookasideList,
  514. &DeviceExtension->FreeContextLock);
  515. return InterlockedDecrement (&DeviceExtension->OrbListDepth);
  516. }
  517. NTSTATUS
  518. Sbp2SendRequest(
  519. PDEVICE_EXTENSION DeviceExtension,
  520. PIRBIRP RequestPacket,
  521. ULONG TransferMode
  522. )
  523. /*++
  524. Routine Description:
  525. Function used to send requests to the 1394 bus driver. It attaches
  526. a completion routine to each request it sends down, and it also wraps
  527. them in a small context, so we can track their completion
  528. Arguments:
  529. DeviceExtension - Sbp2 device extension
  530. Irp - Irp to send to the bus driver
  531. Irb - Bus driver packet, in the Irp
  532. TransferMode - Indicates if we want ot send this request synchronously
  533. or asynchronously
  534. FinalTransferMode - Indicates whether the request was sent synchronously
  535. or asynchronously
  536. Return Value:
  537. NTSTATUS
  538. --*/
  539. {
  540. ULONG originalTransferMode = TransferMode;
  541. NTSTATUS status;
  542. PDEVICE_OBJECT deviceObject = DeviceExtension->DeviceObject;
  543. PREQUEST_CONTEXT requestContext = NULL;
  544. PIO_STACK_LOCATION nextIrpStack;
  545. if (DeviceExtension->Type == SBP2_PDO) {
  546. //
  547. // if device is removed, dont send any requests down
  548. //
  549. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED) &&
  550. (RequestPacket->Irb->FunctionNumber != REQUEST_FREE_ADDRESS_RANGE)) {
  551. return STATUS_UNSUCCESSFUL;
  552. }
  553. //
  554. // get a context for this request, from our pool
  555. //
  556. requestContext = ExAllocateFromNPagedLookasideList(&DeviceExtension->BusRequestContextPool);
  557. } else {
  558. requestContext = ExAllocatePool (NonPagedPool,sizeof(REQUEST_CONTEXT));
  559. }
  560. if (!requestContext) {
  561. DEBUGPRINT2((
  562. "Sbp2Port: SendReq: ERROR, couldn't allocate bus req ctx\n"
  563. ));
  564. return STATUS_INSUFFICIENT_RESOURCES;
  565. }
  566. if (TransferMode == SYNC_1394_REQUEST) {
  567. if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
  568. //
  569. // Since we can't block at this level, we will have to do the
  570. // synch request asynchronously
  571. //
  572. TransferMode = ASYNC_SYNC_1394_REQUEST;
  573. requestContext->Complete = 0;
  574. } else {
  575. KeInitializeEvent(
  576. &requestContext->Event,
  577. NotificationEvent,
  578. FALSE
  579. );
  580. }
  581. }
  582. requestContext->DeviceExtension = DeviceExtension;
  583. requestContext->RequestType = TransferMode;
  584. if (TransferMode == SYNC_1394_REQUEST){
  585. requestContext->Packet = NULL;
  586. } else {
  587. requestContext->Packet = RequestPacket;
  588. }
  589. nextIrpStack = IoGetNextIrpStackLocation (RequestPacket->Irp);
  590. nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  591. nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  592. nextIrpStack->Parameters.Others.Argument1 = RequestPacket->Irb;
  593. IoSetCompletionRoutine(RequestPacket->Irp,
  594. Sbp2RequestCompletionRoutine,
  595. requestContext,
  596. TRUE,
  597. TRUE,
  598. TRUE
  599. );
  600. status = IoCallDriver(
  601. DeviceExtension->LowerDeviceObject,
  602. RequestPacket->Irp
  603. );
  604. if (status == STATUS_INVALID_GENERATION) {
  605. DEBUGPRINT1(("Sbp2Port: SendReq: Bus drv ret'd invalid generation\n"));
  606. RequestPacket->Irp->IoStatus.Status = STATUS_REQUEST_ABORTED;
  607. }
  608. if (originalTransferMode == SYNC_1394_REQUEST ) {
  609. if (TransferMode == SYNC_1394_REQUEST) {
  610. if (status == STATUS_PENDING) {
  611. //
  612. // < DISPATCH_LEVEL so wait on an event
  613. //
  614. KeWaitForSingleObject(
  615. &requestContext->Event,
  616. Executive,
  617. KernelMode,
  618. FALSE,
  619. NULL
  620. );
  621. }
  622. } else { // ASYNC_SYNC_1394_REQUEST
  623. //
  624. // >= DISPATCH_LEVEL so we can't wait, do the nasty...
  625. //
  626. volatile ULONG *pComplete = &requestContext->Complete;
  627. while (*pComplete == 0);
  628. status = RequestPacket->Irp->IoStatus.Status;
  629. }
  630. //
  631. // Free the context (the Irp.Irb will be returnd by the caller)
  632. //
  633. if (DeviceExtension->Type == SBP2_PDO) {
  634. ExFreeToNPagedLookasideList(&DeviceExtension->BusRequestContextPool, requestContext);
  635. } else {
  636. ExFreePool (requestContext);
  637. }
  638. return RequestPacket->Irp->IoStatus.Status;
  639. }
  640. return status;
  641. }
  642. NTSTATUS
  643. Sbp2RequestCompletionRoutine(
  644. IN PDEVICE_OBJECT DeviceObject,
  645. IN PIRP Irp,
  646. IN PREQUEST_CONTEXT Context
  647. )
  648. /*++
  649. Routine Description:
  650. Completion routine used for all requests to 1394 bus driver
  651. Arguments:
  652. DriverObject - Pointer to driver object created by system.
  653. Irp - Irp that just completed
  654. Event - Event we'll signal to say Irp is done
  655. Return Value:
  656. None.
  657. --*/
  658. {
  659. ASSERT(Context!=NULL);
  660. ASSERT(Context->DeviceExtension);
  661. if (Context->RequestType == SYNC_1394_REQUEST) {
  662. //
  663. // Synch request completion (either synch, or synch at DPC)
  664. //
  665. KeSetEvent (&Context->Event, IO_NO_INCREMENT, FALSE);
  666. } else if (Context->RequestType == ASYNC_1394_REQUEST) {
  667. //
  668. // Asynchronous request completion, so do any necessary
  669. // post-processing & return the context and the Irp/Irb
  670. // to the free lists.
  671. //
  672. if (Context->Packet) {
  673. switch (Context->Packet->Irb->FunctionNumber) {
  674. case REQUEST_ASYNC_READ:
  675. case REQUEST_ASYNC_WRITE:
  676. if (Context->Packet->Irb->u.AsyncWrite.nNumberOfBytesToWrite ==
  677. sizeof(OCTLET)) {
  678. IoFreeMdl (Context->Packet->Irb->u.AsyncRead.Mdl);
  679. Context->Packet->Irb->u.AsyncRead.Mdl = NULL;
  680. }
  681. break;
  682. }
  683. DeAllocateIrpAndIrb (Context->DeviceExtension, Context->Packet);
  684. }
  685. if (Context->DeviceExtension->Type == SBP2_PDO) {
  686. ExFreeToNPagedLookasideList(&Context->DeviceExtension->BusRequestContextPool, Context);
  687. } else {
  688. ExFreePool (Context);
  689. }
  690. } else { // ASYNC_SYNC_1394_REQUEST
  691. //
  692. // Just set the Complete flag to unblock Sbp2SendRequest
  693. //
  694. Context->Complete = 1;
  695. }
  696. return STATUS_MORE_PROCESSING_REQUIRED;
  697. }
  698. VOID
  699. Sbp2CreateRequestErrorLog(
  700. IN PDEVICE_OBJECT DeviceObject,
  701. IN PASYNC_REQUEST_CONTEXT Context,
  702. IN NTSTATUS Status
  703. )
  704. {
  705. PIO_ERROR_LOG_PACKET errorLogEntry;
  706. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  707. DeviceObject,
  708. sizeof(IO_ERROR_LOG_PACKET) + sizeof(ORB_NORMAL_CMD)
  709. );
  710. if (errorLogEntry) {
  711. switch (Status) {
  712. case STATUS_DEVICE_POWER_FAILURE:
  713. errorLogEntry->ErrorCode = IO_ERR_NOT_READY;
  714. break;
  715. case STATUS_INSUFFICIENT_RESOURCES:
  716. errorLogEntry->ErrorCode = IO_ERR_INSUFFICIENT_RESOURCES;
  717. break;
  718. case STATUS_TIMEOUT:
  719. errorLogEntry->ErrorCode = IO_ERR_TIMEOUT;
  720. break;
  721. case STATUS_DEVICE_PROTOCOL_ERROR:
  722. errorLogEntry->ErrorCode = IO_ERR_BAD_FIRMWARE;
  723. break;
  724. case STATUS_INVALID_PARAMETER:
  725. case STATUS_INVALID_DEVICE_REQUEST:
  726. errorLogEntry->ErrorCode = IO_ERR_INVALID_REQUEST;
  727. break;
  728. case STATUS_REQUEST_ABORTED:
  729. errorLogEntry->ErrorCode = IO_ERR_RESET;
  730. break;
  731. default:
  732. errorLogEntry->ErrorCode = IO_ERR_BAD_FIRMWARE;
  733. break;
  734. }
  735. errorLogEntry->SequenceNumber = 0;
  736. errorLogEntry->MajorFunctionCode = IRP_MJ_SCSI;
  737. errorLogEntry->RetryCount = 0;
  738. errorLogEntry->UniqueErrorValue = 0;
  739. errorLogEntry->FinalStatus = Status;
  740. if (Context) {
  741. errorLogEntry->DumpDataSize = sizeof(ORB_NORMAL_CMD);
  742. RtlCopyMemory(&(errorLogEntry->DumpData[0]),Context->CmdOrb,sizeof(ORB_NORMAL_CMD));
  743. } else {
  744. errorLogEntry->DumpDataSize = 0;
  745. }
  746. IoWriteErrorLogEntry(errorLogEntry);
  747. DEBUGPRINT2((
  748. "Sbp2Port: ErrorLog: dev=x%p, status=x%x, ctx=x%p\n",
  749. DeviceObject,
  750. Status,
  751. Context
  752. ));
  753. } else {
  754. DEBUGPRINT2 (("Sbp2Port: ErrorLog: failed to allocate log entry\n"));
  755. }
  756. }
  757. NTSTATUS
  758. CheckStatusResponseValue(
  759. IN PSTATUS_FIFO_BLOCK StatusBlock
  760. )
  761. /*++
  762. Routine Description:
  763. It checks the status block result bits and maps the errors to
  764. NT status errors
  765. Arguments:
  766. DeviceExtension - Sbp2 device extension
  767. ManagementStatus - If true then we check the management orb status
  768. Return Value:
  769. NTSTATUS
  770. ++*/
  771. {
  772. NTSTATUS status;
  773. UCHAR resp;
  774. USHORT statusFlags = StatusBlock->AddressAndStatus.u.HighQuad.u.HighPart;
  775. if (statusFlags & STATUS_BLOCK_UNSOLICITED_BIT_MASK) {
  776. //
  777. // The unsolicited bit is set, which means this status is
  778. // not related to anything...
  779. //
  780. return STATUS_NOT_FOUND;
  781. }
  782. resp = ((statusFlags & STATUS_BLOCK_RESP_MASK) >> 12);
  783. switch (resp) {
  784. case 0:
  785. //
  786. // Request complete, check sbp_status field for more info
  787. //
  788. switch ((statusFlags & STATUS_BLOCK_SBP_STATUS_MASK)) {
  789. case 0x00: // no additional status to report
  790. status = STATUS_SUCCESS;
  791. break;
  792. case 0x01: // request type not supported
  793. case 0x02: // speed not supported
  794. case 0x03: // page size not supported
  795. status = STATUS_NOT_SUPPORTED;
  796. break;
  797. case 0x04: // access denied
  798. case 0x05: // LUN not supported
  799. status = STATUS_ACCESS_DENIED;
  800. break;
  801. case 0x08: // resource unavailable
  802. status = STATUS_INSUFFICIENT_RESOURCES;
  803. break;
  804. case 0x09: // function rejected
  805. status = STATUS_ILLEGAL_FUNCTION;
  806. break;
  807. case 0x0a: // login id not recognized
  808. status = STATUS_TRANSACTION_INVALID_ID;
  809. break;
  810. default:
  811. status = STATUS_UNSUCCESSFUL;
  812. break;
  813. }
  814. break;
  815. case 1:
  816. //
  817. // Transport failure, check the redefined sbp-status field
  818. // for serial-bus errors
  819. //
  820. resp = statusFlags & 0x0F;
  821. switch (resp) {
  822. case 0x02: // time out
  823. case 0x0C: // conflict error
  824. case 0x0D: // data error
  825. status = STATUS_DEVICE_PROTOCOL_ERROR;
  826. break;
  827. case 0x04: // busy retry limit exceeded
  828. case 0x05: // busy retry limit exceeded
  829. case 0x06: // busy retry limit exceeded
  830. status = STATUS_DEVICE_BUSY;
  831. break;
  832. case 0x0E: // type error
  833. status = STATUS_INVALID_PARAMETER;
  834. break;
  835. case 0x0F: // address error
  836. status = STATUS_INVALID_ADDRESS;
  837. break;
  838. default:
  839. status = STATUS_UNSUCCESSFUL;
  840. break;
  841. }
  842. break;
  843. case 2: // illegal request
  844. status = STATUS_ILLEGAL_FUNCTION;
  845. break;
  846. default: // case 3:, vendor dependent
  847. status = STATUS_UNSUCCESSFUL; // ISSUE: dankn, 02-Aug-2001
  848. break;
  849. }
  850. return status;
  851. }
  852. VOID
  853. Sbp2StartNextPacketByKey(
  854. IN PDEVICE_OBJECT DeviceObject,
  855. IN ULONG Key
  856. )
  857. /*++
  858. Routine Description:
  859. This routine was lifted from the Io sources
  860. (IopStartNextPacketByKey), and duplicated/modifed here for
  861. two reasons: 1) we got tired of hitting the queue-not-busy assert
  862. in KeRemoveXxx, and 2) we needed a way to prevent stack-blowing
  863. recursion, for example, arising from a bunch of requests sent to
  864. a stopped device (all failed in StartIo, which calls this func).
  865. These routines were originally designed with the idea that there
  866. would only be one outstanding request at a time, but this driver
  867. can have multiple outstanding requests, and it frequently ends up
  868. making redundant calls to XxStartNextPacket(ByKey), which result
  869. in the aforementioned assert.
  870. Rolling our own version of this also allows us to get rid the
  871. the cancel overhead, since we do not (currently) support cancels.
  872. Arguments:
  873. DeviceObject - Pointer to device object itself
  874. Key - Specifics the Key used to remove the entry from the queue
  875. Return Value:
  876. None
  877. --*/
  878. {
  879. PIRP irp;
  880. PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)
  881. DeviceObject->DeviceExtension;
  882. PKDEVICE_QUEUE_ENTRY packet;
  883. //
  884. // Increment the StartNextPacketCount, and if result is != 1
  885. // then just return because we don't want to worry about
  886. // recursion & blowing the stack. The instance of this
  887. // function that caused the SNPCount 0 to 1 transition
  888. // will eventually make another pass through the loop below
  889. // on this instance's behalf.
  890. //
  891. if (InterlockedIncrement (&deviceExtension->StartNextPacketCount) != 1) {
  892. return;
  893. }
  894. do {
  895. //
  896. // Attempt to remove the indicated packet according to the key
  897. // from the device queue. If one is found, then process it.
  898. //
  899. packet = Sbp2RemoveByKeyDeviceQueueIfBusy(
  900. &DeviceObject->DeviceQueue,
  901. Key
  902. );
  903. if (packet) {
  904. irp = CONTAINING_RECORD (packet,IRP,Tail.Overlay.DeviceQueueEntry);
  905. Sbp2StartIo (DeviceObject, irp);
  906. }
  907. } while (InterlockedDecrement (&deviceExtension->StartNextPacketCount));
  908. }
  909. VOID
  910. Sbp2StartPacket(
  911. IN PDEVICE_OBJECT DeviceObject,
  912. IN PIRP Irp,
  913. IN PULONG Key OPTIONAL
  914. )
  915. /*++
  916. Routine Description:
  917. (See routine description for Sbp2StartNextPacketByKey)
  918. Arguments:
  919. DeviceObject - Pointer to device object itself
  920. Irp - I/O Request Packet which should be started on the device
  921. Return Value:
  922. None
  923. --*/
  924. {
  925. KIRQL oldIrql;
  926. BOOLEAN inserted;
  927. PLIST_ENTRY nextEntry;
  928. PKDEVICE_QUEUE queue = &DeviceObject->DeviceQueue;
  929. PKDEVICE_QUEUE_ENTRY queueEntry = &Irp->Tail.Overlay.DeviceQueueEntry,
  930. queueEntry2;
  931. //
  932. // Raise the IRQL of the processor to dispatch level for synchronization
  933. //
  934. KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
  935. KeAcquireSpinLockAtDpcLevel (&queue->Lock);
  936. if (Key) {
  937. //
  938. // Insert the specified device queue entry in the device queue at the
  939. // position specified by the sort key if the device queue is busy.
  940. // Otherwise set the device queue busy an don't insert the device
  941. // queue entry.
  942. //
  943. queueEntry->SortKey = *Key;
  944. if (queue->Busy == TRUE) {
  945. inserted = TRUE;
  946. nextEntry = queue->DeviceListHead.Flink;
  947. while (nextEntry != &queue->DeviceListHead) {
  948. queueEntry2 = CONTAINING_RECORD(
  949. nextEntry,
  950. KDEVICE_QUEUE_ENTRY,
  951. DeviceListEntry
  952. );
  953. if (*Key < queueEntry2->SortKey) {
  954. break;
  955. }
  956. nextEntry = nextEntry->Flink;
  957. }
  958. nextEntry = nextEntry->Blink;
  959. InsertHeadList (nextEntry, &queueEntry->DeviceListEntry);
  960. } else {
  961. queue->Busy = TRUE;
  962. inserted = FALSE;
  963. }
  964. } else {
  965. //
  966. // Insert the specified device queue entry at the end of the device
  967. // queue if the device queue is busy. Otherwise set the device queue
  968. // busy and don't insert the device queue entry.
  969. //
  970. if (queue->Busy == TRUE) {
  971. inserted = TRUE;
  972. InsertTailList(
  973. &queue->DeviceListHead,
  974. &queueEntry->DeviceListEntry
  975. );
  976. } else {
  977. queue->Busy = TRUE;
  978. inserted = FALSE;
  979. }
  980. }
  981. queueEntry->Inserted = inserted;
  982. KeReleaseSpinLockFromDpcLevel (&queue->Lock);
  983. //
  984. // If the packet was not inserted into the queue, then this request is
  985. // now the current packet for this device. Indicate so by storing its
  986. // address in the current IRP field, and begin processing the request.
  987. //
  988. if (!inserted) {
  989. //
  990. // Invoke the driver's start I/O routine to get the request going
  991. // on the device
  992. //
  993. Sbp2StartIo (DeviceObject, Irp);
  994. }
  995. //
  996. // Restore the IRQL back to its value upon entry to this function before
  997. // returning to the caller
  998. //
  999. KeLowerIrql (oldIrql);
  1000. }
  1001. PKDEVICE_QUEUE_ENTRY
  1002. Sbp2RemoveByKeyDeviceQueueIfBusy(
  1003. IN PKDEVICE_QUEUE DeviceQueue,
  1004. IN ULONG SortKey
  1005. )
  1006. /*++
  1007. Routine Description:
  1008. This routine was lifted directly from Ke sources
  1009. (KeRemoveByKeyDeviceQueueIfBusy) to allow this driver to maintain
  1010. WDM compatibility, since the Ke API does not exist on Win9x or Win2k.
  1011. N.B. This function can only be called from DISPATCH_LEVEL.
  1012. Arguments:
  1013. DeviceQueue - Supplies a pointer to a control object of type device queue.
  1014. SortKey - Supplies the sort key by which the position to remove the device
  1015. queue entry is to be determined.
  1016. Return Value:
  1017. A NULL pointer is returned if the device queue is empty. Otherwise a
  1018. pointer to a device queue entry is returned.
  1019. --*/
  1020. {
  1021. PLIST_ENTRY nextEntry;
  1022. PKDEVICE_QUEUE_ENTRY queueEntry;
  1023. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  1024. //
  1025. // Lock specified device queue.
  1026. //
  1027. KeAcquireSpinLockAtDpcLevel (&DeviceQueue->Lock);
  1028. //
  1029. // If the device queue is busy, then attempt to remove an entry from
  1030. // the queue using the sort key. Otherwise, set the device queue not
  1031. // busy.
  1032. //
  1033. if (DeviceQueue->Busy != FALSE) {
  1034. if (IsListEmpty (&DeviceQueue->DeviceListHead) != FALSE) {
  1035. DeviceQueue->Busy = FALSE;
  1036. queueEntry = NULL;
  1037. } else {
  1038. nextEntry = DeviceQueue->DeviceListHead.Flink;
  1039. while (nextEntry != &DeviceQueue->DeviceListHead) {
  1040. queueEntry = CONTAINING_RECORD(
  1041. nextEntry,
  1042. KDEVICE_QUEUE_ENTRY,
  1043. DeviceListEntry
  1044. );
  1045. if (SortKey <= queueEntry->SortKey) {
  1046. break;
  1047. }
  1048. nextEntry = nextEntry->Flink;
  1049. }
  1050. if (nextEntry != &DeviceQueue->DeviceListHead) {
  1051. RemoveEntryList (&queueEntry->DeviceListEntry);
  1052. } else {
  1053. nextEntry = RemoveHeadList (&DeviceQueue->DeviceListHead);
  1054. queueEntry = CONTAINING_RECORD(
  1055. nextEntry,
  1056. KDEVICE_QUEUE_ENTRY,
  1057. DeviceListEntry
  1058. );
  1059. }
  1060. queueEntry->Inserted = FALSE;
  1061. }
  1062. } else {
  1063. queueEntry = NULL;
  1064. }
  1065. //
  1066. // Unlock specified device queue and return address of device queue
  1067. // entry.
  1068. //
  1069. KeReleaseSpinLockFromDpcLevel (&DeviceQueue->Lock);
  1070. return queueEntry;
  1071. }
  1072. BOOLEAN
  1073. Sbp2InsertByKeyDeviceQueue(
  1074. PKDEVICE_QUEUE DeviceQueue,
  1075. PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
  1076. ULONG SortKey
  1077. )
  1078. /*++
  1079. Routine Description:
  1080. (Again, stolen from Ke src to maintain consistent use of spinlocks.)
  1081. This function inserts a device queue entry into the specified device
  1082. queue according to a sort key. If the device is not busy, then it is
  1083. set busy and the entry is not placed in the device queue. Otherwise
  1084. the specified entry is placed in the device queue at a position such
  1085. that the specified sort key is greater than or equal to its predecessor
  1086. and less than its successor.
  1087. N.B. This function can only be called from DISPATCH_LEVEL.
  1088. Arguments:
  1089. DeviceQueue - Supplies a pointer to a control object of type device queue.
  1090. DeviceQueueEntry - Supplies a pointer to a device queue entry.
  1091. SortKey - Supplies the sort key by which the position to insert the device
  1092. queue entry is to be determined.
  1093. Return Value:
  1094. If the device is not busy, then a value of FALSE is returned. Otherwise a
  1095. value of TRUE is returned.
  1096. --*/
  1097. {
  1098. BOOLEAN inserted;
  1099. PLIST_ENTRY nextEntry;
  1100. PKDEVICE_QUEUE queue = DeviceQueue;
  1101. PKDEVICE_QUEUE_ENTRY queueEntry = DeviceQueueEntry,
  1102. queueEntry2;
  1103. KeAcquireSpinLockAtDpcLevel (&queue->Lock);
  1104. //
  1105. // Insert the specified device queue entry in the device queue at the
  1106. // position specified by the sort key if the device queue is busy.
  1107. // Otherwise set the device queue busy an don't insert the device
  1108. // queue entry.
  1109. //
  1110. queueEntry->SortKey = SortKey;
  1111. if (queue->Busy == TRUE) {
  1112. inserted = TRUE;
  1113. nextEntry = queue->DeviceListHead.Flink;
  1114. while (nextEntry != &queue->DeviceListHead) {
  1115. queueEntry2 = CONTAINING_RECORD(
  1116. nextEntry,
  1117. KDEVICE_QUEUE_ENTRY,
  1118. DeviceListEntry
  1119. );
  1120. if (SortKey < queueEntry2->SortKey) {
  1121. break;
  1122. }
  1123. nextEntry = nextEntry->Flink;
  1124. }
  1125. nextEntry = nextEntry->Blink;
  1126. InsertHeadList (nextEntry, &queueEntry->DeviceListEntry);
  1127. } else {
  1128. queue->Busy = TRUE;
  1129. inserted = FALSE;
  1130. }
  1131. KeReleaseSpinLockFromDpcLevel (&queue->Lock);
  1132. return inserted;
  1133. }
  1134. #if PASSWORD_SUPPORT
  1135. NTSTATUS
  1136. Sbp2GetExclusiveValue(
  1137. IN PDEVICE_OBJECT PhysicalDeviceObject,
  1138. OUT PULONG Exclusive
  1139. )
  1140. {
  1141. NTSTATUS ntStatus = STATUS_SUCCESS;
  1142. HANDLE RootHandle = NULL;
  1143. UNICODE_STRING uniTempName;
  1144. // set default value...
  1145. *Exclusive = EXCLUSIVE_FLAG_CLEAR;
  1146. uniTempName.Buffer = NULL;
  1147. ntStatus = IoOpenDeviceRegistryKey( PhysicalDeviceObject,
  1148. PLUGPLAY_REGKEY_DEVICE,
  1149. KEY_ALL_ACCESS,
  1150. &RootHandle
  1151. );
  1152. if (!NT_SUCCESS(ntStatus)) {
  1153. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1154. goto Exit_Sbp2GetExclusiveValue;
  1155. }
  1156. uniTempName.Length = 0;
  1157. uniTempName.MaximumLength = 128;
  1158. uniTempName.Buffer = ExAllocatePool(
  1159. NonPagedPool,
  1160. uniTempName.MaximumLength
  1161. );
  1162. if (!uniTempName.Buffer) {
  1163. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1164. goto Exit_Sbp2GetExclusiveValue;
  1165. }
  1166. {
  1167. PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
  1168. ULONG KeyLength;
  1169. ULONG ResultLength;
  1170. KeyLength = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + sizeof (ULONG);
  1171. KeyInfo = ExAllocatePool (NonPagedPool, KeyLength);
  1172. if (KeyInfo == NULL) {
  1173. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1174. goto Exit_Sbp2GetExclusiveValue;
  1175. }
  1176. RtlZeroMemory(uniTempName.Buffer, uniTempName.MaximumLength);
  1177. uniTempName.Length = 0;
  1178. RtlAppendUnicodeToString(&uniTempName, L"Exclusive");
  1179. ntStatus = ZwQueryValueKey( RootHandle,
  1180. &uniTempName,
  1181. KeyValuePartialInformation,
  1182. KeyInfo,
  1183. KeyLength,
  1184. &ResultLength
  1185. );
  1186. if (NT_SUCCESS(ntStatus)) {
  1187. *Exclusive = *((PULONG) &KeyInfo->Data);
  1188. DEBUGPRINT1 (("Sbp2Port: GetExclVal: excl=x%x\n", *Exclusive));
  1189. } else {
  1190. DEBUGPRINT1((
  1191. "Sbp2Port: GetExclVal: QueryValueKey err=x%x\n",
  1192. ntStatus
  1193. ));
  1194. }
  1195. ExFreePool (KeyInfo);
  1196. }
  1197. Exit_Sbp2GetExclusiveValue:
  1198. if (RootHandle) {
  1199. ZwClose (RootHandle);
  1200. }
  1201. if (uniTempName.Buffer) {
  1202. ExFreePool (uniTempName.Buffer);
  1203. }
  1204. return ntStatus;
  1205. }
  1206. NTSTATUS
  1207. Sbp2SetExclusiveValue(
  1208. IN PDEVICE_OBJECT PhysicalDeviceObject,
  1209. IN PULONG Exclusive
  1210. )
  1211. {
  1212. NTSTATUS ntStatus = STATUS_SUCCESS;
  1213. HANDLE RootHandle = NULL;
  1214. UNICODE_STRING uniTempName;
  1215. uniTempName.Buffer = NULL;
  1216. ntStatus = IoOpenDeviceRegistryKey( PhysicalDeviceObject,
  1217. PLUGPLAY_REGKEY_DEVICE,
  1218. KEY_ALL_ACCESS,
  1219. &RootHandle
  1220. );
  1221. if (!NT_SUCCESS(ntStatus)) {
  1222. goto Exit_Sbp2SetExclusiveValue;
  1223. }
  1224. uniTempName.Length = 0;
  1225. uniTempName.MaximumLength = 128;
  1226. uniTempName.Buffer = ExAllocatePool(
  1227. NonPagedPool,
  1228. uniTempName.MaximumLength
  1229. );
  1230. if (!uniTempName.Buffer) {
  1231. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1232. goto Exit_Sbp2SetExclusiveValue;
  1233. }
  1234. RtlZeroMemory (uniTempName.Buffer, uniTempName.MaximumLength);
  1235. uniTempName.Length = 0;
  1236. RtlAppendUnicodeToString(&uniTempName, L"Exclusive");
  1237. ntStatus = ZwSetValueKey( RootHandle,
  1238. &uniTempName,
  1239. 0,
  1240. REG_DWORD,
  1241. Exclusive,
  1242. sizeof(ULONG)
  1243. );
  1244. if (!NT_SUCCESS(ntStatus)) {
  1245. DEBUGPRINT1(("Sbp2Port: SetExclVal: SetValueKey err=x%x\n", ntStatus));
  1246. *Exclusive = 0;
  1247. }
  1248. else {
  1249. DEBUGPRINT1(("Sbp2Port: SetExclVal: excl=x%x\n", *Exclusive));
  1250. }
  1251. Exit_Sbp2SetExclusiveValue:
  1252. if (RootHandle) {
  1253. ZwClose(RootHandle);
  1254. }
  1255. if (uniTempName.Buffer) {
  1256. ExFreePool(uniTempName.Buffer);
  1257. }
  1258. return ntStatus;
  1259. }
  1260. #endif