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.

5587 lines
161 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 2001
  3. Module Name:
  4. sbp2port.c
  5. Abstract:
  6. Main module 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. #include "stdarg.h"
  15. #include "stdio.h"
  16. #include "stdlib.h"
  17. #include "string.h"
  18. #if DBG
  19. ULONG Sbp2DebugLevel = 0;
  20. ULONG NewSbp2DebugLevel = DEFAULT_DEBUG_LEVEL;
  21. ULONG Sbp2TrapLevel = FALSE;
  22. #endif
  23. BOOLEAN SystemIsNT;
  24. NTSTATUS
  25. DriverEntry(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PUNICODE_STRING RegistryPath
  28. );
  29. NTSTATUS
  30. Sbp2AddDevice(
  31. PDRIVER_OBJECT DriverObject,
  32. PDEVICE_OBJECT Pdo
  33. );
  34. NTSTATUS
  35. Sbp2StartDevice(
  36. IN PDEVICE_OBJECT DeviceObject
  37. );
  38. NTSTATUS
  39. Sbp2CreateDeviceRelations(
  40. IN PFDO_DEVICE_EXTENSION FdoExtension,
  41. IN PDEVICE_RELATIONS DeviceRelations
  42. );
  43. NTSTATUS
  44. Sbp2CreateDevObject(
  45. IN PDRIVER_OBJECT DriverObject,
  46. IN PDEVICE_OBJECT Pdo
  47. );
  48. NTSTATUS
  49. Sbp2DeviceControl(
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN PIRP Irp
  52. );
  53. NTSTATUS
  54. Sbp2CreateClose(
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN PIRP Irp
  57. );
  58. NTSTATUS
  59. Sbp2PnpDeviceControl(
  60. PDEVICE_OBJECT DeviceObject,
  61. PIRP Irp
  62. );
  63. NTSTATUS
  64. Sbp2FDOPnpDeviceControl(
  65. PDEVICE_OBJECT DeviceObject,
  66. PIRP Irp
  67. );
  68. NTSTATUS
  69. Sbp2CreatePdo(
  70. IN PFDO_DEVICE_EXTENSION FdoExtension,
  71. IN PDEVICE_INFORMATION DeviceInfo,
  72. ULONG instanceNum
  73. );
  74. NTSTATUS
  75. Sbp2PowerControl(
  76. PDEVICE_OBJECT DeviceObject,
  77. PIRP Irp
  78. );
  79. NTSTATUS
  80. Sbp2SystemControl(
  81. PDEVICE_OBJECT DeviceObject,
  82. PIRP Irp
  83. );
  84. NTSTATUS
  85. Sbp2FdoRequestCompletionRoutine(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN PIRP Irp,
  88. IN PKEVENT Event
  89. );
  90. VOID
  91. Sbp2Unload(
  92. IN PDRIVER_OBJECT DriverObject
  93. );
  94. NTSTATUS
  95. Sbp2_BuildDeviceId(
  96. IN PDEVICE_INFORMATION DeviceInfo,
  97. IN OUT PUNICODE_STRING uniDeviceId
  98. );
  99. NTSTATUS
  100. Sbp2_BuildHardwareIds(
  101. IN PDEVICE_INFORMATION DeviceInfo,
  102. IN OUT PUNICODE_STRING uniHardwareIds
  103. );
  104. NTSTATUS
  105. Sbp2_BuildCompatIds(
  106. IN PDEVICE_INFORMATION DeviceInfo,
  107. IN OUT PUNICODE_STRING uniCompatIds
  108. );
  109. NTSTATUS
  110. Sbp2_BuildInstanceId(
  111. IN PDEVICE_INFORMATION DeviceInfo,
  112. IN OUT PUNICODE_STRING uniInstanceId
  113. );
  114. NTSTATUS
  115. Sbp2_BuildDeviceText(
  116. IN DEVICE_TEXT_TYPE TextType,
  117. IN PDEVICE_INFORMATION DeviceInfo,
  118. IN OUT PUNICODE_STRING uniDeviceText
  119. );
  120. NTSTATUS
  121. Sbp2ForwardIrpSynchronous(
  122. IN PDEVICE_OBJECT DeviceObject,
  123. IN PIRP Irp
  124. );
  125. NTSTATUS
  126. Sbp2PortForwardIrpSynchronousCompletionRoutine(
  127. IN PDEVICE_OBJECT DeviceObject,
  128. IN PIRP Irp,
  129. IN PVOID Context
  130. );
  131. #ifdef ALLOC_PRAGMA
  132. #pragma alloc_text(PAGE, DriverEntry)
  133. #pragma alloc_text(PAGE, Sbp2AddDevice)
  134. #pragma alloc_text(PAGE, Sbp2StartDevice)
  135. #pragma alloc_text(PAGE, Sbp2CreateDeviceRelations)
  136. #pragma alloc_text(PAGE, Sbp2CreatePdo)
  137. #pragma alloc_text(PAGE, Sbp2CreateDevObject)
  138. #pragma alloc_text(PAGE, Sbp2DeviceControl)
  139. #pragma alloc_text(PAGE, Sbp2SystemControl)
  140. #pragma alloc_text(PAGE, Sbp2CreateClose)
  141. #pragma alloc_text(PAGE, Sbp2ForwardIrpSynchronous)
  142. #endif
  143. NTSTATUS
  144. DriverEntry(
  145. IN PDRIVER_OBJECT DriverObject,
  146. IN PUNICODE_STRING RegistryPath
  147. )
  148. /*++
  149. Routine Description:
  150. This routine is called at system initialization time so we can fill in the basic dispatch points
  151. Arguments:
  152. DriverObject - Supplies the driver object.
  153. RegistryPath - Supplies the registry path for this driver.
  154. Return Value:
  155. STATUS_SUCCESS
  156. --*/
  157. {
  158. //
  159. // Initialize the Driver Object with driver's entry points
  160. //
  161. DEBUGPRINT2(("Sbp2Port: DriverEntry: %s %s\n", __DATE__, __TIME__));
  162. DriverObject->MajorFunction[IRP_MJ_CREATE] = Sbp2CreateClose;
  163. DriverObject->MajorFunction[IRP_MJ_CLOSE] = Sbp2CreateClose;
  164. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Sbp2DeviceControl;
  165. DriverObject->MajorFunction[IRP_MJ_SCSI] = Sbp2ScsiRequests;
  166. DriverObject->DriverExtension->AddDevice = Sbp2AddDevice;
  167. DriverObject->MajorFunction[IRP_MJ_PNP] = Sbp2PnpDeviceControl;
  168. DriverObject->MajorFunction[IRP_MJ_PNP_POWER] = Sbp2PnpDeviceControl;
  169. DriverObject->MajorFunction[IRP_MJ_POWER] = Sbp2PowerControl;
  170. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Sbp2SystemControl;
  171. DriverObject->DriverStartIo = Sbp2StartIo;
  172. DriverObject->DriverUnload = Sbp2Unload;
  173. SystemIsNT = IoIsWdmVersionAvailable ((UCHAR)0x01, (UCHAR)0x10);
  174. return STATUS_SUCCESS;
  175. }
  176. NTSTATUS
  177. Sbp2AddDevice(
  178. PDRIVER_OBJECT DriverObject,
  179. PDEVICE_OBJECT Pdo
  180. )
  181. /*++
  182. Routine Description:
  183. This is our PNP AddDevice called with the PDO ejected from the bus driver
  184. Arguments:
  185. Argument1 - Driver Object.
  186. Argument2 - PDO.
  187. Return Value:
  188. A valid return code for a DriverEntry routine.
  189. --*/
  190. {
  191. return (Sbp2CreateDevObject (DriverObject,Pdo));
  192. }
  193. NTSTATUS
  194. Sbp2CreateDevObject(
  195. IN PDRIVER_OBJECT DriverObject,
  196. IN PDEVICE_OBJECT Pdo
  197. )
  198. /*++
  199. Routine Description:
  200. This routine creates an object for the physical device specified and
  201. sets up the deviceExtension.
  202. Arguments:
  203. DriverObject - Pointer to driver object created by system.
  204. PhysicalDeviceObject = PDO we should attach to.
  205. Return Value:
  206. NTSTATUS
  207. --*/
  208. {
  209. PFDO_DEVICE_EXTENSION deviceExtension;
  210. NTSTATUS status;
  211. PDEVICE_OBJECT deviceObject = NULL;
  212. UNICODE_STRING uniDeviceName;
  213. WCHAR buffer[64];
  214. UNICODE_STRING unicodeDirectoryName;
  215. HANDLE handle;
  216. OBJECT_ATTRIBUTES objectAttributes;
  217. ULONG NextId = 0;
  218. //
  219. // This is the sbp2 filter device object and name
  220. //
  221. do {
  222. swprintf (buffer, L"\\Device\\Sbp2Port%x", NextId);
  223. RtlInitUnicodeString (&uniDeviceName, buffer);
  224. status = IoCreateDevice(DriverObject,
  225. sizeof(FDO_DEVICE_EXTENSION),
  226. &uniDeviceName,
  227. FILE_DEVICE_BUS_EXTENDER,
  228. FILE_DEVICE_SECURE_OPEN,
  229. FALSE,
  230. &deviceObject);
  231. NextId++;
  232. } while (status == STATUS_OBJECT_NAME_COLLISION);
  233. if (!NT_SUCCESS(status)) {
  234. return status;
  235. }
  236. deviceExtension = deviceObject->DeviceExtension;
  237. RtlZeroMemory(deviceExtension,sizeof(FDO_DEVICE_EXTENSION));
  238. if (Pdo != NULL) {
  239. if ((deviceExtension->LowerDeviceObject =
  240. IoAttachDeviceToDeviceStack(deviceObject,Pdo))==NULL){
  241. IoDeleteDevice(deviceObject);
  242. return status;
  243. }
  244. }
  245. deviceExtension->Type = SBP2_FDO;
  246. deviceExtension->DeviceFlags = 0;
  247. deviceExtension->DeviceObject = deviceObject;
  248. deviceExtension->Pdo = Pdo;
  249. KeInitializeSpinLock(&deviceExtension->DeviceListLock);
  250. KeInitializeMutex (&deviceExtension->EnableBusResetNotificationMutex, 0);
  251. //
  252. // create a directory object for Sbp2 children devices
  253. //
  254. swprintf(buffer, L"\\Device\\Sbp2");
  255. RtlInitUnicodeString(&unicodeDirectoryName, buffer);
  256. InitializeObjectAttributes(&objectAttributes,
  257. &unicodeDirectoryName,
  258. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_KERNEL_HANDLE,
  259. NULL,
  260. NULL);
  261. status = ZwCreateDirectoryObject(&handle,
  262. DIRECTORY_ALL_ACCESS,
  263. &objectAttributes);
  264. if (NT_SUCCESS(status)) {
  265. deviceExtension->Sbp2ObjectDirectory = handle;
  266. } else {
  267. //
  268. // the directory is already created by another instance of this driver..
  269. //
  270. status = STATUS_SUCCESS;
  271. }
  272. ExInitializeFastMutex(&deviceExtension->ResetMutex);
  273. IoInitializeRemoveLock( &deviceExtension->RemoveLock,
  274. '2pbS',
  275. REMLOCK_TIMEOUT,
  276. REMLOCK_HIGH_WATERMARK
  277. );
  278. #if DBG
  279. deviceExtension->ulWorkItemCount = 0;
  280. deviceExtension->ulBusResetMutexCount = 0;
  281. #endif
  282. deviceObject->Flags |= DO_DIRECT_IO;
  283. deviceObject->Flags &=~DO_DEVICE_INITIALIZING;
  284. return status;
  285. }
  286. NTSTATUS
  287. Sbp2CreatePdo(
  288. IN PFDO_DEVICE_EXTENSION FdoExtension,
  289. IN PDEVICE_INFORMATION DeviceInfo,
  290. ULONG InstanceNumber
  291. )
  292. {
  293. PDEVICE_EXTENSION pdoExtension;
  294. DEVICE_TYPE devType;
  295. WCHAR *buffer;
  296. UNICODE_STRING uniDeviceName;
  297. NTSTATUS status;
  298. ULONG byteSwappedData;
  299. PAGED_CODE();
  300. switch (DeviceInfo->CmdSetId.QuadPart) {
  301. case 0x10483:
  302. case SCSI_COMMAND_SET_ID:
  303. switch ((DeviceInfo->Lun.u.HighPart & 0x001F)) {
  304. case PRINTER_DEVICE:
  305. devType = FILE_DEVICE_PRINTER;
  306. break;
  307. case SCANNER_DEVICE:
  308. devType = FILE_DEVICE_SCANNER;
  309. break;
  310. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  311. case RBC_DEVICE:
  312. case DIRECT_ACCESS_DEVICE:
  313. default:
  314. devType = FILE_DEVICE_MASS_STORAGE;
  315. break;
  316. }
  317. break;
  318. default:
  319. devType = FILE_DEVICE_UNKNOWN;
  320. break;
  321. }
  322. buffer = ExAllocatePool(PagedPool,
  323. 5 * SBP2_MAX_TEXT_LEAF_LENGTH * sizeof (WCHAR)
  324. );
  325. if (buffer == NULL) {
  326. return STATUS_INSUFFICIENT_RESOURCES;
  327. }
  328. if (DeviceInfo->uniVendorId.Buffer && DeviceInfo->uniModelId.Buffer) {
  329. swprintf( buffer,
  330. L"\\Device\\Sbp2\\%ws&%ws&%x&%08x_%08x_Instance%02d",
  331. DeviceInfo->uniVendorId.Buffer,
  332. DeviceInfo->uniModelId.Buffer,
  333. DeviceInfo->Lun.u.LowPart,
  334. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[0]),
  335. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[1]),
  336. InstanceNumber
  337. );
  338. }
  339. else {
  340. swprintf( buffer,
  341. L"\\Device\\Sbp2\\UNKNOWN_VENDOR&UNKNOWN_MODEL&%x&%08x_%08x_Instance%02d",
  342. DeviceInfo->Lun.u.LowPart,
  343. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[0]),
  344. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[1]),
  345. InstanceNumber
  346. );
  347. }
  348. RtlInitUnicodeString (&uniDeviceName, buffer);
  349. //
  350. // Need to create a device object for this device
  351. //
  352. status = IoCreateDevice(
  353. FdoExtension->DeviceObject->DriverObject,
  354. sizeof(DEVICE_EXTENSION),
  355. &uniDeviceName,
  356. devType,
  357. 0,
  358. FALSE,
  359. &DeviceInfo->DeviceObject
  360. );
  361. if (!NT_SUCCESS(status)) {
  362. ExFreePool (buffer);
  363. return status;
  364. }
  365. // only set alignment if it's less than we require
  366. if (DeviceInfo->DeviceObject->AlignmentRequirement < SBP2_ALIGNMENT_MASK)
  367. DeviceInfo->DeviceObject->AlignmentRequirement = SBP2_ALIGNMENT_MASK;
  368. pdoExtension = (PDEVICE_EXTENSION)DeviceInfo->DeviceObject->DeviceExtension;
  369. RtlZeroMemory(pdoExtension,sizeof(DEVICE_EXTENSION));
  370. pdoExtension->LowerDeviceObject = FdoExtension->LowerDeviceObject;
  371. pdoExtension->DeviceObject = DeviceInfo->DeviceObject;
  372. pdoExtension->Type = SBP2_PDO;
  373. pdoExtension->DeviceInfo = DeviceInfo;
  374. pdoExtension->DeviceInfo->MaxClassTransferSize = FdoExtension->MaxClassTransferSize;
  375. pdoExtension->BusFdo = FdoExtension->DeviceObject;
  376. #if DBG
  377. pdoExtension->ulPendingEvents = 0;
  378. pdoExtension->ulInternalEventCount = 0;
  379. #endif
  380. KeInitializeSpinLock (&pdoExtension->ExtensionDataSpinLock);
  381. IoInitializeRemoveLock(
  382. &pdoExtension->RemoveLock,
  383. '2pbS',
  384. REMLOCK_TIMEOUT,
  385. REMLOCK_HIGH_WATERMARK
  386. );
  387. switch (DeviceInfo->CmdSetId.QuadPart) {
  388. case 0x10483:
  389. case SCSI_COMMAND_SET_ID:
  390. //
  391. // intepret device type only for scsi-variant command sets
  392. //
  393. // NOTE: sbp2port.h #define's MAX_GENERIC_NAME_LENGTH as 16
  394. //
  395. DeviceInfo->uniGenericName.Length = 0;
  396. DeviceInfo->uniGenericName.MaximumLength = MAX_GENERIC_NAME_LENGTH;
  397. DeviceInfo->uniGenericName.Buffer = ExAllocatePool(PagedPool, DeviceInfo->uniGenericName.MaximumLength);
  398. if (!DeviceInfo->uniGenericName.Buffer) {
  399. TRACE(TL_PNP_ERROR, ("Failed to allocate uniGenericName.Buffer!"));
  400. status = STATUS_INSUFFICIENT_RESOURCES;
  401. break;
  402. }
  403. RtlZeroMemory(DeviceInfo->uniGenericName.Buffer, DeviceInfo->uniGenericName.MaximumLength);
  404. switch ((DeviceInfo->Lun.u.HighPart & 0x001F)) {
  405. case RBC_DEVICE:
  406. case DIRECT_ACCESS_DEVICE:
  407. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenDisk");
  408. break;
  409. case SEQUENTIAL_ACCESS_DEVICE:
  410. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenSequential");
  411. break;
  412. case PRINTER_DEVICE:
  413. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenPrinter");
  414. break;
  415. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  416. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenWorm");
  417. break;
  418. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  419. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenCdRom");
  420. break;
  421. case SCANNER_DEVICE:
  422. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenScanner");
  423. break;
  424. case OPTICAL_DEVICE:
  425. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenOptical");
  426. break;
  427. case MEDIUM_CHANGER:
  428. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenChanger");
  429. break;
  430. default:
  431. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenSbp2Device");
  432. break;
  433. }
  434. break;
  435. default:
  436. RtlAppendUnicodeToString(&DeviceInfo->uniGenericName, L"GenSbp2Device");
  437. break;
  438. }
  439. TRACE(TL_PNP_INFO, ("GenericName = %ws", DeviceInfo->uniGenericName.Buffer));
  440. DeviceInfo->DeviceObject->Flags |= DO_DIRECT_IO;
  441. status = Sbp2PreAllocateLists (pdoExtension);
  442. if (!NT_SUCCESS(status)) {
  443. IoDeleteDevice (pdoExtension->DeviceObject);
  444. DeviceInfo->DeviceObject = NULL;
  445. } else {
  446. PWCHAR symlinkBuffer;
  447. symlinkBuffer = ExAllocatePool(PagedPool,
  448. 3 * SBP2_MAX_TEXT_LEAF_LENGTH * sizeof (WCHAR)
  449. );
  450. if (symlinkBuffer) {
  451. swprintf(
  452. symlinkBuffer,
  453. L"\\DosDevices\\Sbp2&LUN%x&%08x%08x&Instance%02d",
  454. DeviceInfo->Lun.u.LowPart,
  455. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[0]),
  456. bswap(FdoExtension->ConfigRom.CR_Node_UniqueID[1]),
  457. InstanceNumber
  458. );
  459. RtlInitUnicodeString (&pdoExtension->UniSymLinkName,symlinkBuffer);
  460. status = IoCreateUnprotectedSymbolicLink(
  461. &pdoExtension->UniSymLinkName,
  462. &uniDeviceName
  463. );
  464. if (NT_SUCCESS (status)) {
  465. DEBUGPRINT2((
  466. "Sbp2Port: CreatePdo: symLink=%ws\n",
  467. symlinkBuffer
  468. ));
  469. } else {
  470. DEBUGPRINT1((
  471. "\nSbp2Port: CreatePdo: createSymLink err=x%x\n",
  472. status
  473. ));
  474. }
  475. } else {
  476. DEBUGPRINT1(("\n Sbp2CreatePdo: failed to alloc sym link buf\n"));
  477. }
  478. //
  479. // if sym link fails its not critical
  480. //
  481. status = STATUS_SUCCESS;
  482. }
  483. ExFreePool (buffer);
  484. DeviceInfo->DeviceObject->Flags &=~DO_DEVICE_INITIALIZING;
  485. return status;
  486. }
  487. NTSTATUS
  488. Sbp2StartDevice(
  489. IN PDEVICE_OBJECT DeviceObject
  490. )
  491. /*++
  492. Routine Description:
  493. This is our START_DEVICE, called when we get an IPR_MN_START_DEVICE. Initializes the driver and
  494. retrieves physical device information and 1394 bus information required for accessing the device.
  495. Arguments:
  496. DeviceObject = Sbp2 driver's device object
  497. Return Value:
  498. NTSTATUS
  499. --*/
  500. {
  501. PDEVICE_EXTENSION deviceExtension=DeviceObject->DeviceExtension;
  502. PFDO_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  503. NTSTATUS status;
  504. ULONG temp;
  505. BOOLEAN enabledBusResetNotification = FALSE;
  506. if (deviceExtension->Type == SBP2_PDO) {
  507. #if PASSWORD_SUPPORT
  508. Sbp2GetExclusiveValue(DeviceObject, &deviceExtension->Exclusive);
  509. #endif
  510. if (!TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZED)){
  511. //
  512. // initialize our device state flags
  513. //
  514. deviceExtension->DevicePowerState = PowerDeviceD0;
  515. deviceExtension->SystemPowerState = PowerSystemWorking;
  516. deviceExtension->MaxOrbListDepth = MAX_ORB_LIST_DEPTH;
  517. }
  518. deviceExtension->DeviceFlags = DEVICE_FLAG_PNP_STOPPED |
  519. DEVICE_FLAG_STOPPED | DEVICE_FLAG_INITIALIZING;
  520. //
  521. // Initiliaze the Timer and timeout DPC used for resets, reconnects and TASK functions
  522. //
  523. KeInitializeDpc(
  524. &deviceExtension->DeviceManagementTimeoutDpc,
  525. Sbp2DeviceManagementTimeoutDpc,
  526. deviceExtension
  527. );
  528. KeInitializeTimer(&deviceExtension->DeviceManagementTimer);
  529. KeInitializeSpinLock(&deviceExtension->OrbListSpinLock);
  530. KeInitializeSpinLock(&deviceExtension->ExtensionDataSpinLock);
  531. KeInitializeSpinLock(&deviceExtension->StatusFifoLock);
  532. KeInitializeSpinLock(&deviceExtension->FreeContextLock);
  533. KeInitializeSpinLock(&deviceExtension->BusRequestLock);
  534. ASSERT(!deviceExtension->ulPendingEvents);
  535. ASSERT(!deviceExtension->ulInternalEventCount);
  536. #if DBG
  537. deviceExtension->ulPendingEvents = 0;
  538. deviceExtension->ulInternalEventCount = 0;
  539. #endif
  540. //
  541. // Initialize our device Extension ORB's, status blocks, Irp and Irb's
  542. // Also allocate 1394 addresses for extension-held sbp2 ORB's
  543. //
  544. status = Sbp2InitializeDeviceExtension(deviceExtension);
  545. if (!NT_SUCCESS(status)) {
  546. goto exitStartDevice;
  547. }
  548. DEBUGPRINT2(("\nSbp2Port: StartDev: cmd set id=x%x\n", deviceExtension->DeviceInfo->CmdSetId.QuadPart));
  549. switch (deviceExtension->DeviceInfo->CmdSetId.QuadPart) {
  550. case 0x0:
  551. case 0x10483:
  552. case SCSI_COMMAND_SET_ID:
  553. SET_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_SPC_CMD_SET);
  554. DEBUGPRINT2(("Sbp2Port: StartDev: enabling SPC cmd set\n"));
  555. break;
  556. }
  557. //
  558. // login
  559. //
  560. status = Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGIN);
  561. if (!NT_SUCCESS(status)) {
  562. DEBUGPRINT1(("\nSbp2StartDev: Login failed with %x, retrying\n",status));
  563. if (status == STATUS_ACCESS_DENIED) {
  564. //
  565. // retry the login. By now we should have access since our bus reset forced a logout
  566. //
  567. Sbp2ManagementTransaction(deviceExtension,TRANSACTION_QUERY_LOGINS);
  568. }
  569. temp = 0;
  570. do {
  571. //
  572. // Give things time (one second) to settle...
  573. //
  574. LARGE_INTEGER waitValue;
  575. ASSERT(InterlockedIncrement(&deviceExtension->ulPendingEvents) == 1);
  576. KeInitializeEvent(&deviceExtension->ManagementEvent, NotificationEvent, FALSE);
  577. waitValue.QuadPart = -1 * 1000 * 1000 * 10;
  578. KeWaitForSingleObject(&deviceExtension->ManagementEvent,Executive,KernelMode,FALSE,&waitValue);
  579. ASSERT(InterlockedDecrement(&deviceExtension->ulPendingEvents) == 0);
  580. //
  581. // all the resident 1394 memory addresses's that we have, are
  582. // now invalidated... So we need to free them and re-allocate
  583. // them
  584. Sbp2CleanDeviceExtension (deviceExtension->DeviceObject,FALSE);
  585. Sbp2InitializeDeviceExtension(deviceExtension);
  586. status = Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGIN);
  587. temp ++;
  588. //
  589. // Note: We get STATUS_REQUEST_ABORTED rather than
  590. // STATUS_INVALID_GENERATION at passive level,
  591. // so check for that instead
  592. //
  593. } while ((status == STATUS_REQUEST_ABORTED) &&
  594. (temp <= 3));
  595. if (!NT_SUCCESS(status)) {
  596. goto exitStartDevice;
  597. }
  598. }
  599. #if PASSWORD_SUPPORT
  600. if (deviceExtension->Exclusive & EXCLUSIVE_FLAG_ENABLE) {
  601. status = Sbp2SetPasswordTransaction(
  602. deviceExtension,
  603. SBP2REQ_SET_PASSWORD_EXCLUSIVE
  604. );
  605. if (NT_SUCCESS(status)) {
  606. deviceExtension->Exclusive = EXCLUSIVE_FLAG_SET;
  607. } else {
  608. deviceExtension->Exclusive = EXCLUSIVE_FLAG_CLEAR;
  609. }
  610. Sbp2SetExclusiveValue(
  611. deviceExtension->DeviceObject,
  612. &deviceExtension->Exclusive
  613. );
  614. }
  615. #endif
  616. //
  617. // We are ready to receive and pass down requests, init the target's
  618. // fetch agent. The value we write to it is not important
  619. //
  620. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,AGENT_RESET_REG | REG_WRITE_SYNC);
  621. //
  622. // enable unsolicited status reg
  623. //
  624. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,UNSOLICITED_STATUS_REG | REG_WRITE_SYNC);
  625. CLEAR_FLAG(
  626. deviceExtension->DeviceFlags,
  627. (DEVICE_FLAG_PNP_STOPPED | DEVICE_FLAG_STOPPED)
  628. );
  629. //
  630. // register for idle detection
  631. //
  632. deviceExtension->IdleCounter = PoRegisterDeviceForIdleDetection(DeviceObject,
  633. -1,
  634. -1,
  635. PowerDeviceD3);
  636. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZING );
  637. SET_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZED);
  638. //
  639. // OK to register for bus reset notifications now
  640. //
  641. if (!Sbp2EnableBusResetNotification (deviceExtension, TRUE)) {
  642. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  643. CleanupOrbList (deviceExtension, STATUS_REQUEST_ABORTED);
  644. Sbp2ManagementTransaction (deviceExtension, TRANSACTION_LOGOUT);
  645. status = STATUS_INSUFFICIENT_RESOURCES;
  646. goto exitStartDevice;
  647. }
  648. enabledBusResetNotification = TRUE;
  649. if (TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_SPC_CMD_SET)) {
  650. //
  651. // issue an Inquiry to the target...
  652. //
  653. status = Sbp2IssueInternalCommand (deviceExtension,SCSIOP_INQUIRY);
  654. if (NT_SUCCESS(status)) {
  655. DEBUGPRINT2((
  656. "Sbp2Port: StartDev: cfgRom devType=x%x, inq devType=x%x\n",
  657. (deviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F),
  658. deviceExtension->InquiryData.DeviceType
  659. ));
  660. } else if ((status == STATUS_DEVICE_DOES_NOT_EXIST) ||
  661. (status == STATUS_DEVICE_BUSY)) {
  662. //
  663. // In win2k if the inquiry failed we'd just turn off the
  664. // SPC_CMD_SET flag and trundle on like nothing happened.
  665. //
  666. // However, we found some devices would allow logins but
  667. // nothing else, like a powered-down mactell hd which would
  668. // allow us to login but fail all other requests. This
  669. // really caused problems in win9x because Ntmap would
  670. // get loaded, but not init'd correctly, and on subsequent
  671. // re-plugs of any device we'd see trap 14's and the like.
  672. // So, it really makes alot more sense to just nip this
  673. // in the bud and fail the start if we get an error back
  674. // from the inquiry that tells us (per Sbp2ScsiRequests())
  675. // that the device has been removed or it timed out the 1st
  676. // inquiry . DanKn, 7 Apr 2000
  677. //
  678. DEBUGPRINT1((
  679. "\nSbp2Port: StartDev: ext=x%p, fatal INQUIRY err=x%x, " \
  680. "log out\n",
  681. deviceExtension,
  682. status
  683. ));
  684. Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGOUT);
  685. status = STATUS_IO_DEVICE_ERROR;
  686. goto exitStartDevice;
  687. } else {
  688. CLEAR_FLAG(
  689. deviceExtension->DeviceFlags,
  690. DEVICE_FLAG_SPC_CMD_SET
  691. );
  692. DEBUGPRINT1((
  693. "\nSbp2Port: StartDev: ext=x%p, non-fatal INQUIRY err=x%x\n",
  694. deviceExtension,
  695. status
  696. ));
  697. status = STATUS_SUCCESS;
  698. }
  699. }
  700. if (deviceExtension->InquiryData.DeviceType != (deviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F)){
  701. deviceExtension->InquiryData.DeviceType = (deviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F);
  702. DEBUGPRINT1(("\nSbp2StartDev: DeviceType mismatch, using one in ConfigRom %x\n",
  703. (deviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F)));
  704. }
  705. //
  706. // if this is a scanner or a printer we dont need to remain logged on..
  707. //
  708. if ((deviceExtension->InquiryData.DeviceType == PRINTER_DEVICE) ||
  709. (deviceExtension->InquiryData.DeviceType == SCANNER_DEVICE)){
  710. if (NT_SUCCESS(status)) {
  711. SET_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  712. CleanupOrbList(deviceExtension,STATUS_REQUEST_ABORTED);
  713. Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGOUT);
  714. }
  715. } else if (deviceExtension->InquiryData.DeviceType == RBC_DEVICE) {
  716. if (NT_SUCCESS(status)) {
  717. //
  718. // retrieve the RBC device mode page
  719. //
  720. status = Sbp2IssueInternalCommand(deviceExtension,SCSIOP_MODE_SENSE);
  721. if (!NT_SUCCESS(status)) {
  722. DEBUGPRINT1(("\nSbp2StartDev: Failed to retrieve RBC mode page\n"));
  723. goto exitStartDevice;
  724. }
  725. }
  726. }
  727. exitStartDevice:
  728. if (!NT_SUCCESS(status)) {
  729. PIO_ERROR_LOG_PACKET errorLogEntry;
  730. ULONG errorId = __LINE__ ;
  731. errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(DeviceObject,sizeof(IO_ERROR_LOG_PACKET));
  732. if(errorLogEntry != NULL) {
  733. errorLogEntry->ErrorCode = IO_ERR_DRIVER_ERROR;
  734. errorLogEntry->UniqueErrorValue = errorId;
  735. errorLogEntry->FinalStatus = status;
  736. errorLogEntry->DumpDataSize = 0;
  737. IoWriteErrorLogEntry(errorLogEntry);
  738. }
  739. DEBUGPRINT1((
  740. "Sbp2Port: StartDev: FAILED, status=x%x\n",
  741. status
  742. ));
  743. SET_FLAG(
  744. deviceExtension->DeviceFlags,
  745. (DEVICE_FLAG_PNP_STOPPED | DEVICE_FLAG_DEVICE_FAILED)
  746. );
  747. if (enabledBusResetNotification) {
  748. Sbp2EnableBusResetNotification (deviceExtension, FALSE);
  749. }
  750. } else {
  751. if (!SystemIsNT) {
  752. DeviceObject->Flags |= DO_POWER_PAGABLE;
  753. } else {
  754. DeviceObject->Flags &= ~DO_POWER_PAGABLE;
  755. }
  756. }
  757. } else if (deviceExtension->Type == SBP2_FDO){
  758. //
  759. // Bus driver FDO start device
  760. // retrieve parameters from the registry, if present
  761. //
  762. fdoExtension->MaxClassTransferSize = SBP2_MAX_TRANSFER_SIZE;
  763. DEBUGPRINT2(("Sbp2Port: StartDev: maxXferSize=x%x\n", fdoExtension->MaxClassTransferSize ));
  764. fdoExtension->DevicePowerState = PowerDeviceD0;
  765. fdoExtension->SystemPowerState = PowerSystemWorking;
  766. deviceExtension->DeviceFlags=DEVICE_FLAG_INITIALIZED;
  767. status = STATUS_SUCCESS;
  768. } else {
  769. status = STATUS_NO_SUCH_DEVICE;
  770. }
  771. return status;
  772. }
  773. NTSTATUS
  774. Sbp2PreAllocateLists(
  775. IN PDEVICE_EXTENSION DeviceExtension
  776. )
  777. /*++
  778. Routine Description:
  779. Initializes all the single linked workhorse lists plus lookasides. Only called from AddDevice or after
  780. a REMOVE -> START
  781. Arguments:
  782. DeviceExtension = Sbp2 driver's extension
  783. Return Value:
  784. NTSTATUS
  785. --*/
  786. {
  787. ULONG cnt ;
  788. PIRBIRP packet;
  789. NTSTATUS status;
  790. PADDRESS_FIFO statusFifoElement ;
  791. PSTATUS_FIFO_BLOCK statusFifo;
  792. PASYNC_REQUEST_CONTEXT context;
  793. //
  794. // initialize all interlocked lists
  795. //
  796. SET_FLAG(
  797. DeviceExtension->DeviceFlags,
  798. (DEVICE_FLAG_INITIALIZING | DEVICE_FLAG_STOPPED |
  799. DEVICE_FLAG_PNP_STOPPED)
  800. );
  801. InitializeListHead(&DeviceExtension->PendingOrbList);
  802. // BUGBUG: Some of these should be changed to lookaside lists
  803. ExInitializeSListHead(&DeviceExtension->FreeContextListHead);
  804. ExInitializeSListHead(&DeviceExtension->BusRequestIrpIrbListHead);
  805. ExInitializeSListHead(&DeviceExtension->StatusFifoListHead);
  806. // init bus request context pool
  807. ExInitializeNPagedLookasideList( &DeviceExtension->BusRequestContextPool,
  808. NULL,
  809. NULL,
  810. 0,
  811. sizeof(REQUEST_CONTEXT),
  812. '2pbs',
  813. 0
  814. );
  815. KeInitializeSpinLock(&DeviceExtension->OrbListSpinLock);
  816. KeInitializeSpinLock(&DeviceExtension->ExtensionDataSpinLock);
  817. KeInitializeSpinLock(&DeviceExtension->StatusFifoLock);
  818. KeInitializeSpinLock(&DeviceExtension->FreeContextLock);
  819. KeInitializeSpinLock(&DeviceExtension->BusRequestLock);
  820. //
  821. // alloc the irb/irp and context slists
  822. //
  823. for (cnt = 0; cnt < MAX_ORB_LIST_DEPTH; cnt++) {
  824. packet = ExAllocatePoolWithTag (NonPagedPool,sizeof(IRBIRP),'2pbs');
  825. if (!packet) {
  826. goto Sbp2PreAllocateLists_error;
  827. }
  828. packet->Irb = ExAllocatePoolWithTag (NonPagedPool,sizeof(IRB),'2pbs');
  829. if (!packet->Irb) {
  830. ExFreePool(packet);
  831. goto Sbp2PreAllocateLists_error;
  832. }
  833. packet->Irp = IoAllocateIrp (DeviceExtension->LowerDeviceObject->StackSize,FALSE);
  834. if (!packet->Irp) {
  835. ExFreePool(packet->Irb);
  836. ExFreePool(packet);
  837. goto Sbp2PreAllocateLists_error;
  838. }
  839. ExInterlockedPushEntrySList (&DeviceExtension->BusRequestIrpIrbListHead,
  840. &packet->ListPointer,
  841. &DeviceExtension->BusRequestLock);
  842. }
  843. //
  844. // status FIFO list
  845. //
  846. cnt = (sizeof(ADDRESS_FIFO)+sizeof(STATUS_FIFO_BLOCK))*NUM_PREALLOCATED_STATUS_FIFO_ELEMENTS;
  847. DeviceExtension->StatusFifoBase = \
  848. (PASYNC_REQUEST_CONTEXT) ExAllocatePoolWithTag(NonPagedPool,cnt,'2pbs');
  849. if (DeviceExtension->StatusFifoBase == NULL) {
  850. goto Sbp2PreAllocateLists_error;
  851. }
  852. for (cnt = 0; cnt < (NUM_PREALLOCATED_STATUS_FIFO_ELEMENTS - 1); cnt++) {
  853. statusFifoElement = (PADDRESS_FIFO) ((PUCHAR)DeviceExtension->StatusFifoBase + \
  854. cnt * (sizeof(ADDRESS_FIFO)+sizeof(STATUS_FIFO_BLOCK)));
  855. statusFifo = (PSTATUS_FIFO_BLOCK) ((PUCHAR)statusFifoElement + sizeof(ADDRESS_FIFO));
  856. //
  857. // make Mdl for this status fifo Element
  858. //
  859. statusFifoElement->FifoMdl = IoAllocateMdl(statusFifo,sizeof(STATUS_FIFO_BLOCK),FALSE,FALSE,NULL);
  860. if (statusFifoElement->FifoMdl == NULL) {
  861. goto Sbp2PreAllocateLists_error;
  862. }
  863. MmBuildMdlForNonPagedPool (statusFifoElement->FifoMdl);
  864. ExInterlockedPushEntrySList(&DeviceExtension->StatusFifoListHead,
  865. &statusFifoElement->FifoList,
  866. &DeviceExtension->StatusFifoLock);
  867. }
  868. //
  869. // Initialize the async request contexts (including page tables)
  870. //
  871. cnt = sizeof (ASYNC_REQUEST_CONTEXT) * MAX_ORB_LIST_DEPTH;
  872. DeviceExtension->AsyncContextBase = (PASYNC_REQUEST_CONTEXT)
  873. ExAllocatePoolWithTag (NonPagedPool, cnt, '2pbs');
  874. if (DeviceExtension->AsyncContextBase == NULL) {
  875. goto Sbp2PreAllocateLists_error;
  876. }
  877. RtlZeroMemory (DeviceExtension->AsyncContextBase, cnt);
  878. AllocateIrpAndIrb (DeviceExtension, &packet);
  879. if (!packet) {
  880. goto Sbp2PreAllocateLists_error;
  881. }
  882. for (cnt = 0; cnt < MAX_ORB_LIST_DEPTH; cnt++) {
  883. context = DeviceExtension->AsyncContextBase + cnt;
  884. context->Tag = SBP2_ASYNC_CONTEXT_TAG;
  885. //
  886. // Initialize the timeout DPC and timer
  887. //
  888. KeInitializeDpc(
  889. &context->TimerDpc,
  890. Sbp2RequestTimeoutDpc,
  891. DeviceExtension
  892. );
  893. KeInitializeTimer (&context->Timer);
  894. //
  895. // Alloc and/or map a page table
  896. //
  897. packet->Irb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
  898. packet->Irb->u.AllocateAddressRange.nLength = PAGE_SIZE;
  899. packet->Irb->u.AllocateAddressRange.fulNotificationOptions =
  900. NOTIFY_FLAGS_NEVER;
  901. packet->Irb->u.AllocateAddressRange.fulAccessType =
  902. ACCESS_FLAGS_TYPE_READ;
  903. packet->Irb->u.AllocateAddressRange.fulFlags =
  904. ALLOCATE_ADDRESS_FLAGS_USE_COMMON_BUFFER;
  905. packet->Irb->u.AllocateAddressRange.Callback = NULL;
  906. packet->Irb->u.AllocateAddressRange.Context = NULL;
  907. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_High = 0;
  908. packet->Irb->u.AllocateAddressRange.Required1394Offset.Off_Low = 0;
  909. packet->Irb->u.AllocateAddressRange.FifoSListHead = NULL;
  910. packet->Irb->u.AllocateAddressRange.FifoSpinLock = NULL;
  911. packet->Irb->u.AllocateAddressRange.AddressesReturned = 0;
  912. packet->Irb->u.AllocateAddressRange.DeviceExtension = DeviceExtension;
  913. packet->Irb->u.AllocateAddressRange.Mdl =
  914. context->PageTableContext.AddressContext.RequestMdl;
  915. packet->Irb->u.AllocateAddressRange.MaxSegmentSize =
  916. (SBP2_MAX_DIRECT_BUFFER_SIZE) / 2;
  917. packet->Irb->u.AllocateAddressRange.p1394AddressRange =(PADDRESS_RANGE)
  918. &context->PageTableContext.AddressContext.Address;
  919. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  920. if (!NT_SUCCESS (status)) {
  921. DeAllocateIrpAndIrb (DeviceExtension, packet);
  922. goto Sbp2PreAllocateLists_error;
  923. }
  924. //
  925. // Common buffer allocations get an mdl *back* from the
  926. // bus/port driver, need to retrieve a corresponding VA
  927. //
  928. context->PageTableContext.AddressContext.RequestMdl =
  929. packet->Irb->u.AllocateAddressRange.Mdl;
  930. context->PageTableContext.PageTable = MmGetMdlVirtualAddress(
  931. packet->Irb->u.AllocateAddressRange.Mdl
  932. );
  933. context->PageTableContext.AddressContext.AddressHandle =
  934. packet->Irb->u.AllocateAddressRange.hAddressRange;
  935. context->PageTableContext.AddressContext.Address.BusAddress.NodeId =
  936. DeviceExtension->InitiatorAddressId;
  937. context->PageTableContext.MaxPages = SBP2_NUM_PAGE_TABLE_ENTRIES;
  938. //
  939. // add this context to the linked list
  940. //
  941. ExInterlockedPushEntrySList(
  942. &DeviceExtension->FreeContextListHead,
  943. &context->LookasideList,
  944. &DeviceExtension->FreeContextLock
  945. );
  946. }
  947. DeAllocateIrpAndIrb (DeviceExtension, packet);
  948. //
  949. // initialize the mdl used for quadlet requests to the port driver..
  950. //
  951. DeviceExtension->ReservedMdl = IoAllocateMdl(
  952. &DeviceExtension->Reserved,
  953. sizeof(QUADLET),
  954. FALSE,
  955. FALSE,
  956. NULL
  957. );
  958. if (!DeviceExtension->ReservedMdl) {
  959. goto Sbp2PreAllocateLists_error;
  960. }
  961. MmBuildMdlForNonPagedPool (DeviceExtension->ReservedMdl);
  962. return STATUS_SUCCESS;
  963. Sbp2PreAllocateLists_error:
  964. Sbp2CleanDeviceExtension (DeviceExtension->DeviceObject, TRUE);
  965. return STATUS_INSUFFICIENT_RESOURCES;
  966. }
  967. NTSTATUS
  968. Sbp2InitializeDeviceExtension(
  969. IN PDEVICE_EXTENSION DeviceExtension
  970. )
  971. /*++
  972. Routine Description:
  973. Initializes all the data structures in our device extension, allocates appropriate 1394 addresses and workhorse
  974. Irps. It also creates a FreeList with pre-allocated contexts and command ORBs.
  975. Arguments:
  976. DeviceExtension = Sbp2 driver's extension
  977. Return Value:
  978. NTSTATUS
  979. --*/
  980. {
  981. ULONG i;
  982. KIRQL cIrql;
  983. NTSTATUS status;
  984. PDEVICE_OBJECT deviceObject = DeviceExtension->DeviceObject;
  985. PASYNC_REQUEST_CONTEXT context, oldContext;
  986. if (DeviceExtension->DeviceFlags & DEVICE_FLAG_REMOVED) {
  987. return STATUS_SUCCESS;
  988. }
  989. InitializeListHead(&DeviceExtension->PendingOrbList);
  990. DeviceExtension->NextContextToFree = NULL;
  991. DeviceExtension->OrbListDepth = 0;
  992. DeviceExtension->CurrentKey = 0;
  993. //
  994. // Get information volatile between bus resets
  995. //
  996. status = Sbp2UpdateNodeInformation (DeviceExtension);
  997. if (!NT_SUCCESS(status)) {
  998. goto exitInit;
  999. }
  1000. //
  1001. // get 1394 data transfer information
  1002. //
  1003. status = Sbp2GetControllerInfo (DeviceExtension);
  1004. if (!NT_SUCCESS(status)) {
  1005. goto exitInit;
  1006. }
  1007. //
  1008. //
  1009. // allocate a status block for the task ORB and a Management ORB
  1010. //
  1011. if (DeviceExtension->TaskOrbStatusContext.AddressHandle == NULL) {
  1012. status = AllocateAddressForStatus(deviceObject,
  1013. &DeviceExtension->TaskOrbStatusContext,
  1014. TASK_STATUS_BLOCK);
  1015. if (!NT_SUCCESS(status)) {
  1016. goto exitInit;
  1017. }
  1018. }
  1019. if (DeviceExtension->ManagementOrbStatusContext.AddressHandle == NULL) {
  1020. status = AllocateAddressForStatus(deviceObject,
  1021. &DeviceExtension->ManagementOrbStatusContext,
  1022. MANAGEMENT_STATUS_BLOCK);
  1023. if (!NT_SUCCESS(status)) {
  1024. goto exitInit;
  1025. }
  1026. }
  1027. if (DeviceExtension->GlobalStatusContext.AddressHandle == NULL) {
  1028. //
  1029. // setup the status FIFO list with the bus driver
  1030. //
  1031. status = AllocateAddressForStatus(deviceObject,
  1032. &DeviceExtension->GlobalStatusContext,
  1033. CMD_ORB_STATUS_BLOCK);
  1034. if (!NT_SUCCESS(status)) {
  1035. goto exitInit;
  1036. }
  1037. }
  1038. #if PASSWORD_SUPPORT
  1039. if (DeviceExtension->PasswordOrbStatusContext.AddressHandle == NULL) {
  1040. status = AllocateAddressForStatus( deviceObject,
  1041. &DeviceExtension->PasswordOrbStatusContext,
  1042. PASSWORD_STATUS_BLOCK
  1043. );
  1044. if (!NT_SUCCESS(status)) {
  1045. goto exitInit;
  1046. }
  1047. }
  1048. DeviceExtension->PasswordOrbContext.DeviceObject = deviceObject;
  1049. #endif
  1050. //
  1051. // Allocate a dummy,task, management ORBs and a login response ,which are going to be reused through out the drivers life...
  1052. //
  1053. DeviceExtension->TaskOrbContext.DeviceObject = deviceObject;
  1054. DeviceExtension->ManagementOrbContext.DeviceObject = deviceObject;
  1055. DeviceExtension->LoginRespContext.DeviceObject = deviceObject;
  1056. DeviceExtension->QueryLoginRespContext.DeviceObject = deviceObject;
  1057. KeInitializeEvent(&DeviceExtension->ManagementEvent,SynchronizationEvent, FALSE);
  1058. #if PASSWORD_SUPPORT
  1059. // kevent for password orb context
  1060. KeInitializeEvent(
  1061. &DeviceExtension->PasswordEvent,
  1062. SynchronizationEvent,
  1063. FALSE
  1064. );
  1065. #endif
  1066. if (DeviceExtension->CommonBufferContext.AddressHandle == NULL) {
  1067. status = AllocateSingle1394Address(
  1068. deviceObject,
  1069. NULL,
  1070. sizeof (*DeviceExtension->CommonBuffer),
  1071. ACCESS_FLAGS_TYPE_READ | ACCESS_FLAGS_TYPE_WRITE,
  1072. &DeviceExtension->CommonBufferContext
  1073. );
  1074. if (!NT_SUCCESS(status)) {
  1075. goto exitInit;
  1076. }
  1077. (PVOID) DeviceExtension->CommonBuffer =
  1078. DeviceExtension->CommonBufferContext.Reserved;
  1079. DeviceExtension->TaskOrb = &DeviceExtension->CommonBuffer->TaskOrb;
  1080. DeviceExtension->TaskOrbContext.Address.BusAddress =
  1081. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1082. DeviceExtension->ManagementOrb =
  1083. &DeviceExtension->CommonBuffer->ManagementOrb;
  1084. DeviceExtension->ManagementOrbContext.Address.BusAddress =
  1085. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1086. DeviceExtension->ManagementOrbContext.Address.BusAddress.Off_Low +=
  1087. (ULONG) ((PUCHAR) DeviceExtension->ManagementOrb -
  1088. (PUCHAR) DeviceExtension->CommonBuffer);
  1089. DeviceExtension->LoginResponse =
  1090. &DeviceExtension->CommonBuffer->LoginResponse;
  1091. DeviceExtension->LoginRespContext.Address.BusAddress =
  1092. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1093. DeviceExtension->LoginRespContext.Address.BusAddress.Off_Low +=
  1094. (ULONG) ((PUCHAR) DeviceExtension->LoginResponse -
  1095. (PUCHAR) DeviceExtension->CommonBuffer);
  1096. DeviceExtension->QueryLoginResponse =
  1097. &DeviceExtension->CommonBuffer->QueryLoginResponse;
  1098. DeviceExtension->QueryLoginRespContext.Address.BusAddress =
  1099. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1100. DeviceExtension->QueryLoginRespContext.Address.BusAddress.Off_Low +=
  1101. (ULONG) ((PUCHAR) DeviceExtension->QueryLoginResponse -
  1102. (PUCHAR) DeviceExtension->CommonBuffer);
  1103. #if PASSWORD_SUPPORT
  1104. DeviceExtension->PasswordOrb =
  1105. &DeviceExtension->CommonBuffer->PasswordOrb;
  1106. DeviceExtension->PasswordOrbContext.Address.BusAddress =
  1107. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1108. DeviceExtension->PasswordOrbContext.Address.BusAddress.Off_Low +=
  1109. (ULONG) ((PUCHAR) DeviceExtension->PasswordOrb -
  1110. (PUCHAR) DeviceExtension->CommonBuffer);
  1111. #endif
  1112. DeviceExtension->OrbPoolContext.Reserved =
  1113. DeviceExtension->CommonBuffer->CmdOrbs;
  1114. DeviceExtension->OrbPoolContext.Address.BusAddress =
  1115. DeviceExtension->CommonBufferContext.Address.BusAddress;
  1116. DeviceExtension->OrbPoolContext.Address.BusAddress.Off_Low +=
  1117. (ULONG) ((PUCHAR) DeviceExtension->OrbPoolContext.Reserved -
  1118. (PUCHAR) DeviceExtension->CommonBuffer);
  1119. KeAcquireSpinLock (&DeviceExtension->OrbListSpinLock, &cIrql);
  1120. //
  1121. // Initialize our pool of contexts
  1122. //
  1123. for (i = 0, context = NULL; i < MAX_ORB_LIST_DEPTH; i++) {
  1124. //
  1125. // Mark this unused context as completed so if we had to
  1126. // free our freelist now (because we got a remove) we wouldn't
  1127. // try to complete its request
  1128. //
  1129. oldContext = context;
  1130. context = (PVOID) ExInterlockedPopEntrySList (&DeviceExtension->FreeContextListHead,
  1131. &DeviceExtension->FreeContextLock);
  1132. context = RETRIEVE_CONTEXT (context,LookasideList);
  1133. context->Flags |= ASYNC_CONTEXT_FLAG_COMPLETED;
  1134. //
  1135. // Create a linked list so we push all the entries later
  1136. //
  1137. context->OrbList.Blink = (PLIST_ENTRY) oldContext;
  1138. //
  1139. // Each command ORB gets a small piece of our continuous pool
  1140. // mapped into the 1394 memory space. The sizeof(PVOID) bytes
  1141. // before the cmdorb buffer are the pointer to its context.
  1142. //
  1143. context->CmdOrb = &DeviceExtension->CommonBuffer->CmdOrbs[i].Orb;
  1144. DeviceExtension->CommonBuffer->CmdOrbs[i].AsyncReqCtx = context;
  1145. context->CmdOrbAddress.BusAddress.Off_Low = \
  1146. DeviceExtension->OrbPoolContext.Address.BusAddress.Off_Low +
  1147. (i * sizeof (ARCP_ORB)) + FIELD_OFFSET (ARCP_ORB, Orb);
  1148. context->CmdOrbAddress.BusAddress.Off_High = \
  1149. DeviceExtension->OrbPoolContext.Address.BusAddress.Off_High;
  1150. context->CmdOrbAddress.BusAddress.NodeId = \
  1151. DeviceExtension->InitiatorAddressId;
  1152. }
  1153. //
  1154. // re-create the free list
  1155. //
  1156. while (context) {
  1157. oldContext = context;
  1158. ExInterlockedPushEntrySList(&DeviceExtension->FreeContextListHead,
  1159. &context->LookasideList,
  1160. &DeviceExtension->FreeContextLock);
  1161. context = (PASYNC_REQUEST_CONTEXT) oldContext->OrbList.Blink;
  1162. oldContext->OrbList.Blink = NULL;
  1163. }
  1164. KeReleaseSpinLock (&DeviceExtension->OrbListSpinLock,cIrql);
  1165. }
  1166. //
  1167. // Update the NodeId portion of the page table addr for each
  1168. // ASYNC_REQUEST_CONTEXT and for the login/queryLogin responses
  1169. //
  1170. for (i = 0; i < MAX_ORB_LIST_DEPTH; i++) {
  1171. context = DeviceExtension->AsyncContextBase + i;
  1172. context->PageTableContext.AddressContext.Address.BusAddress.NodeId =
  1173. DeviceExtension->InitiatorAddressId;
  1174. }
  1175. DeviceExtension->LoginRespContext.Address.BusAddress.NodeId =
  1176. DeviceExtension->InitiatorAddressId;
  1177. DeviceExtension->QueryLoginRespContext.Address.BusAddress.NodeId =
  1178. DeviceExtension->InitiatorAddressId;
  1179. //
  1180. // Finally, allocate a dummy addr that we can easily free & realloc
  1181. // to re-enable phyical addr filters after bus resets
  1182. //
  1183. if (DeviceExtension->DummyContext.AddressHandle == NULL) {
  1184. status = AllocateSingle1394Address(
  1185. deviceObject,
  1186. &DeviceExtension->Dummy,
  1187. sizeof(DeviceExtension->Dummy),
  1188. ACCESS_FLAGS_TYPE_READ | ACCESS_FLAGS_TYPE_WRITE,
  1189. &DeviceExtension->DummyContext
  1190. );
  1191. if (!NT_SUCCESS(status)) {
  1192. goto exitInit;
  1193. }
  1194. }
  1195. //
  1196. // Done
  1197. //
  1198. DEBUGPRINT2(("Sbp2Port: InitDevExt: ext=x%p\n", DeviceExtension));
  1199. exitInit:
  1200. return status;
  1201. }
  1202. BOOLEAN
  1203. Sbp2CleanDeviceExtension(
  1204. IN PDEVICE_OBJECT DeviceObject,
  1205. BOOLEAN FreeLists
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. Called when we get a remove, so it will free all used pool and all the resident Irps.
  1210. It wil also free our FreeList of contexts and any complete any pending IO requests
  1211. Arguments:
  1212. DeviceExtension = Sbp2 driver's extension
  1213. FreeLists - TRUE means we cleanup EVERYTHING including our lookaside lists
  1214. Return Value:
  1215. NTSTATUS
  1216. --*/
  1217. {
  1218. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1219. PFDO_DEVICE_EXTENSION fdoExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  1220. KIRQL cIrql;
  1221. PADDRESS_FIFO statusFifoElement;
  1222. ULONG i;
  1223. BOOLEAN valid = FALSE;
  1224. PIRBIRP packet;
  1225. //
  1226. // there are two types of cleanups. One for the PDO and one for the FDO(alot simpler)
  1227. //
  1228. if (deviceExtension->Type == SBP2_PDO) {
  1229. //
  1230. // make sure that this PDO is something in our list and that we have NOT deleted
  1231. // it already....
  1232. //
  1233. fdoExtension = (PFDO_DEVICE_EXTENSION) deviceExtension->BusFdo->DeviceExtension;
  1234. for (i = 0; i < fdoExtension->DeviceListSize; i++) {
  1235. if (fdoExtension->DeviceList[i].DeviceObject == DeviceObject) {
  1236. valid = TRUE;
  1237. }
  1238. }
  1239. if (!valid) {
  1240. return FALSE;
  1241. }
  1242. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZED) ){
  1243. //
  1244. // stop the timer for any pending management requests
  1245. //
  1246. KeCancelTimer (&deviceExtension->DeviceManagementTimer);
  1247. //
  1248. // We have a list of requests pending, clean it up
  1249. // The reset/logout has automatically made the target to discard any requests
  1250. //
  1251. CleanupOrbList (deviceExtension, STATUS_REQUEST_ABORTED);
  1252. }
  1253. //
  1254. // after a bus reset we must reallocate at least one physical address to allow
  1255. // the ohci driver to re-enable the physical address filters
  1256. //
  1257. if (deviceExtension->DummyContext.AddressHandle != NULL) {
  1258. FreeAddressRange (deviceExtension,&deviceExtension->DummyContext);
  1259. }
  1260. if (FreeLists){
  1261. if (TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_INITIALIZED) ||
  1262. TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_INITIALIZING)){
  1263. FreeAddressRange(deviceExtension,&deviceExtension->TaskOrbStatusContext);
  1264. FreeAddressRange(deviceExtension,&deviceExtension->GlobalStatusContext);
  1265. #if PASSWORD_SUPPORT
  1266. FreeAddressRange(deviceExtension,&deviceExtension->PasswordOrbStatusContext);
  1267. #endif
  1268. FreeAddressRange(deviceExtension,&deviceExtension->ManagementOrbStatusContext);
  1269. if (deviceExtension->PowerDeferredIrp) {
  1270. deviceExtension->PowerDeferredIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  1271. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  1272. IoCompleteRequest (deviceExtension->PowerDeferredIrp, IO_NO_INCREMENT);
  1273. deviceExtension->PowerDeferredIrp = NULL;
  1274. }
  1275. if (deviceExtension->DeferredPowerRequest) {
  1276. deviceExtension->DeferredPowerRequest->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  1277. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  1278. IoCompleteRequest(deviceExtension->DeferredPowerRequest, IO_NO_INCREMENT);
  1279. deviceExtension->DeferredPowerRequest = NULL;
  1280. }
  1281. if (deviceExtension->UniSymLinkName.Buffer) {
  1282. IoDeleteSymbolicLink(&deviceExtension->UniSymLinkName);
  1283. RtlFreeUnicodeString(&deviceExtension->UniSymLinkName);
  1284. deviceExtension->UniSymLinkName.Buffer = NULL;
  1285. }
  1286. //
  1287. // before we go any further, check if the device is physically removed
  1288. //
  1289. if (!TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED)) {
  1290. DEBUGPRINT2(("Sbp2Port: Cleanup: ext=x%p, not freeing ALL wkg sets, dev present\n", deviceExtension));
  1291. return TRUE;
  1292. } else {
  1293. DEBUGPRINT2(("Sbp2Port: Cleanup: ext=x%p, freeing ALL wkg sets\n", deviceExtension));
  1294. }
  1295. CLEAR_FLAG(deviceExtension->DeviceFlags, (DEVICE_FLAG_INITIALIZED | DEVICE_FLAG_INITIALIZING));
  1296. //
  1297. // OK to free common buffer if device is going away
  1298. //
  1299. FreeAddressRange(deviceExtension,&deviceExtension->CommonBufferContext);
  1300. deviceExtension->OrbPoolContext.Reserved = NULL;
  1301. //
  1302. // Free all the page tables & async context buffer
  1303. //
  1304. if (deviceExtension->AsyncContextBase != NULL) {
  1305. for (i = 0; i < MAX_ORB_LIST_DEPTH; i++) {
  1306. PASYNC_REQUEST_CONTEXT context;
  1307. context = deviceExtension->AsyncContextBase + i;
  1308. if (context->PageTableContext.PageTable != NULL) {
  1309. //
  1310. // Common buffer, we didn't alloc the mdl,
  1311. // so zero the field to prevent our free'ing it
  1312. //
  1313. context->PageTableContext.AddressContext.
  1314. RequestMdl = NULL;
  1315. FreeAddressRange(
  1316. deviceExtension,
  1317. &context->PageTableContext.AddressContext
  1318. );
  1319. }
  1320. }
  1321. ExFreePool (deviceExtension->AsyncContextBase);
  1322. deviceExtension->AsyncContextBase = NULL;
  1323. }
  1324. //
  1325. // free pool for status fifo list
  1326. //
  1327. if (deviceExtension->StatusFifoBase !=NULL ) {
  1328. statusFifoElement = (PVOID) ExInterlockedPopEntrySList (&deviceExtension->StatusFifoListHead,
  1329. &deviceExtension->StatusFifoLock);
  1330. while (statusFifoElement){
  1331. DEBUGPRINT3(("Sbp2Port: Cleanup: freeing statusFifo=x%p, fifoBase=x%p\n",
  1332. statusFifoElement,deviceExtension->StatusFifoBase));
  1333. IoFreeMdl (statusFifoElement->FifoMdl);
  1334. statusFifoElement = (PVOID) ExInterlockedPopEntrySList (&deviceExtension->StatusFifoListHead,
  1335. &deviceExtension->StatusFifoLock);
  1336. };
  1337. ExFreePool (deviceExtension->StatusFifoBase);
  1338. deviceExtension->StatusFifoBase = NULL;
  1339. }
  1340. //
  1341. // free the irb/irp and context slists
  1342. //
  1343. packet = (PIRBIRP) ExInterlockedPopEntrySList (&deviceExtension->BusRequestIrpIrbListHead,
  1344. &deviceExtension->BusRequestLock);
  1345. while (packet) {
  1346. ExFreePool(packet->Irb);
  1347. if (packet->Irp->Type == IO_TYPE_IRP) {
  1348. IoFreeIrp(packet->Irp);
  1349. }
  1350. ExFreePool(packet);
  1351. packet = (PIRBIRP) ExInterlockedPopEntrySList (&deviceExtension->BusRequestIrpIrbListHead,
  1352. &deviceExtension->BusRequestLock);
  1353. };
  1354. // delete our bus request context lookaside list
  1355. ExDeleteNPagedLookasideList(&deviceExtension->BusRequestContextPool);
  1356. if (deviceExtension->ReservedMdl) {
  1357. IoFreeMdl (deviceExtension->ReservedMdl);
  1358. deviceExtension->ReservedMdl = NULL;
  1359. }
  1360. // free the vendor id
  1361. if (deviceExtension->DeviceInfo->uniVendorId.Buffer) {
  1362. ExFreePool(deviceExtension->DeviceInfo->uniVendorId.Buffer);
  1363. deviceExtension->DeviceInfo->uniVendorId.Length = 0;
  1364. deviceExtension->DeviceInfo->uniVendorId.Buffer = NULL;
  1365. }
  1366. // free the model id
  1367. if (deviceExtension->DeviceInfo->uniModelId.Buffer) {
  1368. ExFreePool(deviceExtension->DeviceInfo->uniModelId.Buffer);
  1369. deviceExtension->DeviceInfo->uniModelId.Length = 0;
  1370. deviceExtension->DeviceInfo->uniModelId.Buffer = NULL;
  1371. }
  1372. // free the generic name
  1373. if (deviceExtension->DeviceInfo->uniGenericName.Buffer) {
  1374. ExFreePool(deviceExtension->DeviceInfo->uniGenericName.Buffer);
  1375. deviceExtension->DeviceInfo->uniGenericName.Length = 0;
  1376. deviceExtension->DeviceInfo->uniGenericName.Buffer = NULL;
  1377. }
  1378. }
  1379. }
  1380. } else {
  1381. fdoExtension = (PFDO_DEVICE_EXTENSION) deviceExtension;
  1382. if (fdoExtension->Sbp2ObjectDirectory != NULL) {
  1383. ZwMakeTemporaryObject (fdoExtension->Sbp2ObjectDirectory);
  1384. ZwClose (fdoExtension->Sbp2ObjectDirectory);
  1385. fdoExtension->Sbp2ObjectDirectory = NULL;
  1386. }
  1387. if (TEST_FLAG(fdoExtension->DeviceFlags,DEVICE_FLAG_REMOVED)) {
  1388. return FALSE;
  1389. } else {
  1390. SET_FLAG (fdoExtension->DeviceFlags, DEVICE_FLAG_REMOVED);
  1391. }
  1392. if (fdoExtension->DeviceListSize != 0) {
  1393. //
  1394. // Disable bus reset notifications
  1395. //
  1396. AllocateIrpAndIrb ((PDEVICE_EXTENSION) fdoExtension, &packet);
  1397. if (packet) {
  1398. packet->Irb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
  1399. packet->Irb->Flags = 0;
  1400. packet->Irb->u.BusResetNotification.fulFlags =
  1401. DEREGISTER_NOTIFICATION_ROUTINE;
  1402. Sbp2SendRequest(
  1403. (PDEVICE_EXTENSION) fdoExtension,
  1404. packet,
  1405. SYNC_1394_REQUEST
  1406. );
  1407. DeAllocateIrpAndIrb ((PDEVICE_EXTENSION) fdoExtension, packet);
  1408. }
  1409. }
  1410. //
  1411. // Clean up any remaining PDO's
  1412. //
  1413. KeAcquireSpinLock (&fdoExtension->DeviceListLock,&cIrql);
  1414. for (; fdoExtension->DeviceListSize > 0; fdoExtension->DeviceListSize--) {
  1415. i = fdoExtension->DeviceListSize - 1;
  1416. if (fdoExtension->DeviceList[i].DeviceObject) {
  1417. deviceExtension =
  1418. fdoExtension->DeviceList[i].DeviceObject->DeviceExtension;
  1419. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED);
  1420. DeviceObject = fdoExtension->DeviceList[i].DeviceObject;
  1421. KeReleaseSpinLock (&fdoExtension->DeviceListLock, cIrql);
  1422. if (Sbp2CleanDeviceExtension (DeviceObject, TRUE)) {
  1423. //
  1424. // Acquire the pdo's remove lock, start the queue
  1425. // cleanup, and and wait for io to complete. Then
  1426. // delete the device & continue.
  1427. //
  1428. IoAcquireRemoveLock (&deviceExtension->RemoveLock, NULL);
  1429. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  1430. Sbp2StartNextPacketByKey (DeviceObject, 0);
  1431. KeLowerIrql (cIrql);
  1432. DEBUGPRINT2((
  1433. "Sbp2Port: CleanDevExt: walking fdo, wait for " \
  1434. "io compl pdo=x%p...\n",
  1435. DeviceObject
  1436. ));
  1437. IoReleaseRemoveLockAndWait(
  1438. &deviceExtension->RemoveLock,
  1439. NULL
  1440. );
  1441. deviceExtension->Type = SBP2_PDO_DELETED;
  1442. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  1443. IoDeleteDevice (DeviceObject);
  1444. DEBUGPRINT2((
  1445. "Sbp2Port: CleanDevExt: ............ io compl," \
  1446. " deleted pdo=x%p\n",
  1447. DeviceObject
  1448. ));
  1449. KeAcquireSpinLock (&fdoExtension->DeviceListLock, &cIrql);
  1450. fdoExtension->DeviceList[i].DeviceObject = NULL;
  1451. } else {
  1452. KeAcquireSpinLock (&fdoExtension->DeviceListLock, &cIrql);
  1453. }
  1454. }
  1455. if (fdoExtension->DeviceList[i].uniVendorId.Buffer) {
  1456. ExFreePool(fdoExtension->DeviceList[i].uniVendorId.Buffer);
  1457. fdoExtension->DeviceList[i].uniVendorId.Length = 0;
  1458. fdoExtension->DeviceList[i].uniVendorId.Buffer = NULL;
  1459. }
  1460. if (fdoExtension->DeviceList[i].uniModelId.Buffer) {
  1461. ExFreePool(fdoExtension->DeviceList[i].uniModelId.Buffer);
  1462. fdoExtension->DeviceList[i].uniModelId.Length = 0;
  1463. fdoExtension->DeviceList[i].uniModelId.Buffer = NULL;
  1464. }
  1465. if (fdoExtension->DeviceList[i].uniGenericName.Buffer) {
  1466. ExFreePool(fdoExtension->DeviceList[i].uniGenericName.Buffer);
  1467. fdoExtension->DeviceList[i].uniGenericName.Length = 0;
  1468. fdoExtension->DeviceList[i].uniGenericName.Buffer = NULL;
  1469. }
  1470. }
  1471. KeReleaseSpinLock (&fdoExtension->DeviceListLock, cIrql);
  1472. }
  1473. return TRUE;
  1474. }
  1475. VOID
  1476. Sbp2Unload(
  1477. IN PDRIVER_OBJECT DriverObject
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. Does nothing really...
  1482. Arguments:
  1483. DriverObject - the driver being unloaded
  1484. Return Value:
  1485. none
  1486. --*/
  1487. {
  1488. DEBUGPRINT1(("Sbp2Port: unloading\n\n"));
  1489. return;
  1490. }
  1491. VOID
  1492. Sbp2DeviceManagementTimeoutDpc(
  1493. IN PKDPC Dpc,
  1494. IN PDEVICE_EXTENSION DeviceExtension,
  1495. IN PVOID SystemArgument1,
  1496. IN PVOID SystemArgument2
  1497. )
  1498. {
  1499. ULONG i;
  1500. PDEVICE_EXTENSION pdoExtension;
  1501. PFDO_DEVICE_EXTENSION fdoExtension;
  1502. if (Dpc != &DeviceExtension->DeviceManagementTimeoutDpc) {
  1503. return;
  1504. }
  1505. if (TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED)) {
  1506. return;
  1507. }
  1508. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_RECONNECT)) {
  1509. //
  1510. // The flag indicates that a bus reset occured, and a reconnect never happened...
  1511. // OR that the device is realy hose so we reset it and we need to re-login
  1512. //
  1513. DEBUGPRINT1((
  1514. "Sbp2Port: RECONNECT timeout, Ext=x%p, Flags=x%x, doing re-login\n",
  1515. DeviceExtension,
  1516. DeviceExtension->DeviceFlags
  1517. ));
  1518. //
  1519. // all the resident 1394 memory addresses's that we have, are
  1520. // now invalidated... So we need to free them and re-allocate
  1521. // them
  1522. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1523. CLEAR_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_RECONNECT);
  1524. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1525. //
  1526. // If device is marked STOPPED then a target reset was
  1527. // done and that affected all LUNs (spec sect 10.4.4).
  1528. // So if this is a multilun device try logins on each
  1529. // pdo as appropriate.
  1530. //
  1531. fdoExtension = (PFDO_DEVICE_EXTENSION)
  1532. DeviceExtension->BusFdo->DeviceExtension;
  1533. if ((fdoExtension->DeviceListSize > 1) &&
  1534. TEST_FLAG (DeviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED)) {
  1535. for (i = 0; i < fdoExtension->DeviceListSize; i++) {
  1536. pdoExtension = (PDEVICE_EXTENSION)
  1537. fdoExtension->DeviceList[i].DeviceObject->DeviceExtension;
  1538. if (pdoExtension->DeviceObject ==
  1539. DeviceExtension->DeviceObject) {
  1540. // No need to update node info since no bus reset done
  1541. Sbp2ManagementTransaction(
  1542. pdoExtension,
  1543. TRANSACTION_LOGIN
  1544. );
  1545. continue;
  1546. }
  1547. KeAcquireSpinLockAtDpcLevel(
  1548. &pdoExtension->ExtensionDataSpinLock
  1549. );
  1550. if (TEST_FLAG(
  1551. pdoExtension->DeviceFlags,
  1552. DEVICE_FLAG_INITIALIZED
  1553. ) &&
  1554. !TEST_FLAG(
  1555. pdoExtension->DeviceFlags,
  1556. DEVICE_FLAG_STOPPED | DEVICE_FLAG_RESET_IN_PROGRESS |
  1557. DEVICE_FLAG_REMOVED | DEVICE_FLAG_LOGIN_IN_PROGRESS |
  1558. DEVICE_FLAG_RECONNECT | DEVICE_FLAG_DEVICE_FAILED |
  1559. DEVICE_FLAG_SURPRISE_REMOVED
  1560. )) {
  1561. SET_FLAG(
  1562. pdoExtension->DeviceFlags,
  1563. (DEVICE_FLAG_STOPPED | DEVICE_FLAG_RESET_IN_PROGRESS)
  1564. );
  1565. KeReleaseSpinLockFromDpcLevel(
  1566. &pdoExtension->ExtensionDataSpinLock
  1567. );
  1568. CleanupOrbList (pdoExtension, STATUS_REQUEST_ABORTED);
  1569. // No need to update node info since no bus reset done
  1570. Sbp2ManagementTransaction(
  1571. pdoExtension,
  1572. TRANSACTION_LOGIN
  1573. );
  1574. } else {
  1575. KeReleaseSpinLockFromDpcLevel(
  1576. &pdoExtension->ExtensionDataSpinLock
  1577. );
  1578. }
  1579. }
  1580. } else {
  1581. Sbp2UpdateNodeInformation (DeviceExtension);
  1582. Sbp2ManagementTransaction (DeviceExtension, TRANSACTION_LOGIN);
  1583. }
  1584. return ;
  1585. }
  1586. if (TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_LOGIN_IN_PROGRESS)) {
  1587. ULONG flags;
  1588. //
  1589. // the asynchronous login attempt timed out. This is bad news and means the
  1590. // device is not responding
  1591. //
  1592. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1593. flags = DeviceExtension->DeviceFlags;
  1594. CLEAR_FLAG(DeviceExtension->DeviceFlags,(DEVICE_FLAG_LOGIN_IN_PROGRESS | DEVICE_FLAG_RESET_IN_PROGRESS));
  1595. SET_FLAG(DeviceExtension->DeviceFlags, (DEVICE_FLAG_STOPPED | DEVICE_FLAG_DEVICE_FAILED));
  1596. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1597. //
  1598. // check if we had a power irp deferred.. If we did call startio to abort it..
  1599. //
  1600. if (DeviceExtension->DeferredPowerRequest) {
  1601. Sbp2StartIo(DeviceExtension->DeviceObject,DeviceExtension->DeferredPowerRequest);
  1602. DeviceExtension->DeferredPowerRequest = NULL;
  1603. }
  1604. DEBUGPRINT1((
  1605. "Sbp2Port: LOGIN timeout, Ext=x%p, Flags=x%x, device stopped\n",
  1606. DeviceExtension,
  1607. flags
  1608. ));
  1609. Sbp2StartNextPacketByKey (DeviceExtension->DeviceObject, 0);
  1610. IoInvalidateDeviceState(DeviceExtension->DeviceObject);
  1611. return;
  1612. }
  1613. if (TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_RESET_IN_PROGRESS)) {
  1614. //
  1615. // the reset attempt has timed out
  1616. //
  1617. DEBUGPRINT1((
  1618. "Sbp2Port: RESET timeout, Ext=x%p, Flags=x%x, ",
  1619. DeviceExtension,
  1620. DeviceExtension->DeviceFlags
  1621. ));
  1622. if (!TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED)) {
  1623. //
  1624. // Second level of recovery, do a TARGET_RESET task function
  1625. //
  1626. DEBUGPRINT1(("doing target reset\n"));
  1627. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1628. SET_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  1629. DeviceExtension->MaxOrbListDepth = max(MIN_ORB_LIST_DEPTH,DeviceExtension->MaxOrbListDepth/2);
  1630. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1631. CleanupOrbList(DeviceExtension,STATUS_REQUEST_ABORTED);
  1632. //
  1633. // we are close to timing out a reset, try a hard reset
  1634. //
  1635. Sbp2Reset (DeviceExtension->DeviceObject, TRUE);
  1636. return;
  1637. } else {
  1638. //
  1639. // Third level of recovery. Do a hardware node reset
  1640. //
  1641. DEBUGPRINT1(("doing CMD_RESET and relogin.\n"));
  1642. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1643. DeviceExtension->Reserved = 0;
  1644. SET_FLAG(DeviceExtension->DeviceFlags, (DEVICE_FLAG_RESET_IN_PROGRESS | DEVICE_FLAG_RECONNECT | DEVICE_FLAG_STOPPED));
  1645. DeviceExtension->DueTime.HighPart = -1;
  1646. DeviceExtension->DueTime.LowPart = SBP2_RELOGIN_DELAY;
  1647. KeSetTimer(&DeviceExtension->DeviceManagementTimer,DeviceExtension->DueTime, &DeviceExtension->DeviceManagementTimeoutDpc);
  1648. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->ExtensionDataSpinLock);
  1649. Sbp2AccessRegister(DeviceExtension,&DeviceExtension->Reserved,CORE_RESET_REG | REG_WRITE_ASYNC);
  1650. return;
  1651. }
  1652. }
  1653. }
  1654. VOID
  1655. Sbp2RequestTimeoutDpc(
  1656. IN PKDPC Dpc,
  1657. IN PDEVICE_EXTENSION DeviceExtension,
  1658. IN PVOID SystemArgument1,
  1659. IN PVOID SystemArgument2
  1660. )
  1661. /*++
  1662. Routine Description:
  1663. Arguments:
  1664. DeviceObject - Our Device object
  1665. Context - DeviceExtension
  1666. Return Value:
  1667. NTSTATUS
  1668. --*/
  1669. {
  1670. PIRP requestIrp = NULL;
  1671. PASYNC_REQUEST_CONTEXT current = NULL;
  1672. PASYNC_REQUEST_CONTEXT next = NULL;
  1673. LARGE_INTEGER Time;
  1674. #if DBG
  1675. ULONG xferLen;
  1676. UCHAR cdb[6];
  1677. #endif
  1678. //
  1679. // return if device is stopped, but since reset can occur while device is stopped
  1680. // thats why this check is ater the reset timing code
  1681. //
  1682. if (IsListEmpty (&DeviceExtension->PendingOrbList)) {
  1683. return ;
  1684. }
  1685. //
  1686. // search the linked list of contexts, to see which guy timed out
  1687. //
  1688. KeAcquireSpinLockAtDpcLevel(&DeviceExtension->OrbListSpinLock);
  1689. next = RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Flink,OrbList);
  1690. // see if the last status has the suspended state bit set...
  1691. if ((DeviceExtension->LastStatusBlock.AddressAndStatus.u.HighQuad.u.HighPart & STATUS_BLOCK_ENDOFLIST_BIT_MASK) &&
  1692. (next->Flags & ASYNC_CONTEXT_FLAG_TIMER_STARTED) &&
  1693. !(next->Flags & ASYNC_CONTEXT_FLAG_RANG_DOORBELL)) {
  1694. TRACE(TL_1394_INFO, ("GC: Pending Orb - Ring Doorbell."));
  1695. // set the flag...
  1696. SET_FLAG(next->Flags, ASYNC_CONTEXT_FLAG_RANG_DOORBELL);
  1697. Time.QuadPart = (-5*10*1000*1000); // 5 seconds
  1698. KeSetTimer(&next->Timer, Time, &next->TimerDpc);
  1699. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->OrbListSpinLock);
  1700. // reset the timer to track this request...
  1701. // we still have a pending orb, but the device thinks its done.
  1702. // ring the doorbell...
  1703. Sbp2AccessRegister( DeviceExtension,
  1704. &DeviceExtension->Reserved,
  1705. DOORBELL_REG | REG_WRITE_ASYNC
  1706. );
  1707. return;
  1708. }
  1709. if (next->Flags & ASYNC_CONTEXT_FLAG_RANG_DOORBELL) {
  1710. CLEAR_FLAG(next->Flags, ASYNC_CONTEXT_FLAG_RANG_DOORBELL);
  1711. TRACE(TL_1394_INFO, ("Rang Doorbell - didn't work."));
  1712. }
  1713. do {
  1714. current = next;
  1715. if ((&current->TimerDpc == Dpc) && (current->Flags & ASYNC_CONTEXT_FLAG_TIMER_STARTED)) {
  1716. if (TEST_FLAG(current->Flags,ASYNC_CONTEXT_FLAG_COMPLETED)) {
  1717. DEBUGPRINT1(("Sbp2Port: ReqTimeoutDpc: timeout, but req already compl!!\n" ));
  1718. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->OrbListSpinLock);
  1719. return;
  1720. }
  1721. //
  1722. // this is the timed out request
  1723. // do an abort Task Set
  1724. //
  1725. CLEAR_FLAG(current->Flags,ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1726. KeCancelTimer(&current->Timer);
  1727. #if DBG
  1728. xferLen = current->Srb->DataTransferLength;
  1729. cdb[0] = current->Srb->Cdb[0];
  1730. cdb[1] = current->Srb->Cdb[1];
  1731. cdb[2] = current->Srb->Cdb[2];
  1732. cdb[3] = current->Srb->Cdb[3];
  1733. cdb[4] = current->Srb->Cdb[4];
  1734. cdb[5] = current->Srb->Cdb[5];
  1735. #endif
  1736. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->OrbListSpinLock);
  1737. Sbp2CreateRequestErrorLog(DeviceExtension->DeviceObject,current,STATUS_TIMEOUT);
  1738. if (!TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_RESET_IN_PROGRESS)){
  1739. DEBUGPRINT1((
  1740. "Sbp2Port: ReqTimeoutDpc: cdb=x%02x %02x %02x %02x %02x " \
  1741. "%02x, len=x%x\n",
  1742. cdb[0],
  1743. cdb[1],
  1744. cdb[2],
  1745. cdb[3],
  1746. cdb[4],
  1747. cdb[5],
  1748. xferLen
  1749. ));
  1750. Sbp2Reset (DeviceExtension->DeviceObject, FALSE);
  1751. }
  1752. return;
  1753. }
  1754. next = (PASYNC_REQUEST_CONTEXT) current->OrbList.Flink;
  1755. } while ( current != RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Blink,OrbList));
  1756. KeReleaseSpinLockFromDpcLevel(&DeviceExtension->OrbListSpinLock);
  1757. return;
  1758. }
  1759. VOID
  1760. Sbp2Reset(
  1761. PDEVICE_OBJECT DeviceObject,
  1762. BOOLEAN HardReset
  1763. )
  1764. /*++
  1765. Routine Description:
  1766. Used to implement SBP2 high level recovery mechanisms. It will issue an ABORT_TASK_SET if HardReset == FALSE
  1767. otherswise it will issue a RESET_TARGET. Its all done asynchronously and out timer DPC will track the requests
  1768. to check if they timed out...
  1769. Arguments:
  1770. DeviceObject= Sbp2 driver's device object
  1771. HardReset = Type of recovery to perform, TRUE is a target reset, FALSE is an abort task set
  1772. Return Value:
  1773. NTSTATUS
  1774. --*/
  1775. {
  1776. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1777. KIRQL oldIrql;
  1778. NTSTATUS status;
  1779. #if DBG
  1780. ULONG generation;
  1781. #endif
  1782. if ((deviceExtension->DeviceFlags & DEVICE_FLAG_REMOVED) ||
  1783. (deviceExtension->DeviceFlags & DEVICE_FLAG_RECONNECT)) {
  1784. return;
  1785. }
  1786. if (HardReset == TRUE) {
  1787. DEBUGPRINT2(("Sbp2Port: Reset: ext=x%p, do target reset\n", deviceExtension ));
  1788. //
  1789. // Do a target reset
  1790. //
  1791. KeAcquireSpinLock (&deviceExtension->ExtensionDataSpinLock,&oldIrql);
  1792. deviceExtension->TaskOrbContext.TransactionType = TRANSACTION_TARGET_RESET;
  1793. deviceExtension->TaskOrb->OrbInfo.QuadPart = 0;
  1794. deviceExtension->TaskOrb->OrbInfo.u.HighPart |= ORB_NOTIFY_BIT_MASK;
  1795. deviceExtension->TaskOrb->OrbInfo.u.HighPart |= 0x00FF & TRANSACTION_TARGET_RESET;
  1796. deviceExtension->TaskOrb->OrbInfo.u.LowPart =
  1797. deviceExtension->LoginResponse->LengthAndLoginId.u.LowPart; // LOGIN ID
  1798. deviceExtension->TaskOrb->StatusBlockAddress.BusAddress =
  1799. deviceExtension->TaskOrbStatusContext.Address.BusAddress;
  1800. //
  1801. // endian conversion
  1802. //
  1803. octbswap (deviceExtension->TaskOrb->StatusBlockAddress);
  1804. deviceExtension->TaskOrb->OrbInfo.QuadPart =
  1805. bswap(deviceExtension->TaskOrb->OrbInfo.QuadPart);
  1806. //
  1807. // send the task ORB , mark start of reset/abort
  1808. //
  1809. deviceExtension->DeviceFlags |= DEVICE_FLAG_RESET_IN_PROGRESS;
  1810. //
  1811. // now set the timer to track this request
  1812. //
  1813. deviceExtension->DueTime.HighPart = -1;
  1814. deviceExtension->DueTime.LowPart = SBP2_HARD_RESET_TIMEOUT;
  1815. KeSetTimer(&deviceExtension->DeviceManagementTimer,deviceExtension->DueTime,&deviceExtension->DeviceManagementTimeoutDpc);
  1816. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,oldIrql);
  1817. status = Sbp2AccessRegister(deviceExtension, &deviceExtension->TaskOrbContext.Address, MANAGEMENT_AGENT_REG | REG_WRITE_ASYNC);
  1818. if (status == STATUS_INVALID_GENERATION) {
  1819. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  1820. #if DBG
  1821. //
  1822. // Check to see if perhaps we didn't get the reset
  1823. // notification we were expecting
  1824. //
  1825. generation = deviceExtension->CurrentGeneration;
  1826. status = Sbp2UpdateNodeInformation (deviceExtension);
  1827. DEBUGPRINT1((
  1828. "Sbp2Port: Reset: target reset error, sts=x%x, extGen=x%x, " \
  1829. "curGen=x%x\n",
  1830. status,
  1831. generation,
  1832. deviceExtension->CurrentGeneration
  1833. ));
  1834. #endif
  1835. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&oldIrql);
  1836. SET_FLAG(deviceExtension->DeviceFlags, (DEVICE_FLAG_STOPPED | DEVICE_FLAG_DEVICE_FAILED));
  1837. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,oldIrql);
  1838. //
  1839. // check if we had a power irp deferred.. If we did call startio to abort it..
  1840. //
  1841. if (deviceExtension->DeferredPowerRequest) {
  1842. Sbp2StartIo(deviceExtension->DeviceObject,deviceExtension->DeferredPowerRequest);
  1843. deviceExtension->DeferredPowerRequest = NULL;
  1844. }
  1845. Sbp2StartNextPacketByKey (deviceExtension->DeviceObject, 0);
  1846. return;
  1847. }
  1848. } else {
  1849. DEBUGPRINT2(("Sbp2Port: Reset: ext=x%p, do abort task set\n", deviceExtension ));
  1850. //
  1851. // Do an abort task set
  1852. //
  1853. KeAcquireSpinLock (&deviceExtension->ExtensionDataSpinLock,&oldIrql);
  1854. deviceExtension->TaskOrbContext.TransactionType = TRANSACTION_ABORT_TASK_SET;
  1855. deviceExtension->TaskOrb->OrbInfo.QuadPart = 0;
  1856. deviceExtension->TaskOrb->OrbInfo.u.HighPart |= ORB_NOTIFY_BIT_MASK;
  1857. deviceExtension->TaskOrb->OrbInfo.u.HighPart |= 0x00FF & TRANSACTION_ABORT_TASK_SET;
  1858. deviceExtension->TaskOrb->OrbInfo.u.LowPart =
  1859. deviceExtension->LoginResponse->LengthAndLoginId.u.LowPart; // LOGIN ID
  1860. deviceExtension->TaskOrb->StatusBlockAddress.BusAddress =
  1861. deviceExtension->TaskOrbStatusContext.Address.BusAddress;
  1862. //
  1863. // endian conversion
  1864. //
  1865. octbswap (deviceExtension->TaskOrb->StatusBlockAddress);
  1866. deviceExtension->TaskOrb->OrbInfo.QuadPart =
  1867. bswap (deviceExtension->TaskOrb->OrbInfo.QuadPart);
  1868. //
  1869. // send the task ORB , mark start of reset/abort
  1870. //
  1871. deviceExtension->DeviceFlags |= DEVICE_FLAG_RESET_IN_PROGRESS;
  1872. //
  1873. // now set the timer to track this request
  1874. //
  1875. deviceExtension->DueTime.HighPart = -1;
  1876. deviceExtension->DueTime.LowPart = SBP2_RESET_TIMEOUT;
  1877. KeSetTimer(&deviceExtension->DeviceManagementTimer,deviceExtension->DueTime,&deviceExtension->DeviceManagementTimeoutDpc);
  1878. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,oldIrql);
  1879. Sbp2AccessRegister(deviceExtension, &deviceExtension->TaskOrbContext.Address, MANAGEMENT_AGENT_REG | REG_WRITE_ASYNC);
  1880. }
  1881. }
  1882. NTSTATUS
  1883. Sbp2DeviceControl(
  1884. IN PDEVICE_OBJECT DeviceObject,
  1885. IN PIRP Irp
  1886. )
  1887. /*++
  1888. Routine Description:
  1889. This routine is the device control dispatcher.
  1890. Arguments:
  1891. DeviceObject
  1892. Irp
  1893. Return Value:
  1894. NTSTATUS
  1895. --*/
  1896. {
  1897. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1898. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1899. NTSTATUS status;
  1900. ULONG requiredSize;
  1901. if (deviceExtension->Type == SBP2_PDO) {
  1902. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  1903. case IOCTL_STORAGE_QUERY_PROPERTY: {
  1904. //
  1905. // Validate the query
  1906. //
  1907. PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
  1908. if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
  1909. sizeof(STORAGE_PROPERTY_QUERY)) {
  1910. status = STATUS_INVALID_PARAMETER;
  1911. break;
  1912. }
  1913. status = Sbp2QueryProperty(DeviceObject, Irp);
  1914. break;
  1915. }
  1916. case IOCTL_SCSI_PASS_THROUGH:
  1917. status = Sbp2_ScsiPassThrough(DeviceObject, Irp, FALSE);
  1918. break;
  1919. case IOCTL_SCSI_PASS_THROUGH_DIRECT:
  1920. status = Sbp2_ScsiPassThrough(DeviceObject, Irp, TRUE);
  1921. break;
  1922. case IOCTL_SBP2_REQUEST:
  1923. status = Sbp2HandleApiRequest(deviceExtension, Irp);
  1924. break;
  1925. default:
  1926. DEBUGPRINT3(("Sbp2Port: Sbp2DeviceControl: Irp Not Handled.\n" ));
  1927. status = STATUS_NOT_SUPPORTED;
  1928. Irp->IoStatus.Status =status;
  1929. Irp->IoStatus.Information = 0;
  1930. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  1931. break;
  1932. }
  1933. } else {
  1934. status = STATUS_NOT_SUPPORTED;
  1935. Irp->IoStatus.Status =status;
  1936. Irp->IoStatus.Information = 0;
  1937. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  1938. }
  1939. return status;
  1940. }
  1941. NTSTATUS
  1942. Sbp2HandleApiRequest(
  1943. IN PDEVICE_EXTENSION DeviceExtension,
  1944. IN PIRP Irp
  1945. )
  1946. {
  1947. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1948. PSBP2_REQUEST sbp2Req;
  1949. NTSTATUS status;
  1950. status = IoAcquireRemoveLock (&DeviceExtension->RemoveLock, NULL);
  1951. if (!NT_SUCCESS (status)) {
  1952. Irp->IoStatus.Status = status;
  1953. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  1954. return status;
  1955. }
  1956. if (Irp->RequestorMode == KernelMode) {
  1957. sbp2Req = irpStack->Parameters.Others.Argument1;
  1958. } else { // UserMode
  1959. sbp2Req = Irp->AssociatedIrp.SystemBuffer;
  1960. }
  1961. if (sbp2Req == NULL) {
  1962. DEBUGPRINT1(("Sbp2Port: HandleApiReq: Invalid sbp2Req!"));
  1963. status = STATUS_INVALID_PARAMETER;
  1964. goto Exit_Sbp2HandleApiRequest;
  1965. }
  1966. status = STATUS_NOT_IMPLEMENTED;
  1967. switch (sbp2Req->RequestNumber) {
  1968. case SBP2_REQUEST_RETRIEVE_TEXT_LEAFS:
  1969. //
  1970. // Only allow kernel-mode requests of this type, since the
  1971. // RetrieveTextLeaf definition currently has us passing
  1972. // back a buf alloc'd via ExAllocPool - not something we
  1973. // want to hand back to user-mode.
  1974. //
  1975. if (Irp->RequestorMode == KernelMode) {
  1976. status = Sbp2Get1394ConfigInfo(
  1977. (PFDO_DEVICE_EXTENSION)
  1978. DeviceExtension->BusFdo->DeviceExtension,
  1979. sbp2Req
  1980. );
  1981. }
  1982. break;
  1983. #if PASSWORD_SUPPORT
  1984. case SBP2_REQUEST_SET_PASSWORD:
  1985. if (sbp2Req->u.SetPassword.fulFlags == SBP2REQ_SET_PASSWORD_CLEAR) {
  1986. DEBUGPRINT1(("Sbp2Port: Setting Password to Clear\n"));
  1987. status = Sbp2SetPasswordTransaction(
  1988. DeviceExtension,
  1989. SBP2REQ_SET_PASSWORD_CLEAR
  1990. );
  1991. if (NT_SUCCESS(status)) {
  1992. DeviceExtension->Exclusive = EXCLUSIVE_FLAG_CLEAR;
  1993. }
  1994. } else if (sbp2Req->u.SetPassword.fulFlags ==
  1995. SBP2REQ_SET_PASSWORD_EXCLUSIVE) {
  1996. DEBUGPRINT1 (("Sbp2Port: HandleApiReq: set passwd to excl\n"));
  1997. status = Sbp2SetPasswordTransaction(
  1998. DeviceExtension,
  1999. SBP2REQ_SET_PASSWORD_EXCLUSIVE
  2000. );
  2001. if (NT_SUCCESS(status)) {
  2002. DeviceExtension->Exclusive = EXCLUSIVE_FLAG_SET;
  2003. }
  2004. } else {
  2005. DEBUGPRINT1((
  2006. "Sbp2Port: HandleApiReq: set passwd, inval fl=x%x\n",
  2007. sbp2Req->u.SetPassword.fulFlags
  2008. ));
  2009. status = STATUS_INVALID_PARAMETER;
  2010. goto Exit_Sbp2HandleApiRequest;
  2011. }
  2012. Sbp2SetExclusiveValue(
  2013. DeviceExtension->DeviceObject,
  2014. &DeviceExtension->Exclusive
  2015. );
  2016. DEBUGPRINT1((
  2017. "Sbp2Port: HandleApiReq: set passwd sts=x%x\n",
  2018. status
  2019. ));
  2020. break;
  2021. #endif
  2022. default:
  2023. status = STATUS_INVALID_PARAMETER;
  2024. break;
  2025. }
  2026. Exit_Sbp2HandleApiRequest:
  2027. Irp->IoStatus.Status = status;
  2028. IoReleaseRemoveLock (&DeviceExtension->RemoveLock, NULL);
  2029. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  2030. return status;
  2031. }
  2032. NTSTATUS
  2033. Sbp2CreateClose(
  2034. IN PDEVICE_OBJECT DeviceObject,
  2035. IN PIRP Irp
  2036. )
  2037. /*++
  2038. Routine Description:
  2039. create and close routine. This is called by the I/O system
  2040. when the device is opened or closed. The sbp2 driver will do login and logout on
  2041. create/close respectively
  2042. Arguments:
  2043. DeviceObject - Pointer to device object for this miniport
  2044. Irp - IRP involved.
  2045. Return Value:
  2046. STATUS_SUCCESS.
  2047. --*/
  2048. {
  2049. NTSTATUS status = STATUS_SUCCESS;
  2050. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  2051. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2052. if (deviceExtension->Type == SBP2_PDO) {
  2053. if ((deviceExtension->InquiryData.DeviceType == PRINTER_DEVICE) ||
  2054. (deviceExtension->InquiryData.DeviceType == SCANNER_DEVICE)){
  2055. if (!(deviceExtension->DeviceFlags & DEVICE_FLAG_INITIALIZING)) {
  2056. status = IoAcquireRemoveLock(
  2057. &deviceExtension->RemoveLock,
  2058. NULL
  2059. );
  2060. if (!NT_SUCCESS (status)) {
  2061. goto Sbp2CreateClose_CompleteReq;
  2062. }
  2063. switch (irpStack->MajorFunction) {
  2064. case IRP_MJ_CREATE:
  2065. DEBUGPRINT2(("Sbp2Port: Sbp2CreateClose: OPEN_REQUEST, handle cound %d.\n", deviceExtension->HandleCount));
  2066. if (deviceExtension->DeviceFlags & DEVICE_FLAG_STOPPED) {
  2067. //
  2068. // do a login.
  2069. //
  2070. DEBUGPRINT2(("Sbp2Port: Sbp2CreateClose: LOGIN.\n" ));
  2071. status = Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGIN);
  2072. if (status == STATUS_SUCCESS) {
  2073. //
  2074. // make retry limit high for busy transactions
  2075. //
  2076. deviceExtension->Reserved = BUSY_TIMEOUT_SETTING;
  2077. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,CORE_BUSY_TIMEOUT_REG | REG_WRITE_SYNC);
  2078. //
  2079. // We are ready to receive and pass down requests, init the target's
  2080. // fetch agent.
  2081. //
  2082. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,AGENT_RESET_REG | REG_WRITE_ASYNC);
  2083. deviceExtension->DeviceFlags &= ~DEVICE_FLAG_STOPPED;
  2084. InterlockedIncrement(&deviceExtension->HandleCount);
  2085. }
  2086. } else {
  2087. InterlockedIncrement(&deviceExtension->HandleCount);
  2088. }
  2089. break;
  2090. case IRP_MJ_CLOSE:
  2091. if (deviceExtension->HandleCount) {
  2092. InterlockedDecrement(&deviceExtension->HandleCount);
  2093. }
  2094. DEBUGPRINT2(("Sbp2Port: Sbp2CreateClose: CLOSE_REQUEST, handle cound %d.\n", deviceExtension->HandleCount));
  2095. if (!(deviceExtension->DeviceFlags & (DEVICE_FLAG_REMOVED | DEVICE_FLAG_STOPPED)) &&
  2096. !deviceExtension->HandleCount) {
  2097. //
  2098. // Logout
  2099. //
  2100. DEBUGPRINT2(("Sbp2Port: Sbp2CreateClose: LOGIN OUT.\n" ));
  2101. deviceExtension->DeviceFlags |= DEVICE_FLAG_STOPPED;
  2102. Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGOUT);
  2103. CleanupOrbList(deviceExtension,STATUS_REQUEST_ABORTED);
  2104. }
  2105. break;
  2106. }
  2107. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  2108. }
  2109. } // device type check
  2110. } else if (deviceExtension->Type != SBP2_FDO) {
  2111. status = STATUS_NO_SUCH_DEVICE;
  2112. }
  2113. Sbp2CreateClose_CompleteReq:
  2114. Irp->IoStatus.Status = status;
  2115. Irp->IoStatus.Information = 0;
  2116. IoCompleteRequest(Irp, 0);
  2117. return status;
  2118. }
  2119. NTSTATUS
  2120. Sbp2PnpDeviceControl(
  2121. PDEVICE_OBJECT DeviceObject,
  2122. PIRP Irp
  2123. )
  2124. /*++
  2125. Routine Description:
  2126. This routine handles the PNP requests (primarily for PDO's)
  2127. Arguments:
  2128. DeviceObject - Supplies a pointer to the device object for this request.
  2129. Irp - Supplies the Irp making the request.
  2130. Return Value:
  2131. NTSTATUS
  2132. --*/
  2133. {
  2134. KIRQL cIrql;
  2135. PULONG count;
  2136. NTSTATUS status;
  2137. UNICODE_STRING unicodeIdString;
  2138. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2139. PDEVICE_RELATIONS deviceRelations;
  2140. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
  2141. PDEVICE_CAPABILITIES deviceCapabilities;
  2142. PFDO_DEVICE_EXTENSION fdoExtension;
  2143. #if DBG
  2144. const char * minorFuncs[] =
  2145. {
  2146. "START_DEV, ",
  2147. "QUERY_REMOVE_DEV, ",
  2148. "REMOVE_DEV, ",
  2149. "CANCEL_REMOVE_DEV, ",
  2150. "STOP_DEV, ",
  2151. "QUERY_STOP_DEV, ",
  2152. "CANCEL_STOP_DEV, ",
  2153. "QUERY_DEV_RELATIONS, ",
  2154. "QUERY_INTERFACE, ",
  2155. "QUERY_CAPABILITIES, ",
  2156. "QUERY_RESOURCES, ",
  2157. "QUERY_RESOURCE_REQS, ",
  2158. "QUERY_DEV_TEXT, ",
  2159. "FILTER_RESOURCE_REQS,",
  2160. "??, ", // 0xd (14)
  2161. "READ_CFG, ",
  2162. "WRITE_CFG, ",
  2163. "EJECT, ",
  2164. "SET_LOCK, ",
  2165. "QUERY_ID, ",
  2166. "QUERY_PNP_DEV_STATE, ",
  2167. "QUERY_BUS_INFO, ",
  2168. "DEV_USAGE_NOTIF, ",
  2169. "SURPRISE_REMOVAL, ",
  2170. "QUERY_LEG_BUS_INFO, " // 0x18
  2171. };
  2172. DEBUGPRINT2((
  2173. "Sbp2Port: Pnp: [x%02x] %s %sdoX=x%p, fl=x%x\n",
  2174. irpStack->MinorFunction,
  2175. (irpStack->MinorFunction <= 0x18 ?
  2176. minorFuncs[irpStack->MinorFunction] : minorFuncs[14]),
  2177. (deviceExtension->Type == SBP2_PDO ? "p" :
  2178. (deviceExtension->Type == SBP2_FDO ? "f" : "???")),
  2179. deviceExtension,
  2180. deviceExtension->DeviceFlags
  2181. ));
  2182. #endif
  2183. //
  2184. // We may receive an IRP_MN_BUS_RESET before our AddDevice
  2185. // has completed. Check to make sure our DeviceObject is
  2186. // initialized before we allow processing of PNP Irps.
  2187. //
  2188. if (DeviceObject->Flags & DO_DEVICE_INITIALIZING) {
  2189. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  2190. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2191. return(STATUS_NO_SUCH_DEVICE);
  2192. }
  2193. switch (deviceExtension->Type) {
  2194. case SBP2_PDO:
  2195. break;
  2196. case SBP2_FDO:
  2197. return Sbp2FDOPnpDeviceControl (DeviceObject, Irp);
  2198. default:
  2199. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  2200. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  2201. return STATUS_NO_SUCH_DEVICE;
  2202. }
  2203. status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, NULL);
  2204. if (!NT_SUCCESS (status)) {
  2205. Irp->IoStatus.Status = status;
  2206. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  2207. return status;
  2208. }
  2209. switch (irpStack->MinorFunction) {
  2210. case IRP_MN_QUERY_DEVICE_RELATIONS:
  2211. DEBUGPRINT3((
  2212. "Sbp2Port: Pnp: ... Type = %x\n",
  2213. irpStack->Parameters.QueryDeviceRelations.Type
  2214. ));
  2215. //
  2216. // Fill in the DeviceRelations array with this PDO,
  2217. // reference it, and return.
  2218. //
  2219. if (irpStack->Parameters.QueryDeviceRelations.Type !=
  2220. TargetDeviceRelation) {
  2221. status = Irp->IoStatus.Status;
  2222. break;
  2223. }
  2224. if (Irp->IoStatus.Information) {
  2225. deviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
  2226. } else {
  2227. deviceRelations = ExAllocatePool(
  2228. PagedPool,
  2229. sizeof (*deviceRelations)
  2230. );
  2231. if (!deviceRelations) {
  2232. Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
  2233. Irp->IoStatus.Information = 0;
  2234. break;
  2235. }
  2236. deviceRelations->Count = 0;
  2237. }
  2238. deviceRelations->Objects[deviceRelations->Count] = DeviceObject;
  2239. deviceRelations->Count++;
  2240. ObReferenceObject (DeviceObject);
  2241. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2242. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  2243. break;
  2244. case IRP_MN_QUERY_DEVICE_TEXT:
  2245. {
  2246. PDEVICE_INFORMATION DeviceInfo = deviceExtension->DeviceInfo;
  2247. UNICODE_STRING uniRetString;
  2248. // assume success
  2249. status = STATUS_SUCCESS;
  2250. if ((irpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) ||
  2251. (irpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextLocationInformation)) {
  2252. status = Sbp2_BuildDeviceText( irpStack->Parameters.QueryDeviceText.DeviceTextType,
  2253. DeviceInfo,
  2254. &uniRetString
  2255. );
  2256. Irp->IoStatus.Information = (ULONG_PTR)uniRetString.Buffer;
  2257. TRACE(TL_PNP_INFO, ("DeviceText = %ws", uniRetString.Buffer));
  2258. }
  2259. else {
  2260. status = STATUS_NOT_SUPPORTED;
  2261. }
  2262. Irp->IoStatus.Status = status;
  2263. }
  2264. break;
  2265. case IRP_MN_QUERY_ID:
  2266. {
  2267. PDEVICE_INFORMATION DeviceInfo = deviceExtension->DeviceInfo;
  2268. UNICODE_STRING uniRetString;
  2269. TRACE(TL_PNP_TRACE, ("PDO: IRP_MN_QUERY_ID"));
  2270. // assume success
  2271. status = STATUS_SUCCESS;
  2272. Irp->IoStatus.Information = (ULONG_PTR)NULL;
  2273. switch (irpStack->Parameters.QueryId.IdType) {
  2274. case BusQueryDeviceID:
  2275. TRACE(TL_PNP_TRACE, ("BusQueryDeviceID"));
  2276. // build our DeviceId
  2277. status = Sbp2_BuildDeviceId(DeviceInfo, &uniRetString);
  2278. if (!NT_SUCCESS(status)) {
  2279. TRACE(TL_PNP_ERROR, ("Failed to build DeviceId! = 0x%x", status));
  2280. }
  2281. else {
  2282. Irp->IoStatus.Information = (ULONG_PTR)uniRetString.Buffer;
  2283. TRACE(TL_PNP_TRACE, ("DeviceID = %ws", uniRetString.Buffer));
  2284. }
  2285. break; // BusQueryDeviceID
  2286. case BusQueryHardwareIDs:
  2287. TRACE(TL_PNP_TRACE, ("BusQueryHardwareIDs"));
  2288. // build our HardwareIds
  2289. status = Sbp2_BuildHardwareIds(DeviceInfo, &uniRetString);
  2290. if (!NT_SUCCESS(status)) {
  2291. TRACE(TL_PNP_ERROR, ("Failed to build HardwareIds! = 0x%x", status));
  2292. }
  2293. else {
  2294. Irp->IoStatus.Information = (ULONG_PTR)uniRetString.Buffer;
  2295. TRACE(TL_PNP_TRACE, ("HardwareIds = %ws", uniRetString.Buffer));
  2296. }
  2297. break; // BusQueryHardwareIDs
  2298. case BusQueryCompatibleIDs:
  2299. TRACE(TL_PNP_TRACE, ("BusQueryCompatibleIDs"));
  2300. // build our CompatIds
  2301. status = Sbp2_BuildCompatIds(DeviceInfo, &uniRetString);
  2302. if (!NT_SUCCESS(status)) {
  2303. TRACE(TL_1394_ERROR, ("Failed to build CompatIds! = 0x%x", status));
  2304. }
  2305. else {
  2306. Irp->IoStatus.Information = (ULONG_PTR)uniRetString.Buffer;
  2307. TRACE(TL_PNP_TRACE, ("CompatIds = %ws", uniRetString.Buffer));
  2308. }
  2309. break; // BusQueryCompatibleIDs
  2310. case BusQueryInstanceID:
  2311. // if (BusExtension->Tag == BUS_DEVICE_TAG) {
  2312. TRACE(TL_PNP_TRACE, ("BusQueryInstanceID"));
  2313. // build our InstanceId
  2314. status = Sbp2_BuildInstanceId(DeviceInfo, &uniRetString);
  2315. if (!NT_SUCCESS(status)) {
  2316. TRACE(TL_1394_ERROR, ("Failed to build InstanceId! = 0x%x", status));
  2317. }
  2318. else {
  2319. Irp->IoStatus.Information = (ULONG_PTR)uniRetString.Buffer;
  2320. TRACE(TL_PNP_TRACE, ("InstanceID = %ws", uniRetString.Buffer));
  2321. }
  2322. // }
  2323. // else {
  2324. //
  2325. // // let 1394bus deal with it...
  2326. // IoSkipCurrentIrpStackLocation(Irp);
  2327. // status = IoCallDriver(BusExtension->ParentDeviceObject, Irp);
  2328. // return(status); // default
  2329. // }
  2330. break; // BusQueryCompatibleIDs
  2331. default:
  2332. TRACE(TL_PNP_WARNING, ("Unsupported IRP_MN_QUERY_ID"));
  2333. // set status to avoid changing the current IoStatus
  2334. status = Irp->IoStatus.Status;
  2335. break; // default
  2336. } // switch
  2337. }
  2338. Irp->IoStatus.Status = status;
  2339. break; // IRP_MN_QUERY_ID
  2340. case IRP_MN_QUERY_CAPABILITIES:
  2341. deviceCapabilities =
  2342. irpStack->Parameters.DeviceCapabilities.Capabilities;
  2343. //
  2344. // Settings consistent across all 1394 devices
  2345. //
  2346. deviceCapabilities->Removable = TRUE;
  2347. deviceCapabilities->UniqueID = TRUE;
  2348. deviceCapabilities->SilentInstall = TRUE;
  2349. //
  2350. // Settings for different types of devices. We are very
  2351. // familar with SCSI-variant devices and can make some
  2352. // good choices here, but for other devices we'll leave
  2353. // these choices up to the higher-level driver(s).
  2354. //
  2355. switch (deviceExtension->DeviceInfo->CmdSetId.QuadPart) {
  2356. case 0x10483:
  2357. case SCSI_COMMAND_SET_ID:
  2358. switch ((deviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F)) {
  2359. case PRINTER_DEVICE:
  2360. case SCANNER_DEVICE:
  2361. deviceCapabilities->RawDeviceOK = FALSE;
  2362. deviceCapabilities->SurpriseRemovalOK = TRUE;
  2363. break;
  2364. default:
  2365. deviceCapabilities->RawDeviceOK = TRUE;
  2366. break;
  2367. }
  2368. break;
  2369. default:
  2370. break;
  2371. }
  2372. deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  2373. deviceCapabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
  2374. deviceCapabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
  2375. deviceCapabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  2376. deviceCapabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  2377. deviceCapabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
  2378. deviceCapabilities->SystemWake = PowerSystemUnspecified;
  2379. deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  2380. deviceCapabilities->D1Latency = 1 * (1000 * 10); // 1 sec
  2381. deviceCapabilities->D2Latency = 1 * (1000 * 10); // 1
  2382. deviceCapabilities->D3Latency = 1 * (1000 * 10); // 1
  2383. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2384. Irp->IoStatus.Information = 0;
  2385. break;
  2386. case IRP_MN_START_DEVICE:
  2387. status = Sbp2StartDevice (DeviceObject);
  2388. Irp->IoStatus.Status = status;
  2389. break;
  2390. case IRP_MN_CANCEL_STOP_DEVICE:
  2391. case IRP_MN_QUERY_STOP_DEVICE:
  2392. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2393. break;
  2394. case IRP_MN_STOP_DEVICE:
  2395. //
  2396. // Disable bus reset notifications
  2397. //
  2398. Sbp2EnableBusResetNotification (deviceExtension, FALSE);
  2399. //
  2400. // disable idle detection
  2401. //
  2402. PoRegisterDeviceForIdleDetection (DeviceObject, 0L, 0L, PowerDeviceD3);
  2403. //
  2404. // Cleanup
  2405. //
  2406. KeAcquireSpinLock (&deviceExtension->ExtensionDataSpinLock, &cIrql);
  2407. if (!TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED)) {
  2408. SET_FLAG(
  2409. deviceExtension->DeviceFlags,
  2410. (DEVICE_FLAG_PNP_STOPPED | DEVICE_FLAG_STOPPED)
  2411. );
  2412. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2413. fdoExtension = (PFDO_DEVICE_EXTENSION)
  2414. deviceExtension->BusFdo->DeviceExtension;
  2415. ASSERT(!fdoExtension->ulWorkItemCount);
  2416. ExAcquireFastMutex(&fdoExtension->ResetMutex);
  2417. Sbp2ManagementTransaction (deviceExtension,TRANSACTION_LOGOUT);
  2418. ExReleaseFastMutex(&fdoExtension->ResetMutex);
  2419. Sbp2CleanDeviceExtension (DeviceObject,FALSE);
  2420. } else {
  2421. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_PNP_STOPPED);
  2422. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2423. }
  2424. Irp->IoStatus.Status = status = STATUS_SUCCESS;
  2425. ASSERT(!deviceExtension->ulPendingEvents);
  2426. ASSERT(!deviceExtension->ulInternalEventCount);
  2427. break;
  2428. case IRP_MN_BUS_RESET:
  2429. //
  2430. // Start of a PHY reset. We will re-connect asynchronously to the
  2431. // target when our callback is called, so this is ignored..
  2432. //
  2433. // After a bus reset is complete, the bus driver should call our
  2434. // BusResetNotification callback. When it does, we will attempt
  2435. // to reconnect. If the reconnect completion status callback,
  2436. // never fires, it means the following things:
  2437. //
  2438. // 1) The device never completed the RECONNECT, or
  2439. // 2) The device completed the reconnect but because our
  2440. // controlller was BUSY or hosed we didnt get it
  2441. //
  2442. // If 1 or 2 happens, the timeout DPC queued in our bus reset
  2443. // notification, should fire and attempt a relogin...
  2444. //
  2445. Irp->IoStatus.Status = status = STATUS_SUCCESS;
  2446. break;
  2447. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  2448. if (TEST_FLAG(
  2449. deviceExtension->DeviceFlags,
  2450. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_DEVICE_FAILED)
  2451. ) &&
  2452. !TEST_FLAG(
  2453. deviceExtension->DeviceFlags,
  2454. DEVICE_FLAG_RESET_IN_PROGRESS
  2455. )){
  2456. //
  2457. // Set DEVICE_FLAG_REPORTED_FAILED so the SURPRISE_REMOVE
  2458. // handler knows it didn't get called because of physical
  2459. // hardware removal
  2460. //
  2461. KeAcquireSpinLock (&deviceExtension->ExtensionDataSpinLock,&cIrql);
  2462. SET_FLAG(
  2463. deviceExtension->DeviceFlags,
  2464. DEVICE_FLAG_REPORTED_FAILED
  2465. );
  2466. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2467. //
  2468. // indicate our device is disabled due to a failure..
  2469. //
  2470. Irp->IoStatus.Information |= PNP_DEVICE_FAILED;
  2471. DEBUGPRINT2((
  2472. "Sbp2Port: Pnp: QUERY_DEVICE_STATE, device FAILED!!!\n"
  2473. ));
  2474. }
  2475. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2476. break;
  2477. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  2478. switch (irpStack->Parameters.UsageNotification.Type) {
  2479. case DeviceUsageTypePaging:
  2480. count = &deviceExtension->PagingPathCount;
  2481. break;
  2482. case DeviceUsageTypeHibernation:
  2483. count = &deviceExtension->HibernateCount;
  2484. break;
  2485. default:
  2486. count = NULL;
  2487. break;
  2488. }
  2489. if (count) {
  2490. //
  2491. // Send the irp down to see what everyone else thinks
  2492. //
  2493. status = Sbp2ForwardIrpSynchronous(deviceExtension->LowerDeviceObject, Irp);
  2494. if (NT_SUCCESS(status)) {
  2495. IoAdjustPagingPathCount(count, irpStack->Parameters.UsageNotification.InPath);
  2496. }
  2497. } else {
  2498. status = STATUS_NOT_SUPPORTED;
  2499. }
  2500. Irp->IoStatus.Status = status;
  2501. break;
  2502. case IRP_MN_QUERY_REMOVE_DEVICE:
  2503. if (deviceExtension->PagingPathCount ||
  2504. deviceExtension->HibernateCount ||
  2505. deviceExtension->CrashDumpCount) {
  2506. status = Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  2507. } else {
  2508. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  2509. SET_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_REMOVE_PENDING);
  2510. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  2511. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2512. }
  2513. break;
  2514. case IRP_MN_CANCEL_REMOVE_DEVICE:
  2515. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  2516. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_REMOVE_PENDING);
  2517. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  2518. status = Irp->IoStatus.Status = STATUS_SUCCESS;
  2519. break;
  2520. case IRP_MN_REMOVE_DEVICE:
  2521. status = STATUS_SUCCESS;
  2522. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  2523. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_PNP_STOPPED);
  2524. if (TEST_FLAG(
  2525. deviceExtension->DeviceFlags,
  2526. DEVICE_FLAG_SURPRISE_REMOVED
  2527. )) {
  2528. //
  2529. // We already cleaned up in SURPRISE_REMOVAL handler.
  2530. // Empty out the queue, wait for io to complete, then
  2531. // delete the device, complete the request, & return.
  2532. //
  2533. KeReleaseSpinLock(
  2534. &deviceExtension->ExtensionDataSpinLock,
  2535. cIrql
  2536. );
  2537. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  2538. Sbp2StartNextPacketByKey (DeviceObject, 0);
  2539. KeLowerIrql (cIrql);
  2540. DEBUGPRINT2((
  2541. "Sbp2Port: Pnp: wait for io compl pdo=x%p...\n",
  2542. DeviceObject
  2543. ));
  2544. IoReleaseRemoveLockAndWait (&deviceExtension->RemoveLock, NULL);
  2545. deviceExtension->Type = SBP2_PDO_DELETED;
  2546. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  2547. IoDeleteDevice (DeviceObject);
  2548. DEBUGPRINT2((
  2549. "Sbp2Port: Pnp: ......... deleted pdo=x%p\n", DeviceObject
  2550. ));
  2551. Irp->IoStatus.Status = status;
  2552. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2553. return status;
  2554. }
  2555. if (TEST_FLAG(
  2556. deviceExtension->DeviceFlags,
  2557. DEVICE_FLAG_REMOVE_PENDING
  2558. )) {
  2559. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2560. //
  2561. // If device is initialized & MgmtOrbCtx event is still around
  2562. // then do a log out
  2563. //
  2564. if (TEST_FLAG(
  2565. deviceExtension->DeviceFlags,
  2566. DEVICE_FLAG_INITIALIZED
  2567. )) {
  2568. DEBUGPRINT1((
  2569. "Sbp2Port: Pnp: LOG OUT, since QUERY preceded RMV\n"
  2570. ));
  2571. fdoExtension = (PFDO_DEVICE_EXTENSION)
  2572. deviceExtension->BusFdo->DeviceExtension;
  2573. ExAcquireFastMutex(&fdoExtension->ResetMutex);
  2574. Sbp2ManagementTransaction(deviceExtension,TRANSACTION_LOGOUT);
  2575. ExReleaseFastMutex(&fdoExtension->ResetMutex);
  2576. }
  2577. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  2578. CLEAR_FLAG(
  2579. deviceExtension->DeviceFlags,
  2580. DEVICE_FLAG_REMOVE_PENDING
  2581. );
  2582. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  2583. } else if (!TEST_FLAG(
  2584. deviceExtension->DeviceFlags,
  2585. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_DEVICE_FAILED)
  2586. )){
  2587. //
  2588. // If no query has preceded and NO SUPRISE_REMOVAL has preceded
  2589. // this means we are running under win98, where physical device
  2590. // removals are only indicated by only MN_REMOVES being sent,
  2591. // with no QUERY_REMOVE prior to the remove.
  2592. //
  2593. if (deviceExtension->DeviceFlags ==
  2594. (DEVICE_FLAG_INITIALIZING | DEVICE_FLAG_STOPPED) &&
  2595. !SystemIsNT) {
  2596. DEBUGPRINT1((
  2597. "Sbp2Port: Pnp: 9x REMOVE, don't delete dev\n"
  2598. ));
  2599. deviceExtension->DeviceFlags =
  2600. DEVICE_FLAG_UNSTARTED_AND_REMOVED;
  2601. } else {
  2602. SET_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED);
  2603. CLEAR_FLAG(
  2604. deviceExtension->DeviceFlags,
  2605. DEVICE_FLAG_RESET_IN_PROGRESS | DEVICE_FLAG_RECONNECT |
  2606. DEVICE_FLAG_LOGIN_IN_PROGRESS
  2607. );
  2608. DEBUGPRINT1((
  2609. "Sbp2Port: Pnp: Suprise removal, since QUERY " \
  2610. "did not precede REMOVE.\n"
  2611. ));
  2612. }
  2613. }
  2614. CLEAR_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_CLAIMED);
  2615. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2616. if (!Sbp2CleanDeviceExtension (DeviceObject, TRUE)) {
  2617. DEBUGPRINT1(("Sbp2Port: Pnp: Double remove\n"));
  2618. }
  2619. //
  2620. // In all cases other than surprise removals, pdo's will get
  2621. // deleted by the fdo remove handler
  2622. //
  2623. Irp->IoStatus.Status = status;
  2624. break;
  2625. case IRP_MN_SURPRISE_REMOVAL: {
  2626. //
  2627. // If device was reported failed (due to async login failure &
  2628. // IoInvalidateDeviceState) then just set REMOVED & PNP_STOPPED
  2629. // flags and clean up the device extension - we don't want to
  2630. // delete the pdo at this point.
  2631. //
  2632. // Otherwise, assume physical device removal occured, in which
  2633. // case we need to do our own cleanup & teardown right here
  2634. // because the dev stack will start disintegrating.
  2635. //
  2636. // ISSUE: Per AdriaO, another case where we can get a
  2637. // SURPRISE_REMOVAL is if a START fails *after* a STOP
  2638. // - at any point in this pdo's stack! Not sure how to
  2639. // tell whether or not this is the case if it's not
  2640. // SBP2PORT that failed the START, so leaving that case
  2641. // as is for now. DanKn, 04-Jun-2001
  2642. //
  2643. BOOLEAN reportedMissing;
  2644. KeAcquireSpinLock (&deviceExtension->ExtensionDataSpinLock, &cIrql);
  2645. if (TEST_FLAG(
  2646. deviceExtension->DeviceFlags,
  2647. DEVICE_FLAG_REPORTED_FAILED
  2648. )) {
  2649. SET_FLAG(
  2650. deviceExtension->DeviceFlags,
  2651. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_PNP_STOPPED)
  2652. );
  2653. reportedMissing = FALSE;
  2654. } else {
  2655. SET_FLAG(
  2656. deviceExtension->DeviceFlags,
  2657. (DEVICE_FLAG_REMOVED | DEVICE_FLAG_SURPRISE_REMOVED |
  2658. DEVICE_FLAG_PNP_STOPPED)
  2659. );
  2660. reportedMissing = TRUE;
  2661. }
  2662. CLEAR_FLAG(
  2663. deviceExtension->DeviceFlags,
  2664. (DEVICE_FLAG_RESET_IN_PROGRESS | DEVICE_FLAG_RECONNECT |
  2665. DEVICE_FLAG_LOGIN_IN_PROGRESS | DEVICE_FLAG_REPORTED_FAILED)
  2666. );
  2667. KeReleaseSpinLock (&deviceExtension->ExtensionDataSpinLock, cIrql);
  2668. Sbp2CleanDeviceExtension (DeviceObject, TRUE);
  2669. if (reportedMissing) {
  2670. Sbp2HandleRemove (DeviceObject);
  2671. }
  2672. Irp->IoStatus.Status = STATUS_SUCCESS;
  2673. break;
  2674. }
  2675. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  2676. //
  2677. // PnP walks up the device tree looking for the FILE_CHAR flags,
  2678. // and stops when it finds a node marked Removable. Since our pdo's
  2679. // are marked Removable, PnP won't make it to a BUS1394 PDO, so we
  2680. // need to propagate the FILE_CHAR flags here.
  2681. //
  2682. fdoExtension = (PFDO_DEVICE_EXTENSION)
  2683. deviceExtension->BusFdo->DeviceExtension;
  2684. DeviceObject->Characteristics |=
  2685. (FILE_CHARACTERISTICS_REMOVAL_POLICY_MASK &
  2686. fdoExtension->Pdo->Characteristics);
  2687. status = Irp->IoStatus.Status;
  2688. break;
  2689. default:
  2690. status = Irp->IoStatus.Status;
  2691. break;
  2692. }
  2693. //
  2694. // This is the bottom of the stack, complete the request
  2695. //
  2696. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  2697. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2698. return status;
  2699. }
  2700. NTSTATUS
  2701. Sbp2FDOPnpDeviceControl(
  2702. PDEVICE_OBJECT DeviceObject,
  2703. PIRP Irp
  2704. )
  2705. /*++
  2706. Routine Description:
  2707. This routine handles the PNP requests for FDO's
  2708. Arguments:
  2709. DeviceObject - Supplies a pointer to the device object for this request.
  2710. Irp - Supplies the Irp making the request.
  2711. Return Value:
  2712. NTSTATUS
  2713. --*/
  2714. {
  2715. KEVENT event;
  2716. NTSTATUS status;
  2717. PDEVICE_RELATIONS deviceRelations;
  2718. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  2719. PDEVICE_CAPABILITIES deviceCapabilities;
  2720. PFDO_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  2721. status = IoAcquireRemoveLock(&fdoExtension->RemoveLock, NULL);
  2722. if (!NT_SUCCESS(status)) {
  2723. Irp->IoStatus.Status = status;
  2724. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  2725. return status;
  2726. }
  2727. switch (irpStack->MinorFunction) {
  2728. case IRP_MN_QUERY_DEVICE_RELATIONS:
  2729. DEBUGPRINT3((
  2730. "Sbp2Port: Pnp: ... Type = %x\n",
  2731. irpStack->Parameters.QueryDeviceRelations.Type
  2732. ));
  2733. if (irpStack->Parameters.QueryDeviceRelations.Type != BusRelations) {
  2734. break;
  2735. }
  2736. deviceRelations = ExAllocatePool(
  2737. PagedPool,
  2738. sizeof (*deviceRelations) +
  2739. (SBP2_MAX_LUNS_PER_NODE * sizeof (PDEVICE_OBJECT))
  2740. );
  2741. if (!deviceRelations) {
  2742. DEBUGPRINT1 (("Sbp2Port: Pnp: devRels alloc failed!!\n"));
  2743. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  2744. Irp->IoStatus.Information = 0;
  2745. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2746. return (STATUS_INSUFFICIENT_RESOURCES);
  2747. }
  2748. status = Sbp2CreateDeviceRelations (fdoExtension, deviceRelations);
  2749. Irp->IoStatus.Status = status;
  2750. if (NT_SUCCESS(status)) {
  2751. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  2752. } else {
  2753. Irp->IoStatus.Information = 0;
  2754. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2755. return status;
  2756. }
  2757. break;
  2758. case IRP_MN_QUERY_CAPABILITIES:
  2759. deviceCapabilities =
  2760. irpStack->Parameters.DeviceCapabilities.Capabilities;
  2761. deviceCapabilities->SurpriseRemovalOK = TRUE;
  2762. break;
  2763. case IRP_MN_START_DEVICE:
  2764. KeInitializeEvent (&event, SynchronizationEvent, FALSE);
  2765. IoCopyCurrentIrpStackLocationToNext (Irp);
  2766. IoSetCompletionRoutine(
  2767. Irp,
  2768. Sbp2FdoRequestCompletionRoutine,
  2769. (PVOID) &event,
  2770. TRUE,
  2771. TRUE,
  2772. TRUE
  2773. );
  2774. status = IoCallDriver (fdoExtension->LowerDeviceObject, Irp);
  2775. if(!NT_SUCCESS(Irp->IoStatus.Status) && (status != STATUS_PENDING)) {
  2776. status = Irp->IoStatus.Status;
  2777. } else {
  2778. KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
  2779. status = Sbp2StartDevice (DeviceObject);
  2780. }
  2781. IoReleaseRemoveLock(&fdoExtension->RemoveLock, NULL);
  2782. Irp->IoStatus.Status = status;
  2783. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2784. return status;
  2785. case IRP_MN_REMOVE_DEVICE:
  2786. KeInitializeEvent (&event, SynchronizationEvent, FALSE);
  2787. IoCopyCurrentIrpStackLocationToNext(Irp);
  2788. IoSetCompletionRoutine(
  2789. Irp,
  2790. Sbp2FdoRequestCompletionRoutine,
  2791. (PVOID) &event,
  2792. TRUE,
  2793. TRUE,
  2794. TRUE
  2795. );
  2796. status = IoCallDriver (fdoExtension->LowerDeviceObject, Irp);
  2797. if (!NT_SUCCESS (Irp->IoStatus.Status) && status != STATUS_PENDING) {
  2798. status = Irp->IoStatus.Status;
  2799. } else {
  2800. KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
  2801. //
  2802. // do FDO cleanup..
  2803. //
  2804. IoReleaseRemoveLockAndWait(&fdoExtension->RemoveLock, NULL);
  2805. if (Sbp2CleanDeviceExtension (DeviceObject, TRUE)) {
  2806. ASSERT(!fdoExtension->ulBusResetMutexCount);
  2807. ASSERT(!fdoExtension->ulWorkItemCount);
  2808. IoDetachDevice (fdoExtension->LowerDeviceObject);
  2809. IoDeleteDevice (DeviceObject);
  2810. }
  2811. status = STATUS_SUCCESS;
  2812. }
  2813. Irp->IoStatus.Status = status;
  2814. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  2815. return status;
  2816. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  2817. Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
  2818. break;
  2819. default:
  2820. break;
  2821. }
  2822. IoReleaseRemoveLock(&fdoExtension->RemoveLock, NULL);
  2823. //
  2824. // Pass the irp down the stack
  2825. //
  2826. IoCopyCurrentIrpStackLocationToNext (Irp);
  2827. status = IoCallDriver (fdoExtension->LowerDeviceObject, Irp);
  2828. return status;
  2829. }
  2830. VOID
  2831. Sbp2HandleRemove(
  2832. IN PDEVICE_OBJECT DeviceObject
  2833. )
  2834. {
  2835. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2836. PFDO_DEVICE_EXTENSION fdoExtension;
  2837. KIRQL cIrql;
  2838. ULONG i,j;
  2839. PIRBIRP packet;
  2840. fdoExtension = (PFDO_DEVICE_EXTENSION) deviceExtension->BusFdo->DeviceExtension;
  2841. if (!TEST_FLAG (deviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED)) {
  2842. return;
  2843. }
  2844. //
  2845. // now we need to remove ourselves from the DeviceList, the sbp2 FDO keeps of its
  2846. // children...
  2847. // then we re-condense the list..
  2848. //
  2849. KeAcquireSpinLock (&fdoExtension->DeviceListLock,&cIrql);
  2850. if (fdoExtension->DeviceListSize > 1) {
  2851. DEBUGPRINT1(("\'Sbp2Cleanup, condensing PDO list\n"));
  2852. for (i = 0; i < fdoExtension->DeviceListSize; i++) {
  2853. if (fdoExtension->DeviceList[i].DeviceObject == DeviceObject) {
  2854. //
  2855. // free the model descriptor only if its not the same as the FDOs
  2856. // this only happens in the multi-lu case
  2857. //
  2858. if (fdoExtension->DeviceList[i].uniVendorId.Buffer) {
  2859. ExFreePool(fdoExtension->DeviceList[i].uniVendorId.Buffer);
  2860. fdoExtension->DeviceList[i].uniVendorId.Length = 0;
  2861. fdoExtension->DeviceList[i].uniVendorId.Buffer = NULL;
  2862. }
  2863. if (fdoExtension->DeviceList[i].uniModelId.Buffer) {
  2864. ExFreePool(fdoExtension->DeviceList[i].uniModelId.Buffer);
  2865. fdoExtension->DeviceList[i].uniModelId.Length = 0;
  2866. fdoExtension->DeviceList[i].uniModelId.Buffer = NULL;
  2867. }
  2868. if (fdoExtension->DeviceList[i].uniGenericName.Buffer) {
  2869. ExFreePool(fdoExtension->DeviceList[i].uniGenericName.Buffer);
  2870. fdoExtension->DeviceList[i].uniGenericName.Length = 0;
  2871. fdoExtension->DeviceList[i].uniGenericName.Buffer = NULL;
  2872. }
  2873. //
  2874. // we found our place in the list. Remove us and re-condense the list
  2875. //
  2876. for (j = i; j < fdoExtension->DeviceListSize; j++) {
  2877. if ((j + 1) < fdoExtension->DeviceListSize) {
  2878. fdoExtension->DeviceList[j] = fdoExtension->DeviceList[j+1];
  2879. //
  2880. // Change the (pdo)DevExt->DeviceInfo to point at
  2881. // the next postion in the device list
  2882. //
  2883. deviceExtension = fdoExtension->DeviceList[j].
  2884. DeviceObject->DeviceExtension;
  2885. deviceExtension->DeviceInfo =
  2886. &fdoExtension->DeviceList[j];
  2887. }
  2888. }
  2889. fdoExtension->DeviceListSize--;
  2890. }
  2891. }
  2892. } else {
  2893. if (fdoExtension->DeviceList[0].DeviceObject == DeviceObject) {
  2894. if (fdoExtension->DeviceList[0].uniVendorId.Buffer) {
  2895. ExFreePool(fdoExtension->DeviceList[0].uniVendorId.Buffer);
  2896. fdoExtension->DeviceList[0].uniVendorId.Length = 0;
  2897. fdoExtension->DeviceList[0].uniVendorId.Buffer = NULL;
  2898. }
  2899. if (fdoExtension->DeviceList[0].uniModelId.Buffer) {
  2900. ExFreePool(fdoExtension->DeviceList[0].uniModelId.Buffer);
  2901. fdoExtension->DeviceList[0].uniModelId.Length = 0;
  2902. fdoExtension->DeviceList[0].uniModelId.Buffer = NULL;
  2903. }
  2904. if (fdoExtension->DeviceList[0].uniGenericName.Buffer) {
  2905. ExFreePool(fdoExtension->DeviceList[0].uniGenericName.Buffer);
  2906. fdoExtension->DeviceList[0].uniGenericName.Length = 0;
  2907. fdoExtension->DeviceList[0].uniGenericName.Buffer = NULL;
  2908. }
  2909. }
  2910. fdoExtension->DeviceList[0].DeviceObject = NULL;
  2911. fdoExtension->DeviceListSize = 0;
  2912. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZED);
  2913. }
  2914. if (fdoExtension->DeviceListSize == 0) {
  2915. //
  2916. // all our children have been deleted, set our FDO to be inactive
  2917. // so it can not re create PDOs qhen it receives a QDR.
  2918. // The reaosn is that if our PDOS are all removed, we dont support
  2919. // dynamic changes ot the crom, which would then warrant us being
  2920. // able to eject PDOs again.
  2921. //
  2922. SET_FLAG(fdoExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  2923. KeReleaseSpinLock (&fdoExtension->DeviceListLock, cIrql);
  2924. //
  2925. // Disable bus reset notifications
  2926. //
  2927. AllocateIrpAndIrb ((PDEVICE_EXTENSION) fdoExtension, &packet);
  2928. if (packet) {
  2929. packet->Irb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
  2930. packet->Irb->Flags = 0;
  2931. packet->Irb->u.BusResetNotification.fulFlags = DEREGISTER_NOTIFICATION_ROUTINE;
  2932. Sbp2SendRequest(
  2933. (PDEVICE_EXTENSION) fdoExtension,
  2934. packet,
  2935. SYNC_1394_REQUEST
  2936. );
  2937. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)fdoExtension,packet);
  2938. }
  2939. fdoExtension->NumPDOsStarted = 0;
  2940. } else {
  2941. KeReleaseSpinLock (&fdoExtension->DeviceListLock, cIrql);
  2942. }
  2943. }
  2944. NTSTATUS
  2945. Sbp2FdoRequestCompletionRoutine(
  2946. IN PDEVICE_OBJECT DeviceObject,
  2947. IN PIRP Irp,
  2948. IN PKEVENT Event
  2949. )
  2950. {
  2951. KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
  2952. return STATUS_MORE_PROCESSING_REQUIRED;
  2953. }
  2954. NTSTATUS
  2955. Sbp2CreateDeviceRelations(
  2956. IN PFDO_DEVICE_EXTENSION FdoExtension,
  2957. IN PDEVICE_RELATIONS DeviceRelations
  2958. )
  2959. {
  2960. ULONG i;
  2961. NTSTATUS status;
  2962. ULONG instanceNum;
  2963. PAGED_CODE();
  2964. //
  2965. // LUNS are static in the Config Rom. so if our DeviceListSize >0, that objetc
  2966. // has been seen before
  2967. //
  2968. DeviceRelations->Count = 0;
  2969. status = Sbp2Get1394ConfigInfo (FdoExtension, NULL);
  2970. if (!NT_SUCCESS(status)) {
  2971. ExFreePool (DeviceRelations);
  2972. return status;
  2973. }
  2974. if (TEST_FLAG (FdoExtension->DeviceFlags,DEVICE_FLAG_STOPPED)) {
  2975. ExFreePool(DeviceRelations);
  2976. return STATUS_UNSUCCESSFUL;
  2977. }
  2978. for (i = 0; i < FdoExtension->DeviceListSize; i++) {
  2979. if (!FdoExtension->DeviceList[i].DeviceObject) {
  2980. instanceNum = 0;
  2981. do {
  2982. status = Sbp2CreatePdo (FdoExtension,&FdoExtension->DeviceList[i],instanceNum++);
  2983. } while (status == STATUS_OBJECT_NAME_COLLISION);
  2984. if (!NT_SUCCESS(status)) {
  2985. DEBUGPRINT1(("\'Sbp2CreateDeviceRelations, Failed to create PDO \n"));
  2986. ExFreePool (DeviceRelations);
  2987. return status;
  2988. }
  2989. DeviceRelations->Objects[DeviceRelations->Count] = FdoExtension->DeviceList[i].DeviceObject;
  2990. DeviceRelations->Count++;
  2991. ObReferenceObject (FdoExtension->DeviceList[i].DeviceObject);
  2992. } else {
  2993. //
  2994. // On NT we always add existing pdo's to the dev relations list.
  2995. //
  2996. // On 9x, we only add pdo's to the list whose DevFlags field
  2997. // is non-zero. If we see a pdo with a zero DevFlags field
  2998. // then that means it was never started (likely for lack of
  2999. // a driver), and we don't want to re-indicate it to the caller.
  3000. // The pdo will eventually get deleted when cleaning up the fdo.
  3001. //
  3002. if (!SystemIsNT) {
  3003. PDEVICE_EXTENSION pdoExtension;
  3004. pdoExtension = (PDEVICE_EXTENSION)
  3005. FdoExtension->DeviceList[i].DeviceObject->DeviceExtension;
  3006. if (pdoExtension->DeviceFlags &
  3007. DEVICE_FLAG_UNSTARTED_AND_REMOVED) {
  3008. ASSERT(pdoExtension->DeviceFlags == DEVICE_FLAG_UNSTARTED_AND_REMOVED);
  3009. DEBUGPRINT2((
  3010. "Sbp2Port: CreateDevRelations: excluding ext=x%x\n",
  3011. pdoExtension
  3012. ));
  3013. continue;
  3014. }
  3015. }
  3016. DeviceRelations->Objects[DeviceRelations->Count] =
  3017. FdoExtension->DeviceList[i].DeviceObject;
  3018. DeviceRelations->Count++;
  3019. ObReferenceObject (FdoExtension->DeviceList[i].DeviceObject);
  3020. }
  3021. }
  3022. return STATUS_SUCCESS;
  3023. }
  3024. //
  3025. // code below ported from scsiport
  3026. //
  3027. NTSTATUS
  3028. Sbp2SystemControl(
  3029. PDEVICE_OBJECT DeviceObject,
  3030. PIRP Irp
  3031. )
  3032. /*++
  3033. Routine Description:
  3034. This routine handles only the WMI related requests. It mostly passes everything down
  3035. Arguments:
  3036. DeviceObject - Supplies a pointer to the device object for this request.
  3037. Irp - Supplies the Irp making the request.
  3038. Return Value:
  3039. NTSTATUS
  3040. --*/
  3041. {
  3042. NTSTATUS status;
  3043. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  3044. if (deviceExtension->Type == SBP2_FDO) {
  3045. DEBUGPRINT2(("Sbp2Port: WmiCtl: irp=x%p not handled, passing it down\n", Irp));
  3046. IoCopyCurrentIrpStackLocationToNext(Irp);
  3047. return (IoCallDriver(deviceExtension->LowerDeviceObject, Irp));
  3048. } else {
  3049. status = Irp->IoStatus.Status;
  3050. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  3051. return status;
  3052. }
  3053. }
  3054. /* ******************************* POWER MANAGEMENT ********************************/
  3055. NTSTATUS
  3056. Sbp2PowerControl(
  3057. IN PDEVICE_OBJECT DeviceObject,
  3058. IN PIRP Irp
  3059. )
  3060. /*++
  3061. Routine Description:
  3062. This routine receives the various Power messages
  3063. Arguments:
  3064. DeviceObject - Pointer to class device object.
  3065. Irp - Pointer to the request packet.
  3066. Return Value:
  3067. Status is returned.
  3068. --*/
  3069. {
  3070. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  3071. PFDO_DEVICE_EXTENSION fdoExtension;
  3072. PIO_STACK_LOCATION irpStack;
  3073. PIO_COMPLETION_ROUTINE complRoutine;
  3074. KIRQL cIrql;
  3075. NTSTATUS status;
  3076. POWER_STATE State;
  3077. UCHAR minorFunction;
  3078. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3079. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  3080. DEBUGPRINT2((
  3081. "Sbp2Port: Power: %sExt=x%p, irp=x%p, minor=x%x\n",
  3082. (deviceExtension->Type == SBP2_FDO ? "fdo" : "pdo"),
  3083. deviceExtension,
  3084. Irp,
  3085. irpStack->MinorFunction
  3086. ));
  3087. switch (deviceExtension->Type) {
  3088. case SBP2_PDO:
  3089. status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, NULL);
  3090. if (!NT_SUCCESS (status)) {
  3091. DEBUGPRINT2((
  3092. "Sbp2Port: Power: pdoExt=x%p REMOVED!\n",
  3093. deviceExtension
  3094. ));
  3095. Irp->IoStatus.Status = status;
  3096. PoStartNextPowerIrp (Irp);
  3097. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  3098. return status;
  3099. }
  3100. switch ((minorFunction = irpStack->MinorFunction)) {
  3101. case IRP_MN_SET_POWER:
  3102. DEBUGPRINT2(("Sbp2Port: Power: Type = %d, State = %d\n",
  3103. irpStack->Parameters.Power.Type,irpStack->Parameters.Power.State.DeviceState));
  3104. State = irpStack->Parameters.Power.State;
  3105. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  3106. BOOLEAN sendDIrp = FALSE;
  3107. //
  3108. // make up a device state to correspond to a system state
  3109. //
  3110. DEBUGPRINT2(("Sbp2Port: Power: sys power chg from %x to %x\n",deviceExtension->SystemPowerState,State));
  3111. status = STATUS_SUCCESS;
  3112. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  3113. if (State.SystemState >= PowerSystemShutdown) {
  3114. //
  3115. // dont do anything for shutdown
  3116. //
  3117. DEBUGPRINT2(("Sbp2Port: Power: sys shutdown, ignoring\n"));
  3118. deviceExtension->SystemPowerState = State.SystemState;
  3119. } else if ((deviceExtension->SystemPowerState == PowerSystemWorking) &&
  3120. (State.SystemState != PowerSystemWorking)){
  3121. deviceExtension->SystemPowerState = State.SystemState;
  3122. if (deviceExtension->DevicePowerState != PowerDeviceD3) {
  3123. //
  3124. // Powering down
  3125. //
  3126. State.DeviceState = PowerDeviceD3;
  3127. sendDIrp = TRUE;
  3128. }
  3129. } else if (State.SystemState == PowerSystemWorking) {
  3130. deviceExtension->SystemPowerState = State.SystemState;
  3131. if (deviceExtension->DevicePowerState != PowerDeviceD0) {
  3132. //
  3133. // Powering up - check for an absent fdo
  3134. //
  3135. fdoExtension =
  3136. deviceExtension->BusFdo->DeviceExtension;
  3137. if (TEST_FLAG(
  3138. fdoExtension->DeviceFlags,
  3139. DEVICE_FLAG_ABSENT_ON_POWER_UP
  3140. )) {
  3141. SET_FLAG(
  3142. deviceExtension->DeviceFlags,
  3143. DEVICE_FLAG_ABSENT_ON_POWER_UP
  3144. );
  3145. DEBUGPRINT1((
  3146. "Sbp2Port: Power: dev absent, failing\n"
  3147. ));
  3148. status = STATUS_NO_SUCH_DEVICE;
  3149. } else {
  3150. State.DeviceState = PowerDeviceD0;
  3151. sendDIrp = TRUE;
  3152. }
  3153. }
  3154. }
  3155. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  3156. if (sendDIrp) {
  3157. DEBUGPRINT2((
  3158. "Sbp2Port: Power: ext=x%p send D irp for state %d\n",
  3159. deviceExtension,
  3160. State
  3161. ));
  3162. IoMarkIrpPending (Irp);
  3163. status = PoRequestPowerIrp(
  3164. DeviceObject,
  3165. IRP_MN_SET_POWER,
  3166. State,
  3167. Sbp2PdoDIrpCompletion,
  3168. Irp,
  3169. NULL);
  3170. if (NT_SUCCESS (status)) {
  3171. return STATUS_PENDING;
  3172. }
  3173. irpStack->Control &= ~SL_PENDING_RETURNED;
  3174. DEBUGPRINT1((
  3175. "Sbp2Port: Power: ext=x%p PoReqPowerIrp err=x%x\n",
  3176. deviceExtension,
  3177. status
  3178. ));
  3179. }
  3180. Irp->IoStatus.Status = status;
  3181. PoStartNextPowerIrp (Irp);
  3182. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  3183. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  3184. return status;
  3185. } else {
  3186. DEBUGPRINT2(("Sbp2Port: Power: dev power chg from %x to %x\n",deviceExtension->DevicePowerState,State));
  3187. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock,&cIrql);
  3188. deviceExtension->DevicePowerState = State.DeviceState;
  3189. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock,cIrql);
  3190. }
  3191. status = STATUS_SUCCESS;
  3192. break;
  3193. case IRP_MN_WAIT_WAKE:
  3194. case IRP_MN_POWER_SEQUENCE:
  3195. case IRP_MN_QUERY_POWER:
  3196. status = STATUS_SUCCESS;
  3197. break;
  3198. default:
  3199. status = Irp->IoStatus.Status;
  3200. break;
  3201. }
  3202. Irp->IoStatus.Status = status;
  3203. PoStartNextPowerIrp (Irp);
  3204. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  3205. if ((minorFunction == IRP_MN_SET_POWER) &&
  3206. (State.DeviceState == PowerDeviceD0)) {
  3207. //
  3208. // restart our queue if we had to queue something while powering up
  3209. //
  3210. // ISSUE: This may be bad - there is already some logic in
  3211. // SBP2SCSI.C to restart the queue on power up, i.e.
  3212. // the UNLOCK_QUEUE handler. For now i am at least
  3213. // limiting this to SET_POWER irps when state is D0
  3214. // DanKn 02-Jun-2001
  3215. //
  3216. KeRaiseIrql (DISPATCH_LEVEL, &cIrql);
  3217. Sbp2StartNextPacketByKey(
  3218. DeviceObject,
  3219. deviceExtension->CurrentKey
  3220. );
  3221. KeLowerIrql (cIrql);
  3222. }
  3223. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  3224. return (status);
  3225. case SBP2_FDO:
  3226. fdoExtension = (PFDO_DEVICE_EXTENSION) deviceExtension;
  3227. complRoutine = NULL;
  3228. if (irpStack->MinorFunction == IRP_MN_SET_POWER) {
  3229. DEBUGPRINT2((
  3230. "Sbp2Port: Power: Type = %d, State = %d\n",
  3231. irpStack->Parameters.Power.Type,
  3232. irpStack->Parameters.Power.State.DeviceState
  3233. ));
  3234. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  3235. State = irpStack->Parameters.Power.State;
  3236. DEBUGPRINT2((
  3237. "Sbp2Port: Power: sys power chg from %x to %x\n",
  3238. fdoExtension->SystemPowerState,
  3239. State
  3240. ));
  3241. if (State.SystemState >= PowerSystemShutdown) {
  3242. //
  3243. // Shutdown (setting state here, the assumption being
  3244. // that we're shutting down regardless of the
  3245. // completion status of this request)
  3246. //
  3247. fdoExtension->SystemPowerState = State.SystemState;
  3248. } else if ((fdoExtension->SystemPowerState ==
  3249. PowerSystemWorking) &&
  3250. (State.SystemState != PowerSystemWorking)) {
  3251. //
  3252. // Power down. If DevPowerState != D3 then send
  3253. // a D irp first (when that completes successfully
  3254. // we'll continue with the S irp), else just
  3255. // set the completion routine so we can update
  3256. // the system state field in our extension on
  3257. // successful completion of this S irp.
  3258. //
  3259. if (fdoExtension->DevicePowerState != PowerDeviceD3) {
  3260. //
  3261. // Power down, send a D irp first
  3262. //
  3263. IoMarkIrpPending (Irp);
  3264. fdoExtension->SystemPowerIrp = Irp;
  3265. State.DeviceState = PowerDeviceD3;
  3266. DEBUGPRINT2((
  3267. "Sbp2Port: Power: ext=x%p sending D irp for state %x\n",
  3268. deviceExtension,
  3269. State
  3270. ));
  3271. status = PoRequestPowerIrp(
  3272. fdoExtension->Pdo,
  3273. IRP_MN_SET_POWER,
  3274. State,
  3275. Sbp2FdoDIrpCompletion,
  3276. fdoExtension,
  3277. NULL
  3278. );
  3279. if (!NT_SUCCESS (status)) {
  3280. DEBUGPRINT1((
  3281. "Sbp2Port: Power: ext=x%p PoReqPowerIrp err=x%x\n",
  3282. fdoExtension,
  3283. status
  3284. ));
  3285. irpStack->Control &= ~SL_PENDING_RETURNED;
  3286. Irp->IoStatus.Status = status;
  3287. PoStartNextPowerIrp (Irp);
  3288. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  3289. }
  3290. return status;
  3291. } else {
  3292. complRoutine = Sbp2FdoSIrpCompletion;
  3293. }
  3294. } else if (State.SystemState == PowerSystemWorking) {
  3295. //
  3296. // Power up. Set the completion routine so we
  3297. // follow up with a D irp or update the system
  3298. // state field in our extension on successful
  3299. // completion of this S irp.
  3300. //
  3301. complRoutine = Sbp2FdoSIrpCompletion;
  3302. }
  3303. }
  3304. }
  3305. PoStartNextPowerIrp (Irp);
  3306. IoCopyCurrentIrpStackLocationToNext (Irp);
  3307. if (complRoutine) {
  3308. IoSetCompletionRoutine(
  3309. Irp,
  3310. Sbp2FdoSIrpCompletion,
  3311. NULL,
  3312. TRUE,
  3313. TRUE,
  3314. TRUE
  3315. );
  3316. }
  3317. return (PoCallDriver (deviceExtension->LowerDeviceObject, Irp));
  3318. default:
  3319. break;
  3320. }
  3321. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  3322. PoStartNextPowerIrp (Irp);
  3323. IoCompleteRequest (Irp,IO_NO_INCREMENT);
  3324. return STATUS_NO_SUCH_DEVICE;
  3325. }
  3326. VOID
  3327. Sbp2PdoDIrpCompletion(
  3328. IN PDEVICE_OBJECT DeviceObject,
  3329. IN UCHAR MinorFunction,
  3330. IN POWER_STATE PowerState,
  3331. IN PIRP SIrp,
  3332. IN PIO_STATUS_BLOCK IoStatus
  3333. )
  3334. {
  3335. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  3336. ASSERT(deviceExtension->Type == SBP2_PDO);
  3337. if (SIrp) {
  3338. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (SIrp);
  3339. SYSTEM_POWER_STATE state = irpStack->Parameters.Power.State.SystemState;
  3340. DEBUGPRINT1((
  3341. "Sbp2Port: PdoDIrpCompl: ext=x%p, sIrp=x%p, state=%d, status=x%x\n",
  3342. deviceExtension,
  3343. SIrp,
  3344. PowerState.DeviceState,
  3345. IoStatus->Status
  3346. ));
  3347. SIrp->IoStatus.Status = STATUS_SUCCESS;
  3348. PoStartNextPowerIrp (SIrp);
  3349. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  3350. IoCompleteRequest (SIrp, IO_NO_INCREMENT);
  3351. }
  3352. }
  3353. NTSTATUS
  3354. Sbp2FdoSIrpCompletion(
  3355. IN PDEVICE_OBJECT DeviceObject,
  3356. IN PIRP Irp,
  3357. IN PVOID Unused
  3358. )
  3359. {
  3360. KIRQL cIrql;
  3361. NTSTATUS status = Irp->IoStatus.Status;
  3362. POWER_STATE state;
  3363. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
  3364. PFDO_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  3365. state = irpStack->Parameters.Power.State;
  3366. DEBUGPRINT1((
  3367. "Sbp2Port: FdoSIrpCompl: fdoExt=x%p, status=x%x, state=%d\n",
  3368. fdoExtension,
  3369. status,
  3370. state
  3371. ));
  3372. if (!NT_SUCCESS (status)) {
  3373. if ((status == STATUS_NO_SUCH_DEVICE) &&
  3374. (state.SystemState == PowerSystemWorking)) {
  3375. //
  3376. // Controller (i.e. pc card) was ejected while powered down
  3377. //
  3378. SET_FLAG(
  3379. fdoExtension->DeviceFlags,
  3380. DEVICE_FLAG_ABSENT_ON_POWER_UP
  3381. );
  3382. }
  3383. PoStartNextPowerIrp (Irp);
  3384. return STATUS_SUCCESS;
  3385. }
  3386. //
  3387. // If we're completing a power up S irp then see if we have
  3388. // to follow up with a power up D irp
  3389. //
  3390. if ((state.SystemState == PowerSystemWorking) &&
  3391. (fdoExtension->DevicePowerState != PowerDeviceD0)) {
  3392. fdoExtension->SystemPowerIrp = Irp;
  3393. state.DeviceState = PowerDeviceD0;
  3394. DEBUGPRINT1(("Sbp2Port: FdoSIrpCompl: sending D irp...\n"));
  3395. status = PoRequestPowerIrp(
  3396. fdoExtension->Pdo,
  3397. IRP_MN_SET_POWER,
  3398. state,
  3399. Sbp2FdoDIrpCompletion,
  3400. fdoExtension,
  3401. NULL
  3402. );
  3403. if (!NT_SUCCESS (status)) {
  3404. DEBUGPRINT1((
  3405. "Sbp2Port: FdoSIrpCompl: ERROR! fdoExt=x%p, D irp sts=x%x\n",
  3406. fdoExtension,
  3407. status
  3408. ));
  3409. Irp->IoStatus.Status = status;
  3410. PoStartNextPowerIrp (Irp);
  3411. return status;
  3412. }
  3413. return STATUS_MORE_PROCESSING_REQUIRED;
  3414. }
  3415. //
  3416. // Update appropriate XxxPowerState extension fields
  3417. //
  3418. if ((fdoExtension->SystemPowerState == PowerSystemWorking) &&
  3419. (state.SystemState != PowerSystemWorking)) {
  3420. //
  3421. // Power down (might not have sent a D irp but it doesn't
  3422. // hurt to overwrite the DevicePowerState field anyway)
  3423. //
  3424. fdoExtension->SystemPowerState = state.SystemState;
  3425. fdoExtension->DevicePowerState = PowerDeviceD3;
  3426. } else if (state.SystemState == PowerSystemWorking) {
  3427. //
  3428. // Power up
  3429. //
  3430. fdoExtension->SystemPowerState = PowerSystemWorking;
  3431. }
  3432. PoStartNextPowerIrp (Irp);
  3433. return STATUS_SUCCESS;
  3434. }
  3435. VOID
  3436. Sbp2FdoDIrpCompletion(
  3437. IN PDEVICE_OBJECT TargetDeviceObject,
  3438. IN UCHAR MinorFunction,
  3439. IN POWER_STATE PowerState,
  3440. IN PFDO_DEVICE_EXTENSION FdoExtension,
  3441. IN PIO_STATUS_BLOCK IoStatus
  3442. )
  3443. {
  3444. PIRP sIrp = FdoExtension->SystemPowerIrp;
  3445. DEBUGPRINT1((
  3446. "Sbp2Port: FdoDIrpCompl: ext=x%p, status=x%x\n",
  3447. FdoExtension,
  3448. IoStatus->Status
  3449. ));
  3450. FdoExtension->SystemPowerIrp = NULL;
  3451. if (NT_SUCCESS (IoStatus->Status)) {
  3452. if (PowerState.DeviceState == PowerDeviceD0) {
  3453. //
  3454. // Power up, update the XxxPowerState extension fields &
  3455. // complete the s irp
  3456. //
  3457. FdoExtension->SystemPowerState = PowerSystemWorking;
  3458. FdoExtension->DevicePowerState = PowerDeviceD0;
  3459. } else {
  3460. //
  3461. // Power down, forward the s irp
  3462. //
  3463. PoStartNextPowerIrp (sIrp);
  3464. IoCopyCurrentIrpStackLocationToNext (sIrp);
  3465. PoCallDriver (FdoExtension->LowerDeviceObject, sIrp);
  3466. return;
  3467. }
  3468. } else {
  3469. //
  3470. // Propagate the error to the S irp & complete it
  3471. //
  3472. DEBUGPRINT1((
  3473. "Sbp2Port: FdoDIrpCompl: ERROR! fdoExt=x%p, D irp status=x%x\n",
  3474. FdoExtension,
  3475. IoStatus->Status
  3476. ));
  3477. sIrp->IoStatus.Status = IoStatus->Status;
  3478. }
  3479. PoStartNextPowerIrp (sIrp);
  3480. IoCompleteRequest (sIrp, IO_NO_INCREMENT);
  3481. }
  3482. BOOLEAN
  3483. Sbp2EnableBusResetNotification(
  3484. PDEVICE_EXTENSION DeviceExtension,
  3485. BOOLEAN Enable
  3486. )
  3487. /*++
  3488. Routine Description:
  3489. This routine serializes the enabling/disabling of the bus reset
  3490. notification routine for a set of related PDOs (1 or more).
  3491. Enables bus reset notifications for the first device to start, and
  3492. disables bus reset notifications when the last started device stops.
  3493. Arguments:
  3494. DeviceObject - Supplies a pointer to the device extension for this request.
  3495. StartDevice - Whether we are processing a START_DEVICE or (implicitly)
  3496. a STOP_DEVICE request.
  3497. Return Value:
  3498. BOOLEAN - yay or nay
  3499. --*/
  3500. {
  3501. BOOLEAN result = TRUE;
  3502. PIRBIRP packet;
  3503. LARGE_INTEGER waitValue;
  3504. PFDO_DEVICE_EXTENSION fdoExtension;
  3505. fdoExtension = DeviceExtension->BusFdo->DeviceExtension;
  3506. ASSERT(InterlockedIncrement(&fdoExtension->ulBusResetMutexCount) == 1);
  3507. waitValue.QuadPart = -3 * 1000 * 1000 * 10; // 3 seconds
  3508. KeWaitForSingleObject(
  3509. &fdoExtension->EnableBusResetNotificationMutex,
  3510. Executive,
  3511. KernelMode,
  3512. FALSE,
  3513. &waitValue
  3514. );
  3515. ASSERT(InterlockedDecrement(&fdoExtension->ulBusResetMutexCount) == 0);
  3516. if (Enable) {
  3517. fdoExtension->NumPDOsStarted++;
  3518. if (fdoExtension->NumPDOsStarted > 1) {
  3519. goto releaseMutex;
  3520. }
  3521. } else {
  3522. fdoExtension->NumPDOsStarted--;
  3523. if (fdoExtension->NumPDOsStarted > 0) {
  3524. goto releaseMutex;
  3525. }
  3526. }
  3527. AllocateIrpAndIrb (DeviceExtension, &packet);
  3528. if (packet) {
  3529. packet->Irb->FunctionNumber = REQUEST_BUS_RESET_NOTIFICATION;
  3530. packet->Irb->Flags = 0;
  3531. if (Enable) {
  3532. packet->Irb->u.BusResetNotification.fulFlags =
  3533. REGISTER_NOTIFICATION_ROUTINE;
  3534. packet->Irb->u.BusResetNotification.ResetRoutine =
  3535. (PBUS_BUS_RESET_NOTIFICATION) Sbp2BusResetNotification;
  3536. packet->Irb->u.BusResetNotification.ResetContext =
  3537. fdoExtension;
  3538. } else {
  3539. packet->Irb->u.BusResetNotification.fulFlags =
  3540. DEREGISTER_NOTIFICATION_ROUTINE;
  3541. }
  3542. Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  3543. DeAllocateIrpAndIrb (DeviceExtension,packet);
  3544. } else {
  3545. if (Enable) {
  3546. fdoExtension->NumPDOsStarted--;
  3547. }
  3548. result = FALSE;
  3549. }
  3550. releaseMutex:
  3551. KeReleaseMutex (&fdoExtension->EnableBusResetNotificationMutex, FALSE);
  3552. return result;
  3553. }
  3554. NTSTATUS
  3555. Sbp2_BuildDeviceId(
  3556. IN PDEVICE_INFORMATION DeviceInfo,
  3557. IN OUT PUNICODE_STRING uniDeviceId
  3558. )
  3559. {
  3560. NTSTATUS ntStatus = STATUS_SUCCESS;
  3561. PAGED_CODE();
  3562. //
  3563. // Create the DeviceId
  3564. //
  3565. uniDeviceId->Length = 0;
  3566. uniDeviceId->MaximumLength = DEVICE_NAME_MAX_CHARS*3;
  3567. uniDeviceId->Buffer = ExAllocatePool(PagedPool, uniDeviceId->MaximumLength);
  3568. if (!uniDeviceId->Buffer) {
  3569. TRACE(TL_PNP_ERROR, ("Failed to allocate uniDeviceId->Buffer"));
  3570. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3571. goto Exit_Sbp2_BuildDeviceId;
  3572. }
  3573. RtlZeroMemory(uniDeviceId->Buffer, uniDeviceId->MaximumLength);
  3574. // Format: SBP2\\<VendorName>&<ModelName>&LUN<#>
  3575. if ((DeviceInfo->uniVendorId.Buffer) && (DeviceInfo->uniModelId.Buffer)) {
  3576. swprintf( uniDeviceId->Buffer,
  3577. L"SBP2\\%ws&%ws&LUN%x",
  3578. DeviceInfo->uniVendorId.Buffer,
  3579. DeviceInfo->uniModelId.Buffer,
  3580. DeviceInfo->Lun.u.LowPart
  3581. );
  3582. }
  3583. else {
  3584. swprintf( uniDeviceId->Buffer,
  3585. L"SBP2\\UNKNOWN VENDOR&UNKNOWN MODEL&LUN%x",
  3586. DeviceInfo->Lun.u.LowPart
  3587. );
  3588. }
  3589. Exit_Sbp2_BuildDeviceId:
  3590. return(ntStatus);
  3591. } // Sbp2_BuildDeviceId
  3592. NTSTATUS
  3593. Sbp2_BuildHardwareIds(
  3594. IN PDEVICE_INFORMATION DeviceInfo,
  3595. IN OUT PUNICODE_STRING uniHardwareIds
  3596. )
  3597. {
  3598. NTSTATUS ntStatus = STATUS_SUCCESS;
  3599. UNICODE_STRING uniLunNumber;
  3600. UNICODE_STRING uniCmdSetId;
  3601. PAGED_CODE();
  3602. // init our unicodes in case of error...
  3603. uniLunNumber.Buffer = NULL;
  3604. uniCmdSetId.Buffer = NULL;
  3605. //
  3606. // Create uniLunNumber
  3607. //
  3608. uniLunNumber.Length = 0;
  3609. uniLunNumber.MaximumLength = DEVICE_NAME_MAX_CHARS;
  3610. uniLunNumber.Buffer = ExAllocatePool(PagedPool, uniLunNumber.MaximumLength);
  3611. if (!uniLunNumber.Buffer) {
  3612. TRACE(TL_PNP_ERROR, ("Failed to allocate uniLunNumber.Buffer"));
  3613. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3614. goto Exit_Sbp2_BuildHardwareIds;
  3615. }
  3616. RtlZeroMemory(uniLunNumber.Buffer, uniLunNumber.MaximumLength);
  3617. RtlIntegerToUnicodeString(DeviceInfo->Lun.u.LowPart, 16, &uniLunNumber);
  3618. //
  3619. // Create uniCmdSetId
  3620. //
  3621. uniCmdSetId.Length = 0;
  3622. uniCmdSetId.MaximumLength = DEVICE_NAME_MAX_CHARS;
  3623. uniCmdSetId.Buffer = ExAllocatePool(PagedPool, uniCmdSetId.MaximumLength);
  3624. if (!uniCmdSetId.Buffer) {
  3625. TRACE(TL_PNP_ERROR, ("Failed to allocate uniCmdSetId.Buffer"));
  3626. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3627. goto Exit_Sbp2_BuildHardwareIds;
  3628. }
  3629. RtlZeroMemory(uniCmdSetId.Buffer, uniCmdSetId.MaximumLength);
  3630. RtlIntegerToUnicodeString(DeviceInfo->CmdSetId.QuadPart, 16, &uniCmdSetId);
  3631. //
  3632. // Create the HardwareIds
  3633. //
  3634. uniHardwareIds->Length = 0;
  3635. uniHardwareIds->MaximumLength = DEVICE_NAME_MAX_CHARS*5;
  3636. uniHardwareIds->Buffer = ExAllocatePool(PagedPool, uniHardwareIds->MaximumLength);
  3637. if (!uniHardwareIds->Buffer) {
  3638. TRACE(TL_PNP_ERROR, ("Failed to allocate uniHardwareIds->Buffer"));
  3639. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3640. goto Exit_Sbp2_BuildHardwareIds;
  3641. }
  3642. RtlZeroMemory(uniHardwareIds->Buffer, uniHardwareIds->MaximumLength);
  3643. // 1. SBP2\<Vendor>&<Model>&CmdSetId<number,base16>&Gen<dev type, ie. Disk>
  3644. // BASE: SBP2
  3645. RtlAppendUnicodeToString(uniHardwareIds, BASE_SBP2_DEVICE_NAME);
  3646. // VendorName and ModelName
  3647. if ((DeviceInfo->uniVendorId.Buffer) && (DeviceInfo->uniModelId.Buffer)) {
  3648. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniVendorId);
  3649. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3650. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniModelId);
  3651. }
  3652. else {
  3653. RtlAppendUnicodeToString(uniHardwareIds, L"UNKNOWN VENDOR&UNKNOWN MODEL");
  3654. }
  3655. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3656. // CmdSetId
  3657. RtlAppendUnicodeToString(uniHardwareIds, L"CmdSetId");
  3658. RtlAppendUnicodeStringToString(uniHardwareIds, &uniCmdSetId);
  3659. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3660. // GenericName
  3661. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniGenericName);
  3662. uniHardwareIds->Length += sizeof(WCHAR);
  3663. // 2. SBP2\<Vendor>&<Model>&CmdSetId<number,base16>
  3664. // BASE: SBP2
  3665. RtlAppendUnicodeToString(uniHardwareIds, BASE_SBP2_DEVICE_NAME);
  3666. // VendorName and ModelName
  3667. if ((DeviceInfo->uniVendorId.Buffer) && (DeviceInfo->uniModelId.Buffer)) {
  3668. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniVendorId);
  3669. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3670. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniModelId);
  3671. }
  3672. else {
  3673. RtlAppendUnicodeToString(uniHardwareIds, L"UNKNOWN VENDOR&UNKNOWN MODEL");
  3674. }
  3675. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3676. // CmdSetId
  3677. RtlAppendUnicodeToString(uniHardwareIds, L"CmdSetId");
  3678. RtlAppendUnicodeStringToString(uniHardwareIds, &uniCmdSetId);
  3679. uniHardwareIds->Length += sizeof(WCHAR);
  3680. // 3. SBP2\<Vendor>&<Model>&LUN<number,base16>
  3681. // BASE: SBP2
  3682. RtlAppendUnicodeToString(uniHardwareIds, BASE_SBP2_DEVICE_NAME);
  3683. // VendorName and ModelName
  3684. if ((DeviceInfo->uniVendorId.Buffer) && (DeviceInfo->uniModelId.Buffer)) {
  3685. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniVendorId);
  3686. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3687. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniModelId);
  3688. }
  3689. else {
  3690. RtlAppendUnicodeToString(uniHardwareIds, L"UNKNOWN VENDOR&UNKNOWN MODEL");
  3691. }
  3692. RtlAppendUnicodeToString(uniHardwareIds, L"&");
  3693. // LunNumber
  3694. RtlAppendUnicodeToString(uniHardwareIds, L"LUN");
  3695. RtlAppendUnicodeStringToString(uniHardwareIds, &uniLunNumber);
  3696. uniHardwareIds->Length += sizeof(WCHAR);
  3697. // 4. SBP2\Gen<dev type, i.e. Disk>
  3698. // BASE: SBP2
  3699. RtlAppendUnicodeToString(uniHardwareIds, BASE_SBP2_DEVICE_NAME);
  3700. // GenericName
  3701. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniGenericName);
  3702. uniHardwareIds->Length += sizeof(WCHAR);
  3703. // 5. Gen<dev type, i.e Disk>
  3704. // GenericName
  3705. RtlAppendUnicodeStringToString(uniHardwareIds, &DeviceInfo->uniGenericName);
  3706. Exit_Sbp2_BuildHardwareIds:
  3707. if (uniLunNumber.Buffer)
  3708. ExFreePool(uniLunNumber.Buffer);
  3709. if (uniCmdSetId.Buffer)
  3710. ExFreePool(uniCmdSetId.Buffer);
  3711. return(ntStatus);
  3712. } // Sbp2_BuildHardwareIds
  3713. NTSTATUS
  3714. Sbp2_BuildCompatIds(
  3715. IN PDEVICE_INFORMATION DeviceInfo,
  3716. IN OUT PUNICODE_STRING uniCompatIds
  3717. )
  3718. {
  3719. NTSTATUS ntStatus = STATUS_SUCCESS;
  3720. PAGED_CODE();
  3721. //
  3722. // Create the CompatIds
  3723. //
  3724. uniCompatIds->Length = 0;
  3725. uniCompatIds->MaximumLength = DEVICE_NAME_MAX_CHARS;
  3726. uniCompatIds->Buffer = ExAllocatePool(PagedPool, uniCompatIds->MaximumLength);
  3727. if (!uniCompatIds->Buffer) {
  3728. TRACE(TL_PNP_ERROR, ("Failed to allocate uniCompatIds->Buffer"));
  3729. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3730. goto Exit_Sbp2_BuildCompatIds;
  3731. }
  3732. RtlZeroMemory(uniCompatIds->Buffer, uniCompatIds->MaximumLength);
  3733. // Format: SBP2\\<CmdSetSpecId,base10>&<CmdSetId,base10>&<Lun,base10>
  3734. swprintf( uniCompatIds->Buffer,
  3735. L"SBP2\\%d&%d&%d",
  3736. DeviceInfo->CmdSetSpecId.QuadPart,
  3737. DeviceInfo->CmdSetId.QuadPart,
  3738. (ULONG)(DeviceInfo->Lun.u.HighPart & 0x001F) // huh?
  3739. );
  3740. Exit_Sbp2_BuildCompatIds:
  3741. return(ntStatus);
  3742. } // Sbp2_BuildCompatIds
  3743. NTSTATUS
  3744. Sbp2_BuildInstanceId(
  3745. IN PDEVICE_INFORMATION DeviceInfo,
  3746. IN OUT PUNICODE_STRING uniInstanceId
  3747. )
  3748. {
  3749. NTSTATUS ntStatus = STATUS_SUCCESS;
  3750. PAGED_CODE();
  3751. //
  3752. // Create the InstanceId
  3753. //
  3754. uniInstanceId->Length = 0;
  3755. uniInstanceId->MaximumLength = UNIQUE_ID_MAX_CHARS;
  3756. uniInstanceId->Buffer = ExAllocatePool(PagedPool, uniInstanceId->MaximumLength);
  3757. if (!uniInstanceId->Buffer) {
  3758. TRACE(TL_PNP_ERROR, ("Failed to allocate uniInstanceId->Buffer"));
  3759. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3760. goto Exit_Sbp2_BuildInstanceId;
  3761. }
  3762. RtlZeroMemory(uniInstanceId->Buffer, uniInstanceId->MaximumLength);
  3763. swprintf( uniInstanceId->Buffer,
  3764. L"%08x%08x",
  3765. bswap(DeviceInfo->ConfigRom->CR_Node_UniqueID[0]),
  3766. bswap(DeviceInfo->ConfigRom->CR_Node_UniqueID[1])
  3767. );
  3768. Exit_Sbp2_BuildInstanceId:
  3769. return(ntStatus);
  3770. } // Sbp2_BuildInstanceId
  3771. NTSTATUS
  3772. Sbp2_BuildDeviceText(
  3773. IN DEVICE_TEXT_TYPE TextType,
  3774. IN PDEVICE_INFORMATION DeviceInfo,
  3775. IN OUT PUNICODE_STRING uniDeviceText
  3776. )
  3777. {
  3778. NTSTATUS ntStatus = STATUS_SUCCESS;
  3779. PAGED_CODE();
  3780. //
  3781. // Create the DeviceText
  3782. //
  3783. uniDeviceText->Length = 0;
  3784. uniDeviceText->MaximumLength = DEVICE_NAME_MAX_CHARS*3;
  3785. uniDeviceText->Buffer = ExAllocatePool(PagedPool, uniDeviceText->MaximumLength);
  3786. if (!uniDeviceText->Buffer) {
  3787. TRACE(TL_PNP_ERROR, ("Failed to allocate uniDeviceText->Buffer"));
  3788. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3789. goto Exit_Sbp2_BuildDeviceText;
  3790. }
  3791. RtlZeroMemory(uniDeviceText->Buffer, uniDeviceText->MaximumLength);
  3792. if (TextType == DeviceTextDescription) {
  3793. if ((DeviceInfo->uniVendorId.Buffer) && (DeviceInfo->uniModelId.Buffer)) {
  3794. swprintf( uniDeviceText->Buffer,
  3795. L"%ws %ws IEEE 1394 SBP2 Device",
  3796. DeviceInfo->uniVendorId.Buffer,
  3797. DeviceInfo->uniModelId.Buffer
  3798. );
  3799. }
  3800. else {
  3801. swprintf( uniDeviceText->Buffer,
  3802. L"UNKNOWN VENDOR AND MODEL IEEE 1394 SBP2 Device"
  3803. );
  3804. }
  3805. }
  3806. else if (TextType == DeviceTextLocationInformation) {
  3807. swprintf( uniDeviceText->Buffer,
  3808. L"LUN %d",
  3809. DeviceInfo->Lun.u.LowPart
  3810. );
  3811. }
  3812. Exit_Sbp2_BuildDeviceText:
  3813. return(ntStatus);
  3814. } // Sbp2_BuildDeviceText
  3815. NTSTATUS
  3816. Sbp2ForwardIrpSynchronous(
  3817. IN PDEVICE_OBJECT DeviceObject,
  3818. IN PIRP Irp
  3819. )
  3820. {
  3821. NTSTATUS ntStatus = STATUS_SUCCESS;
  3822. PIRP newIrp;
  3823. PAGED_CODE();
  3824. ASSERT(DeviceObject);
  3825. newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
  3826. if (newIrp)
  3827. {
  3828. PIO_STACK_LOCATION currentIrpSp = IoGetCurrentIrpStackLocation(Irp);
  3829. PIO_STACK_LOCATION newIrpSp = IoGetNextIrpStackLocation(newIrp);
  3830. KEVENT event;
  3831. RtlMoveMemory (newIrpSp, currentIrpSp, sizeof(IO_STACK_LOCATION));
  3832. newIrp->IoStatus = Irp->IoStatus;
  3833. KeInitializeEvent(&event, NotificationEvent, FALSE);
  3834. IoSetCompletionRoutine(newIrp, Sbp2PortForwardIrpSynchronousCompletionRoutine, &event, TRUE, TRUE, TRUE);
  3835. ntStatus = IoCallDriver (DeviceObject, newIrp);
  3836. if (ntStatus == STATUS_PENDING)
  3837. {
  3838. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  3839. }
  3840. ntStatus = newIrp->IoStatus.Status;
  3841. IoFreeIrp(newIrp);
  3842. }
  3843. else
  3844. {
  3845. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3846. }
  3847. return ntStatus;
  3848. }
  3849. NTSTATUS
  3850. Sbp2PortForwardIrpSynchronousCompletionRoutine(
  3851. IN PDEVICE_OBJECT DeviceObject,
  3852. IN PIRP Irp,
  3853. IN PVOID Context
  3854. )
  3855. {
  3856. PKEVENT event = Context;
  3857. KeSetEvent(event, EVENT_INCREMENT, FALSE);
  3858. return STATUS_MORE_PROCESSING_REQUIRED;
  3859. }