Source code of Windows XP (NT5)
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.

3839 lines
114 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 2001
  3. Module Name:
  4. sbp21394.c
  5. Abstract:
  6. 1394 bus driver to SBP2 interface routines
  7. Author:
  8. George Chrysanthakopoulos January-1997
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "sbp2port.h"
  14. NTSTATUS
  15. Sbp2Issue1394BusReset (
  16. IN PDEVICE_EXTENSION DeviceExtension
  17. )
  18. {
  19. PIRBIRP packet = NULL;
  20. NTSTATUS status;
  21. AllocateIrpAndIrb (DeviceExtension, &packet);
  22. if (!packet) {
  23. return STATUS_INSUFFICIENT_RESOURCES;
  24. }
  25. //
  26. // Issue a 1394 bus reset
  27. //
  28. packet->Irb->FunctionNumber = REQUEST_BUS_RESET;
  29. packet->Irb->Flags = BUS_RESET_FLAGS_PERFORM_RESET;
  30. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  31. if (!NT_SUCCESS(status)) {
  32. DEBUGPRINT1((
  33. "Sbp2Port: IssueBusReset: err=x%x issuing bus reset\n",
  34. status
  35. ));
  36. }
  37. DeAllocateIrpAndIrb(DeviceExtension,packet);
  38. return status;
  39. }
  40. void
  41. Sbp2BusResetNotification(
  42. PFDO_DEVICE_EXTENSION FdoExtension
  43. )
  44. {
  45. NTSTATUS ntStatus;
  46. PIO_WORKITEM WorkItem;
  47. ntStatus = IoAcquireRemoveLock(&FdoExtension->RemoveLock, NULL);
  48. if (NT_SUCCESS(ntStatus)) {
  49. WorkItem = IoAllocateWorkItem(FdoExtension->DeviceObject);
  50. IoQueueWorkItem( WorkItem,
  51. Sbp2BusResetNotificationWorker,
  52. CriticalWorkQueue,
  53. WorkItem
  54. );
  55. }
  56. return;
  57. }
  58. void
  59. Sbp2BusResetNotificationWorker(
  60. PDEVICE_OBJECT DeviceObject,
  61. PIO_WORKITEM WorkItem
  62. )
  63. {
  64. PFDO_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  65. PDEVICE_EXTENSION deviceExtension;
  66. PSCSI_REQUEST_BLOCK pendingPowerSrb = NULL;
  67. ULONG i=0;
  68. BOOLEAN doReconnect;
  69. KIRQL DeviceListIrql, DataIrql;
  70. NTSTATUS ntStatus;
  71. ExAcquireFastMutex(&fdoExtension->ResetMutex);
  72. #if DBG
  73. InterlockedIncrement(&fdoExtension->ulWorkItemCount);
  74. #endif
  75. //
  76. // dont check if alloc failed here, its not critical
  77. //
  78. //
  79. // go through each children, and do whats necessry (reconnect/cleanup)
  80. //
  81. KeAcquireSpinLock(&fdoExtension->DeviceListLock, &DeviceListIrql);
  82. if (fdoExtension->DeviceListSize == 0) {
  83. DEBUGPRINT1(("Sbp2Port:Sbp2BusResetNotification, NO PDOs, exiting..\n"));
  84. goto Exit_Sbp2BusResetNotificationWorker;
  85. }
  86. for (i = 0;i < fdoExtension->DeviceListSize; i++) {
  87. if (!fdoExtension->DeviceList[i].DeviceObject) {
  88. break;
  89. }
  90. deviceExtension = fdoExtension->DeviceList[i].DeviceObject->DeviceExtension;
  91. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED) ||
  92. !TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_INITIALIZED)){
  93. continue;
  94. }
  95. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  96. ntStatus = IoAcquireRemoveLock(&deviceExtension->RemoveLock, NULL);
  97. if (!NT_SUCCESS(ntStatus))
  98. continue;
  99. //
  100. // if this a login-per-use device, we might be logged at the moment
  101. // so we do need to re-init but not reconnect
  102. //
  103. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_STOPPED)) {
  104. doReconnect = FALSE;
  105. } else {
  106. //
  107. // Turn on the RESET & RECONNECT flags, and turn off the LOGIN
  108. // flag just in case the reset interrupted a previous (re-)LOGIN.
  109. // All address mappings are invalidated after a reset
  110. //
  111. KeAcquireSpinLock(&deviceExtension->ExtensionDataSpinLock, &DataIrql);
  112. CLEAR_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_LOGIN_IN_PROGRESS);
  113. SET_FLAG(deviceExtension->DeviceFlags, (DEVICE_FLAG_RESET_IN_PROGRESS | DEVICE_FLAG_RECONNECT));
  114. KeReleaseSpinLock(&deviceExtension->ExtensionDataSpinLock, DataIrql);
  115. doReconnect = TRUE;
  116. }
  117. KeReleaseSpinLock(&fdoExtension->DeviceListLock, DeviceListIrql);
  118. DEBUGPRINT1((
  119. "\nSbp2Port: BusResetNotification: ext=x%x, lun=x%x\n",
  120. deviceExtension,
  121. deviceExtension->DeviceInfo->Lun.u.LowPart
  122. ));
  123. Sbp2DeferPendingRequest(deviceExtension, NULL);
  124. Sbp2CleanDeviceExtension(deviceExtension->DeviceObject,FALSE);
  125. //
  126. // all the resident 1394 memory addresses's that we have, are
  127. // now invalidated... So we need to free them and re-allocate
  128. // them
  129. Sbp2InitializeDeviceExtension(deviceExtension);
  130. if (doReconnect) {
  131. deviceExtension->DueTime.HighPart = -1;
  132. deviceExtension->DueTime.LowPart = -((deviceExtension->DeviceInfo->UnitCharacteristics.u.LowPart >> 8) & 0x000000FF) * 1000 * 1000 * 5;
  133. KeSetTimer(&deviceExtension->DeviceManagementTimer,deviceExtension->DueTime,&deviceExtension->DeviceManagementTimeoutDpc);
  134. Sbp2ManagementTransaction(deviceExtension, TRANSACTION_RECONNECT);
  135. } else {
  136. DEBUGPRINT1(("Sbp2Port:Sbp2BusResetNotification, NO need for reconnect, device stopped\n"));
  137. SET_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_STOPPED);
  138. }
  139. KeAcquireSpinLock(&fdoExtension->DeviceListLock, &DeviceListIrql);
  140. IoReleaseRemoveLock(&deviceExtension->RemoveLock, NULL);
  141. }
  142. Exit_Sbp2BusResetNotificationWorker:
  143. KeReleaseSpinLock(&fdoExtension->DeviceListLock, DeviceListIrql);
  144. #if DBG
  145. InterlockedDecrement(&fdoExtension->ulWorkItemCount);
  146. #endif
  147. ExReleaseFastMutex(&fdoExtension->ResetMutex);
  148. IoFreeWorkItem(WorkItem);
  149. IoReleaseRemoveLock(&fdoExtension->RemoveLock, NULL);
  150. return;
  151. }
  152. VOID
  153. Sbp2DeferPendingRequest(
  154. IN PDEVICE_EXTENSION DeviceExtension,
  155. IN PIRP Irp
  156. )
  157. {
  158. KIRQL oldIrql;
  159. //
  160. // If the queue is locked, it means that we might be trying to process
  161. // a power request. We cannot abort it, since that would prevent the
  162. // device from powering up/down. So save the SRB and irp, free the
  163. // context, and then after we are done-reinitializing, call StartIo
  164. // directly with the power request
  165. //
  166. if (TEST_FLAG (DeviceExtension->DeviceFlags, DEVICE_FLAG_QUEUE_LOCKED)) {
  167. KeAcquireSpinLock (&DeviceExtension->OrbListSpinLock, &oldIrql);
  168. if (!IsListEmpty (&DeviceExtension->PendingOrbList)) {
  169. PASYNC_REQUEST_CONTEXT tail = \
  170. RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Flink,OrbList);
  171. ASSERT (Irp == NULL);
  172. if (TEST_FLAG(tail->Srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE)) {
  173. DEBUGPRINT1((
  174. "Sbp2Port: DeferPendingReq: ext=x%p, defer irp=x%p cdb=x%x\n",
  175. DeviceExtension,
  176. tail->Srb->OriginalRequest,
  177. tail->Srb->Cdb[0]
  178. ));
  179. ASSERT (DeviceExtension->DeferredPowerRequest == NULL);
  180. DeviceExtension->DeferredPowerRequest =
  181. tail->Srb->OriginalRequest;
  182. //
  183. // Since a bus reset has occured it's safe to remove the
  184. // pending ORB from the list... this only works if there
  185. // is only one pending ORB (the power one)
  186. //
  187. ASSERT (tail->OrbList.Flink == tail->OrbList.Blink);
  188. tail->Srb = NULL;
  189. CLEAR_FLAG (tail->Flags, ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  190. KeCancelTimer (&tail->Timer);
  191. FreeAsyncRequestContext (DeviceExtension, tail);
  192. InitializeListHead (&DeviceExtension->PendingOrbList);
  193. } else {
  194. DeviceExtension->DeferredPowerRequest = NULL;
  195. }
  196. } else if (Irp) {
  197. DEBUGPRINT1((
  198. "Sbp2Port: DeferPendingReq: ext=x%p, defer irp=x%p\n",
  199. DeviceExtension,
  200. Irp
  201. ));
  202. ASSERT (DeviceExtension->DeferredPowerRequest == NULL);
  203. DeviceExtension->DeferredPowerRequest = Irp;
  204. }
  205. KeReleaseSpinLock (&DeviceExtension->OrbListSpinLock, oldIrql);
  206. }
  207. }
  208. NTSTATUS
  209. Sbp2Get1394ConfigInfo(
  210. IN PFDO_DEVICE_EXTENSION DeviceExtension,
  211. IN OUT PSBP2_REQUEST Sbp2Req
  212. )
  213. /*++
  214. Routine Description:
  215. Reads the configuration ROM from the SBP2 device. Retrieve any SBP2 required info
  216. for accessing the device and updates our device extension.
  217. Arguments:
  218. DeviceExtension - Pointer to device extension.
  219. Sbp2Req - Sbp2 request packet to read/parse a text leaf for a give key. When this parameter is defined
  220. this routine does NOT re-enumerate the crom, looking for pdos and sbp2 keys
  221. Return Value:
  222. NTSTATUS
  223. --*/
  224. {
  225. PDEVICE_INFORMATION devInfo, firstDevInfo;
  226. NTSTATUS status;
  227. ULONG directoryLength, vendorLeafLength, modelLeafLength,
  228. depDirLength, devListSize = DeviceExtension->DeviceListSize;
  229. ULONG i,j,dirInfoQuad;
  230. ULONG currentGeneration;
  231. ULONG unitDirEntries = 0;
  232. BOOLEAN sbp2Device = FALSE;
  233. BOOLEAN firstOne = FALSE;
  234. PVOID unitDirectory = NULL;
  235. PVOID unitDependentDirectory = NULL;
  236. PVOID modelLeaf = NULL;
  237. PVOID vendorLeaf = NULL;
  238. IO_ADDRESS cromOffset, cromOffset1;
  239. ULONG offset;
  240. PIRBIRP packet = NULL;
  241. AllocateIrpAndIrb ((PDEVICE_EXTENSION) DeviceExtension, &packet);
  242. if (!packet) {
  243. return STATUS_INSUFFICIENT_RESOURCES;
  244. }
  245. //
  246. // find out how much configuration space we need by setting lengths to zero.
  247. //
  248. packet->Irb->FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
  249. packet->Irb->Flags = 0;
  250. packet->Irb->u.GetConfigurationInformation.UnitDirectoryBufferSize = 0;
  251. packet->Irb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize = 0;
  252. packet->Irb->u.GetConfigurationInformation.VendorLeafBufferSize = 0;
  253. packet->Irb->u.GetConfigurationInformation.ModelLeafBufferSize = 0;
  254. status = Sbp2SendRequest(
  255. (PDEVICE_EXTENSION) DeviceExtension,
  256. packet,
  257. SYNC_1394_REQUEST
  258. );
  259. if (!NT_SUCCESS(status)) {
  260. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: err=x%x getting cfg info (1)\n", status));
  261. goto exit1394Config;
  262. }
  263. //
  264. // Now go thru and allocate what we need to so we can get our info.
  265. //
  266. if (packet->Irb->u.GetConfigurationInformation.UnitDirectoryBufferSize) {
  267. unitDirectory = ExAllocatePool(NonPagedPool, packet->Irb->u.GetConfigurationInformation.UnitDirectoryBufferSize);
  268. if (!unitDirectory) {
  269. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: alloc UnitDir me failed\n"));
  270. status = STATUS_INSUFFICIENT_RESOURCES;
  271. goto exit1394Config;
  272. }
  273. } else {
  274. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: no unit dir, bad dev\n"));
  275. status = STATUS_BAD_DEVICE_TYPE;
  276. goto exit1394Config;
  277. }
  278. if (packet->Irb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize) {
  279. unitDependentDirectory = ExAllocatePool(NonPagedPool, packet->Irb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize);
  280. if (!unitDependentDirectory) {
  281. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: alloc UnitDepDir mem failed\n"));
  282. status = STATUS_INSUFFICIENT_RESOURCES;
  283. goto exit1394Config;
  284. }
  285. }
  286. if (packet->Irb->u.GetConfigurationInformation.VendorLeafBufferSize) {
  287. vendorLeaf = ExAllocatePool(NonPagedPool, packet->Irb->u.GetConfigurationInformation.VendorLeafBufferSize);
  288. if (!vendorLeaf) {
  289. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: alloc VendorLeaf mem failed\n"));
  290. status = STATUS_INSUFFICIENT_RESOURCES;
  291. goto exit1394Config;
  292. }
  293. vendorLeafLength = packet->Irb->u.GetConfigurationInformation.VendorLeafBufferSize;
  294. }
  295. if (packet->Irb->u.GetConfigurationInformation.ModelLeafBufferSize) {
  296. modelLeaf = ExAllocatePool(NonPagedPool, packet->Irb->u.GetConfigurationInformation.ModelLeafBufferSize);
  297. if (!modelLeaf) {
  298. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: alloc ModelLeaf mem failed\n"));
  299. status = STATUS_INSUFFICIENT_RESOURCES;
  300. goto exit1394Config;
  301. }
  302. modelLeafLength = packet->Irb->u.GetConfigurationInformation.ModelLeafBufferSize;
  303. }
  304. //
  305. // Now resubmit the Irb with the appropriate pointers inside
  306. //
  307. packet->Irb->FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
  308. packet->Irb->Flags = 0;
  309. packet->Irb->u.GetConfigurationInformation.ConfigRom = &DeviceExtension->ConfigRom;
  310. packet->Irb->u.GetConfigurationInformation.UnitDirectory = unitDirectory;
  311. packet->Irb->u.GetConfigurationInformation.UnitDependentDirectory = unitDependentDirectory;
  312. packet->Irb->u.GetConfigurationInformation.VendorLeaf = vendorLeaf;
  313. packet->Irb->u.GetConfigurationInformation.ModelLeaf = modelLeaf;
  314. status = Sbp2SendRequest(
  315. (PDEVICE_EXTENSION) DeviceExtension,
  316. packet,
  317. SYNC_1394_REQUEST
  318. );
  319. if (!NT_SUCCESS(status)) {
  320. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: error=x%x getting cfg info (2)\n", status));
  321. goto exit1394Config;
  322. }
  323. //
  324. // get generation count..
  325. //
  326. packet->Irb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
  327. packet->Irb->Flags = 0;
  328. status = Sbp2SendRequest(
  329. (PDEVICE_EXTENSION) DeviceExtension,
  330. packet,
  331. SYNC_1394_REQUEST
  332. );
  333. if (!NT_SUCCESS(status)) {
  334. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: err=x%x getting gen #\n", status));
  335. goto exit1394Config;
  336. }
  337. currentGeneration = packet->Irb->u.GetGenerationCount.GenerationCount;
  338. cromOffset = packet->Irb->u.GetConfigurationInformation.UnitDirectoryLocation;
  339. if (!Sbp2Req) {
  340. //
  341. // run through the list amd free any model leafs we have seen before
  342. //
  343. for (i = 0; i < DeviceExtension->DeviceListSize; i++) {
  344. devInfo = &DeviceExtension->DeviceList[i];
  345. if (devInfo->ModelLeaf) {
  346. ExFreePool(devInfo->ModelLeaf);
  347. devInfo->ModelLeaf = NULL;
  348. }
  349. }
  350. if (DeviceExtension->VendorLeaf) {
  351. ExFreePool(DeviceExtension->VendorLeaf);
  352. DeviceExtension->VendorLeaf = NULL;
  353. }
  354. devListSize = 0;
  355. DeviceExtension->VendorLeaf = vendorLeaf;
  356. if (vendorLeaf != NULL) {
  357. DeviceExtension->VendorLeaf->TL_Length = (USHORT) vendorLeafLength;
  358. }
  359. }
  360. //
  361. // Now dwell deep in the configRom and get Lun number, uniqueId identifiers, etc
  362. // Since the bus driver returned the unit directory, we can just look at our local buffer
  363. // for all the info we need. We neeed to find the offsets withtin the unit directory
  364. //
  365. directoryLength = packet->Irb->u.GetConfigurationInformation.UnitDirectoryBufferSize >> 2;
  366. firstDevInfo = &DeviceExtension->DeviceList[0];
  367. for (i = 1; i < directoryLength; i++) {
  368. if (Sbp2Req) {
  369. //
  370. // look for this particular text leaf..
  371. //
  372. if (Sbp2Req->u.RetrieveTextLeaf.fulFlags & SBP2REQ_RETRIEVE_TEXT_LEAF_INDIRECT) {
  373. if ((*(((PULONG) unitDirectory)+i) & CONFIG_ROM_KEY_MASK) == TEXTUAL_LEAF_INDIRECT_KEY_SIGNATURE) {
  374. if ((*(((PULONG) unitDirectory-1)+i) & CONFIG_ROM_KEY_MASK) == Sbp2Req->u.RetrieveTextLeaf.Key) {
  375. DEBUGPRINT2(("Sbp2Port: Get1394CfgInfo: matched text leaf, req=x%x\n", Sbp2Req));
  376. offset = cromOffset.IA_Destination_Offset.Off_Low + i*sizeof(ULONG) + (ULONG) (bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK)
  377. *sizeof(ULONG));
  378. cromOffset.IA_Destination_Offset.Off_Low = offset;
  379. DEBUGPRINT2(("Sbp2Port: Get1394CfgInfo: unitDir=x%p, offset=x%x, key=x%x\n", unitDirectory,
  380. cromOffset.IA_Destination_Offset.Off_Low, *(((PULONG) unitDirectory)+i) ));
  381. Sbp2ParseTextLeaf(DeviceExtension,unitDirectory,
  382. &cromOffset,
  383. &Sbp2Req->u.RetrieveTextLeaf.Buffer);
  384. if (Sbp2Req->u.RetrieveTextLeaf.Buffer) {
  385. Sbp2Req->u.RetrieveTextLeaf.ulLength = \
  386. (bswap(*(PULONG) Sbp2Req->u.RetrieveTextLeaf.Buffer) >> 16) * sizeof(ULONG);
  387. status = STATUS_SUCCESS;
  388. } else {
  389. status = STATUS_UNSUCCESSFUL;
  390. }
  391. break;
  392. }
  393. }
  394. }
  395. continue;
  396. }
  397. devInfo = &DeviceExtension->DeviceList[devListSize];
  398. switch (*(((PULONG) unitDirectory)+i) & CONFIG_ROM_KEY_MASK) {
  399. case CSR_OFFSET_KEY_SIGNATURE:
  400. //
  401. // Found the command base offset. This is a quadlet offset from
  402. // the initial register space.
  403. //
  404. firstDevInfo->ManagementAgentBaseReg.BusAddress.Off_Low =
  405. (ULONG) (bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK)
  406. *sizeof(ULONG)) | INITIAL_REGISTER_SPACE_LO;
  407. sbp2Device = TRUE;
  408. break;
  409. case LUN_CHARACTERISTICS_KEY_SIGNATURE:
  410. firstDevInfo->UnitCharacteristics.QuadPart =
  411. (ULONG) bswap(*(((PULONG)unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
  412. unitDirEntries ++;
  413. break;
  414. case CMD_SET_ID_KEY_SIGNATURE:
  415. firstDevInfo->CmdSetId.QuadPart =
  416. (ULONG) bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
  417. unitDirEntries ++;
  418. break;
  419. case CMD_SET_SPEC_ID_KEY_SIGNATURE :
  420. firstDevInfo->CmdSetSpecId.QuadPart =
  421. (ULONG) bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
  422. unitDirEntries ++;
  423. break;
  424. case FIRMWARE_REVISION_KEY_SIGNATURE:
  425. if ((bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK) >> 8) == LSI_VENDOR_ID) {
  426. DEBUGPRINT2(("Sbp2Port: Get1394CfgInfo: found LSI bridge, maxXfer=128kb\n"));
  427. DeviceExtension->MaxClassTransferSize = (SBP2_MAX_DIRECT_BUFFER_SIZE+1)*2;
  428. }
  429. break;
  430. case LUN_KEY_SIGNATURE:
  431. devInfo->Lun.QuadPart =
  432. (ULONG) bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK);
  433. if ((devListSize == 0) && modelLeaf) {
  434. devInfo->ModelLeaf = modelLeaf;
  435. devInfo->ModelLeaf->TL_Length = (USHORT) modelLeafLength;
  436. } else {
  437. devInfo->ModelLeaf = NULL;
  438. }
  439. devInfo->VendorLeaf = vendorLeaf;
  440. devInfo->ConfigRom = &DeviceExtension->ConfigRom;
  441. devListSize++;
  442. devInfo->ManagementAgentBaseReg.BusAddress.Off_Low = \
  443. firstDevInfo->ManagementAgentBaseReg.BusAddress.Off_Low;
  444. devInfo->CmdSetId.QuadPart = firstDevInfo->CmdSetId.QuadPart;
  445. devInfo->CmdSetSpecId.QuadPart =
  446. firstDevInfo->CmdSetSpecId.QuadPart;
  447. devInfo->UnitCharacteristics.QuadPart = firstDevInfo->UnitCharacteristics.QuadPart;
  448. unitDirEntries ++;
  449. break;
  450. case LU_DIRECTORY_KEY_SIGNATURE:
  451. //
  452. // this device has logical unit subdirectories within its unit. Probably
  453. // has multiple units..
  454. // calculate offset to that LU dir..
  455. // If this is the first one, ignore it, we already got through the
  456. // GetConfiguration call..
  457. //
  458. if (firstOne == FALSE) {
  459. firstOne = TRUE;
  460. depDirLength = packet->Irb->u.GetConfigurationInformation.UnitDependentDirectoryBufferSize >> 2;
  461. //
  462. // parse the unit dep dir..we are looking for the LUN entry and the model leaf
  463. //
  464. for (j = 0;j < depDirLength; j++) {
  465. if ((*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_KEY_MASK) == LUN_KEY_SIGNATURE) {
  466. devInfo->Lun.QuadPart =
  467. (ULONG) bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK);
  468. devInfo->ConfigRom = &DeviceExtension->ConfigRom;
  469. if (devListSize > 0) {
  470. devInfo->ModelLeaf = NULL;
  471. } else if (modelLeaf){
  472. devInfo->ModelLeaf = modelLeaf;
  473. devInfo->ModelLeaf->TL_Length = (USHORT) modelLeafLength;
  474. }
  475. devInfo->VendorLeaf = vendorLeaf;
  476. devListSize++;
  477. devInfo->ManagementAgentBaseReg.BusAddress.Off_Low =
  478. firstDevInfo->ManagementAgentBaseReg.BusAddress.Off_Low;
  479. if (devInfo->CmdSetId.QuadPart == 0 ) {
  480. devInfo->CmdSetId.QuadPart = firstDevInfo->CmdSetId.QuadPart;
  481. }
  482. if (devInfo->CmdSetSpecId.QuadPart == 0 ) {
  483. devInfo->CmdSetSpecId.QuadPart = firstDevInfo->CmdSetSpecId.QuadPart;
  484. }
  485. if (devInfo->UnitCharacteristics.QuadPart == 0 ) {
  486. devInfo->UnitCharacteristics.QuadPart = firstDevInfo->UnitCharacteristics.QuadPart;
  487. }
  488. unitDirEntries ++;
  489. }
  490. switch (*(((PULONG) unitDependentDirectory)+j) &
  491. CONFIG_ROM_KEY_MASK) {
  492. case CMD_SET_ID_KEY_SIGNATURE:
  493. devInfo->CmdSetId.QuadPart =
  494. (ULONG) bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK);
  495. unitDirEntries ++;
  496. break;
  497. case CMD_SET_SPEC_ID_KEY_SIGNATURE:
  498. devInfo->CmdSetSpecId.QuadPart =
  499. (ULONG) bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK);
  500. unitDirEntries ++;
  501. break;
  502. case TEXTUAL_LEAF_INDIRECT_KEY_SIGNATURE:
  503. if ((*(((PULONG) unitDependentDirectory)+j-1) & CONFIG_ROM_KEY_MASK) == MODEL_ID_KEY_SIGNATURE) {
  504. if (devInfo->ModelLeaf == NULL) {
  505. //
  506. // special case. if the first LU is only present in unit dir, then the second
  507. // LU will be the first unit dependent dir , which means we have to parse
  508. // its model text
  509. //
  510. cromOffset1 = packet->Irb->u.GetConfigurationInformation.UnitDependentDirectoryLocation;
  511. cromOffset1.IA_Destination_Offset.Off_Low += j*sizeof(ULONG) + (ULONG) (bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK)
  512. *sizeof(ULONG));
  513. Sbp2ParseTextLeaf(DeviceExtension,unitDependentDirectory,
  514. &cromOffset1,
  515. &devInfo->ModelLeaf);
  516. }
  517. }
  518. break;
  519. default:
  520. break;
  521. } // switch
  522. }
  523. } else {
  524. //
  525. // read the crom and retrieve the unit dep dir
  526. //
  527. offset = cromOffset.IA_Destination_Offset.Off_Low + i*sizeof(ULONG) + (ULONG) (bswap(*(((PULONG) unitDirectory)+i) & CONFIG_ROM_OFFSET_MASK)
  528. *sizeof(ULONG));
  529. //
  530. // read LU dir header..
  531. //
  532. packet->Irb->u.AsyncRead.Mdl = IoAllocateMdl(unitDependentDirectory,
  533. depDirLength,
  534. FALSE,
  535. FALSE,
  536. NULL);
  537. MmBuildMdlForNonPagedPool(packet->Irb->u.AsyncRead.Mdl);
  538. packet->Irb->FunctionNumber = REQUEST_ASYNC_READ;
  539. packet->Irb->Flags = 0;
  540. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  541. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low = offset;
  542. packet->Irb->u.AsyncRead.nNumberOfBytesToRead = sizeof(ULONG);
  543. packet->Irb->u.AsyncRead.nBlockSize = 0;
  544. packet->Irb->u.AsyncRead.fulFlags = 0;
  545. packet->Irb->u.AsyncRead.ulGeneration = currentGeneration;
  546. packet->Irb->u.AsyncRead.nSpeed = SCODE_100_RATE;
  547. status = Sbp2SendRequest(
  548. (PDEVICE_EXTENSION)DeviceExtension,
  549. packet,
  550. SYNC_1394_REQUEST
  551. );
  552. if (!NT_SUCCESS(status)) {
  553. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: err=x%x getting cfg info (3)\n", status));
  554. IoFreeMdl (packet->Irb->u.AsyncRead.Mdl);
  555. goto exit1394Config;
  556. }
  557. dirInfoQuad = bswap (*(PULONG) unitDependentDirectory) >> 16;
  558. depDirLength = dirInfoQuad * sizeof(ULONG);
  559. IoFreeMdl (packet->Irb->u.AsyncRead.Mdl);
  560. if (depDirLength > 0x100) {
  561. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: unitDep dir 2 too big, len=x%x\n", depDirLength));
  562. goto exit1394Config;
  563. }
  564. ExFreePool (unitDependentDirectory);
  565. unitDependentDirectory = ExAllocatePoolWithTag(NonPagedPool,depDirLength+sizeof(ULONG),'2pbs');
  566. if (!unitDependentDirectory) {
  567. goto exit1394Config;
  568. }
  569. packet->Irb->u.AsyncRead.Mdl = IoAllocateMdl(unitDependentDirectory,
  570. depDirLength+sizeof(ULONG),
  571. FALSE,
  572. FALSE,
  573. NULL);
  574. MmBuildMdlForNonPagedPool (packet->Irb->u.AsyncRead.Mdl);
  575. //
  576. // read the rest of the unit dependent dir, one quadlet at a time...
  577. // parse as you read..
  578. //
  579. j = 1;
  580. do {
  581. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low = offset+j*sizeof(ULONG);
  582. ((PULONG) (((PMDL) (packet->Irb->u.AsyncRead.Mdl))->MappedSystemVa))++;
  583. ((PULONG) (((PMDL) (packet->Irb->u.AsyncRead.Mdl))->StartVa))++;
  584. status = Sbp2SendRequest(
  585. (PDEVICE_EXTENSION)DeviceExtension,
  586. packet,
  587. SYNC_1394_REQUEST
  588. );
  589. if (!NT_SUCCESS(status)) {
  590. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: err=x%x getting cfg info (4)\n", status));
  591. IoFreeMdl (packet->Irb->u.AsyncRead.Mdl);
  592. goto exit1394Config;
  593. }
  594. if ((*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_KEY_MASK) == LUN_KEY_SIGNATURE) {
  595. devInfo->Lun.QuadPart =
  596. (ULONG) bswap(*(((PULONG) unitDependentDirectory+j)) & CONFIG_ROM_OFFSET_MASK);
  597. devInfo->ModelLeaf = NULL;
  598. devInfo->VendorLeaf = vendorLeaf;
  599. devInfo->ConfigRom = &DeviceExtension->ConfigRom;
  600. devListSize++;
  601. devInfo->ManagementAgentBaseReg.BusAddress.Off_Low =
  602. firstDevInfo->ManagementAgentBaseReg.BusAddress.Off_Low;
  603. if (devInfo->CmdSetId.QuadPart == 0 ) {
  604. devInfo->CmdSetId.QuadPart = firstDevInfo->CmdSetId.QuadPart;
  605. }
  606. if (devInfo->CmdSetSpecId.QuadPart == 0 ) {
  607. devInfo->CmdSetSpecId.QuadPart = firstDevInfo->CmdSetSpecId.QuadPart;
  608. }
  609. if (devInfo->UnitCharacteristics.QuadPart == 0 ) {
  610. devInfo->UnitCharacteristics.QuadPart = firstDevInfo->UnitCharacteristics.QuadPart;
  611. }
  612. unitDirEntries ++;
  613. }
  614. switch (*(((PULONG) unitDependentDirectory)+j) &
  615. CONFIG_ROM_KEY_MASK) {
  616. case CMD_SET_ID_KEY_SIGNATURE:
  617. devInfo->CmdSetId.QuadPart =
  618. (ULONG) bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK);
  619. unitDirEntries ++;
  620. break;
  621. case CMD_SET_SPEC_ID_KEY_SIGNATURE:
  622. devInfo->CmdSetSpecId.QuadPart =
  623. (ULONG) bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK);
  624. unitDirEntries ++;
  625. break;
  626. case TEXTUAL_LEAF_INDIRECT_KEY_SIGNATURE:
  627. //
  628. // oh man, we run into a textual descriptor..
  629. // this means we need to parse a LU model descriptor from this..
  630. // make sure the quad behind it is a MODEL_ID...
  631. //
  632. if ((*(((PULONG) unitDependentDirectory)+j-1) & CONFIG_ROM_KEY_MASK) == MODEL_ID_KEY_SIGNATURE) {
  633. cromOffset1.IA_Destination_Offset.Off_Low = offset + j*sizeof(ULONG) + (ULONG) (bswap(*(((PULONG) unitDependentDirectory)+j) & CONFIG_ROM_OFFSET_MASK)
  634. *sizeof(ULONG));
  635. Sbp2ParseTextLeaf(DeviceExtension,unitDependentDirectory,
  636. &cromOffset1,
  637. &devInfo->ModelLeaf);
  638. }
  639. break;
  640. default:
  641. break;
  642. }
  643. j++;
  644. } while (j <= depDirLength / sizeof(ULONG));
  645. IoFreeMdl (packet->Irb->u.AsyncRead.Mdl);
  646. }
  647. break;
  648. default:
  649. break;
  650. } // switch
  651. }
  652. if (!Sbp2Req) {
  653. if (!sbp2Device || (unitDirEntries < SBP2_MIN_UNIT_DIR_ENTRIES)) {
  654. DEBUGPRINT1(("Sbp2Port: Get1394CfgInfo: bad/non-SBP2 dev, cRom missing unitDir info\n"));
  655. status = STATUS_BAD_DEVICE_TYPE;
  656. }
  657. }
  658. exit1394Config:
  659. if (packet) {
  660. DeAllocateIrpAndIrb ((PDEVICE_EXTENSION) DeviceExtension, packet);
  661. }
  662. if (unitDirectory) {
  663. ExFreePool (unitDirectory);
  664. }
  665. if (unitDependentDirectory) {
  666. ExFreePool (unitDependentDirectory);
  667. }
  668. if (!Sbp2Req) {
  669. DeviceExtension->DeviceListSize = devListSize;
  670. if (!NT_SUCCESS (status)) {
  671. if (vendorLeaf) {
  672. ExFreePool (vendorLeaf);
  673. }
  674. if (modelLeaf) {
  675. ExFreePool (modelLeaf);
  676. if (modelLeaf == DeviceExtension->DeviceList[0].ModelLeaf) {
  677. DeviceExtension->DeviceList[0].ModelLeaf = NULL;
  678. }
  679. }
  680. DeviceExtension->VendorLeaf = NULL;
  681. }
  682. } else {
  683. if (vendorLeaf) {
  684. ExFreePool (vendorLeaf);
  685. }
  686. if (modelLeaf) {
  687. ExFreePool (modelLeaf);
  688. }
  689. }
  690. return status;
  691. }
  692. VOID
  693. Sbp2ParseTextLeaf(
  694. PFDO_DEVICE_EXTENSION DeviceExtension,
  695. PVOID UnitDepDir,
  696. PIO_ADDRESS ModelLeafLocation,
  697. PVOID *ModelLeaf
  698. )
  699. {
  700. PIRBIRP packet = NULL;
  701. PVOID tModelLeaf;
  702. PTEXTUAL_LEAF leaf;
  703. ULONG leafLength,i, currentGeneration;
  704. ULONG temp;
  705. NTSTATUS status;
  706. AllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,&packet);
  707. if (!packet) {
  708. return;
  709. }
  710. //
  711. // get generation count..
  712. //
  713. packet->Irb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
  714. packet->Irb->Flags = 0;
  715. status = Sbp2SendRequest(
  716. (PDEVICE_EXTENSION) DeviceExtension,
  717. packet,
  718. SYNC_1394_REQUEST
  719. );
  720. if (!NT_SUCCESS(status)) {
  721. DeAllocateIrpAndIrb ((PDEVICE_EXTENSION) DeviceExtension, packet);
  722. DEBUGPRINT1(("Sbp2Port:Sbp2ParseModelLeaf: Error %x while trying to get generation number\n", status));
  723. return;
  724. }
  725. currentGeneration = packet->Irb->u.GetGenerationCount.GenerationCount;
  726. tModelLeaf = ExAllocatePoolWithTag(NonPagedPool,32,'2pbs');
  727. if (!tModelLeaf) {
  728. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,packet);
  729. return;
  730. }
  731. //
  732. // find out how big the model leaf is
  733. //
  734. packet->Irb->u.AsyncRead.Mdl = IoAllocateMdl(tModelLeaf,
  735. 32,
  736. FALSE,
  737. FALSE,
  738. NULL);
  739. MmBuildMdlForNonPagedPool(packet->Irb->u.AsyncRead.Mdl);
  740. packet->Irb->FunctionNumber = REQUEST_ASYNC_READ;
  741. packet->Irb->Flags = 0;
  742. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  743. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low = \
  744. ModelLeafLocation->IA_Destination_Offset.Off_Low;
  745. packet->Irb->u.AsyncRead.nNumberOfBytesToRead = sizeof(ULONG);
  746. packet->Irb->u.AsyncRead.nBlockSize = 0;
  747. packet->Irb->u.AsyncRead.fulFlags = 0;
  748. packet->Irb->u.AsyncRead.ulGeneration = currentGeneration;
  749. packet->Irb->u.AsyncRead.nSpeed = SCODE_100_RATE;
  750. status = Sbp2SendRequest(
  751. (PDEVICE_EXTENSION) DeviceExtension,
  752. packet,
  753. SYNC_1394_REQUEST
  754. );
  755. if (!NT_SUCCESS(status)) {
  756. DEBUGPRINT1(("Sbp2Get1394ConfigInfo: Error %x while trying to get LU dir model LEAF\n", status));
  757. ExFreePool(tModelLeaf);
  758. IoFreeMdl(packet->Irb->u.AsyncRead.Mdl);
  759. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,packet);
  760. return;
  761. }
  762. leafLength = (bswap(*(PULONG) tModelLeaf) >> 16) * sizeof(ULONG);
  763. temp = *((PULONG) tModelLeaf);
  764. if ((leafLength+sizeof(ULONG)) > 32) {
  765. //
  766. // re allocate the mdl to fit the whole leaf
  767. //
  768. IoFreeMdl(packet->Irb->u.AsyncRead.Mdl);
  769. ExFreePool(tModelLeaf);
  770. tModelLeaf = ExAllocatePoolWithTag(NonPagedPool,leafLength+sizeof(ULONG),'2pbs');
  771. if (!tModelLeaf) {
  772. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,packet);
  773. return;
  774. }
  775. packet->Irb->u.AsyncRead.Mdl = IoAllocateMdl(tModelLeaf,
  776. leafLength+sizeof(ULONG),
  777. FALSE,
  778. FALSE,
  779. NULL);
  780. MmBuildMdlForNonPagedPool(packet->Irb->u.AsyncRead.Mdl);
  781. }
  782. //
  783. // read the entire model leaf...
  784. //
  785. i=1;
  786. *((PULONG)tModelLeaf) = temp;
  787. do {
  788. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low = \
  789. ModelLeafLocation->IA_Destination_Offset.Off_Low+i*sizeof(ULONG);
  790. ((PULONG) (((PMDL) (packet->Irb->u.AsyncRead.Mdl))->MappedSystemVa))++;
  791. ((PULONG) (((PMDL) (packet->Irb->u.AsyncRead.Mdl))->StartVa))++;
  792. status = Sbp2SendRequest(
  793. (PDEVICE_EXTENSION) DeviceExtension,
  794. packet,
  795. SYNC_1394_REQUEST
  796. );
  797. if (!NT_SUCCESS(status)) {
  798. DEBUGPRINT1(("Sbp2Get1394ConfigInfo: Error %x while trying to get LU dir model LEAF\n", status));
  799. ExFreePool(tModelLeaf);
  800. IoFreeMdl(packet->Irb->u.AsyncRead.Mdl);
  801. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,packet);
  802. return;
  803. }
  804. i++;
  805. } while (i<= leafLength/4);
  806. leaf = (PTEXTUAL_LEAF) tModelLeaf;
  807. leaf->TL_Length = (USHORT)leafLength;
  808. *ModelLeaf = tModelLeaf;
  809. IoFreeMdl(packet->Irb->u.AsyncRead.Mdl);
  810. DeAllocateIrpAndIrb((PDEVICE_EXTENSION)DeviceExtension,packet);
  811. }
  812. NTSTATUS
  813. Sbp2UpdateNodeInformation(
  814. PDEVICE_EXTENSION DeviceExtension
  815. )
  816. /*++
  817. Routine Description:
  818. Gets node ID and generation information, volatile between bus resets
  819. Arguments:
  820. DeviceExtension - Pointer to device extension.
  821. Return Value:
  822. NTSTATUS
  823. --*/
  824. {
  825. KIRQL oldIrql;
  826. PIRBIRP packet = NULL;
  827. NTSTATUS status;
  828. PASYNC_REQUEST_CONTEXT nextListItem,currentListItem ;
  829. AllocateIrpAndIrb (DeviceExtension, &packet);
  830. if (!packet) {
  831. return STATUS_INSUFFICIENT_RESOURCES;
  832. }
  833. //
  834. // Make a call to determine what the generation # is on the bus,
  835. // followed by a call to find out about ourself (config rom info)
  836. //
  837. packet->Irb->FunctionNumber = REQUEST_GET_GENERATION_COUNT;
  838. packet->Irb->Flags = 0;
  839. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  840. if (!NT_SUCCESS(status)) {
  841. DEBUGPRINT1((
  842. "Sbp2Port: UpdateNodeInfo: ext=%p, err=x%x getting gen(2)\n",
  843. DeviceExtension,
  844. status
  845. ));
  846. goto exitGetNodeInfo;
  847. }
  848. KeAcquireSpinLock (&DeviceExtension->ExtensionDataSpinLock, &oldIrql);
  849. DeviceExtension->CurrentGeneration =
  850. packet->Irb->u.GetGenerationCount.GenerationCount;
  851. KeReleaseSpinLock(&DeviceExtension->ExtensionDataSpinLock,oldIrql);
  852. //
  853. // Get the initiator id (Sbp2port is the initiator in all 1394
  854. // transactions)
  855. //
  856. packet->Irb->FunctionNumber = REQUEST_GET_ADDR_FROM_DEVICE_OBJECT;
  857. packet->Irb->u.Get1394AddressFromDeviceObject.fulFlags = USE_LOCAL_NODE;
  858. packet->Irb->Flags = 0;
  859. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  860. if (!NT_SUCCESS(status)) {
  861. DEBUGPRINT1((
  862. "Sbp2Port: UpdateNodeInfo: ext=%p, err=x%x getting node id\n",
  863. DeviceExtension,
  864. status
  865. ));
  866. goto exitGetNodeInfo;
  867. }
  868. KeAcquireSpinLock (&DeviceExtension->ExtensionDataSpinLock, &oldIrql);
  869. DeviceExtension->InitiatorAddressId =
  870. packet->Irb->u.Get1394AddressFromDeviceObject.NodeAddress;
  871. KeReleaseSpinLock (&DeviceExtension->ExtensionDataSpinLock, oldIrql);
  872. DEBUGPRINT2((
  873. "Sbp2Port: UpdateNodeInfo: ext=x%p, gen=%d, initiatorId=x%x\n",
  874. DeviceExtension,
  875. DeviceExtension->CurrentGeneration,
  876. DeviceExtension->InitiatorAddressId
  877. ));
  878. //
  879. // If we have active requests pending, we have to traverse the
  880. // list and update their addresses...
  881. //
  882. KeAcquireSpinLock (&DeviceExtension->OrbListSpinLock, &oldIrql);
  883. if (!IsListEmpty (&DeviceExtension->PendingOrbList)) {
  884. nextListItem = RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Flink,OrbList);
  885. do {
  886. currentListItem = nextListItem;
  887. //
  888. // Now update the cmdOrb fields with the new addresses...
  889. // Since they are stored in BigEndian (awaiting to be fetched)
  890. // so when we correct their address, this taken into consideration
  891. //
  892. // update the data descriptor address
  893. octbswap (currentListItem->CmdOrb->DataDescriptor);
  894. currentListItem->CmdOrb->DataDescriptor.BusAddress.NodeId = DeviceExtension->InitiatorAddressId;
  895. octbswap (currentListItem->CmdOrb->DataDescriptor);
  896. nextListItem = (PASYNC_REQUEST_CONTEXT) currentListItem->OrbList.Flink;
  897. } while (currentListItem != RETRIEVE_CONTEXT(DeviceExtension->PendingOrbList.Blink,OrbList));
  898. }
  899. KeReleaseSpinLock (&DeviceExtension->OrbListSpinLock, oldIrql);
  900. exitGetNodeInfo:
  901. DeAllocateIrpAndIrb (DeviceExtension, packet);
  902. return status;
  903. }
  904. NTSTATUS
  905. Sbp2ManagementTransaction(
  906. IN PDEVICE_EXTENSION DeviceExtension,
  907. IN ULONG Type
  908. )
  909. /*++
  910. Routine Description:
  911. This routine creates and sends down management ORB's. According to the ORB type
  912. it will send the request synch/asynchronously. After a management ORB completes
  913. the bus driver will call the SBp2ManagementStatusCallback
  914. Arguments:
  915. deviceExtension - Sbp2 device extension
  916. Type - Type of Managament SBP2 transaction
  917. Return Value:
  918. NTSTATUS
  919. --*/
  920. {
  921. PDEVICE_OBJECT deviceObject = DeviceExtension->DeviceObject;
  922. NTSTATUS status;
  923. KIRQL cIrql;
  924. PORB_MNG sbpRequest = DeviceExtension->ManagementOrb;
  925. PORB_QUERY_LOGIN queryOrb;
  926. PORB_LOGIN loginOrb;
  927. LARGE_INTEGER waitValue;
  928. LONG temp;
  929. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED)) {
  930. return STATUS_DEVICE_DOES_NOT_EXIST;
  931. }
  932. RtlZeroMemory (sbpRequest, sizeof (ORB_MNG));
  933. //
  934. // Get the 1394 address for our request ORB and the responce ORB's(for login) from the target
  935. // setup the Type in the status context
  936. //
  937. DeviceExtension->GlobalStatusContext.TransactionType = Type;
  938. switch (Type) {
  939. case TRANSACTION_LOGIN:
  940. loginOrb = (PORB_LOGIN) sbpRequest;
  941. //
  942. // indicate in our device extension that we are doing a login
  943. //
  944. KeAcquireSpinLock(&DeviceExtension->ExtensionDataSpinLock,&cIrql);
  945. SET_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_LOGIN_IN_PROGRESS);
  946. KeReleaseSpinLock(&DeviceExtension->ExtensionDataSpinLock, cIrql);
  947. RtlZeroMemory (DeviceExtension->LoginResponse, sizeof(LOGIN_RESPONSE));
  948. //
  949. // Fill in the login ORB, the address of the response buffer
  950. //
  951. loginOrb->LoginResponseAddress.BusAddress = DeviceExtension->LoginRespContext.Address.BusAddress;
  952. loginOrb->LengthInfo.u.HighPart= 0 ; // password length is 0
  953. loginOrb->LengthInfo.u.LowPart= sizeof(LOGIN_RESPONSE); //set size of response buffer
  954. //
  955. // Set the notify bit ot one, Exclusive bit to 0, rq_fmt bit to 0
  956. // Then set our LUN number
  957. //
  958. loginOrb->OrbInfo.QuadPart =0;
  959. loginOrb->OrbInfo.u.HighPart |= (ORB_NOTIFY_BIT_MASK | ORB_MNG_RQ_FMT_VALUE);
  960. //
  961. // If this is an rbc or direct access device then set the exclusive
  962. // login bit.
  963. //
  964. // NOTE: Win2k & Win98SE are checking InquiryData.DeviceType,
  965. // but during StartDevice() we are doing a login before we
  966. // do an INQUIRY, so this field was always zeroed & we log
  967. // in exclusively on those platforms
  968. //
  969. switch (DeviceExtension->DeviceInfo->Lun.u.HighPart & 0x001f) {
  970. case RBC_DEVICE:
  971. case DIRECT_ACCESS_DEVICE:
  972. loginOrb->OrbInfo.u.HighPart |= ORB_MNG_EXCLUSIVE_BIT_MASK;
  973. break;
  974. }
  975. loginOrb->OrbInfo.u.LowPart = DeviceExtension->DeviceInfo->Lun.u.LowPart;
  976. //
  977. // We don't support passwords yet
  978. //
  979. #if PASSWORD_SUPPORT
  980. if (DeviceExtension->Exclusive & EXCLUSIVE_FLAG_SET) {
  981. loginOrb->Password.u.HighQuad.QuadPart =
  982. DeviceExtension->DeviceInfo->ConfigRom->CR_Node_UniqueID[1];
  983. loginOrb->Password.u.LowQuad.QuadPart =
  984. DeviceExtension->DeviceInfo->ConfigRom->CR_Node_UniqueID[0];
  985. DEBUGPRINT1(("Sbp2Port: MgmtXact: password=x%x%x, len=x%x\n",
  986. loginOrb->Password.u.HighQuad.QuadPart,
  987. loginOrb->Password.u.LowQuad.QuadPart,
  988. loginOrb->LengthInfo.u.HighPart));
  989. } else {
  990. loginOrb->Password.OctletPart = 0;
  991. }
  992. #else
  993. loginOrb->Password.OctletPart = 0;
  994. #endif
  995. //
  996. // Set the type of the management transaction in the ORB
  997. //
  998. loginOrb->OrbInfo.u.HighPart |=0x00FF & Type;
  999. #if PASSWORD_SUPPORT
  1000. octbswap(loginOrb->Password);
  1001. #endif
  1002. octbswap(loginOrb->LoginResponseAddress);
  1003. loginOrb->OrbInfo.QuadPart = bswap(loginOrb->OrbInfo.QuadPart);
  1004. loginOrb->LengthInfo.QuadPart = bswap(loginOrb->LengthInfo.QuadPart);
  1005. sbpRequest->StatusBlockAddress.BusAddress = DeviceExtension->GlobalStatusContext.Address.BusAddress;
  1006. octbswap(loginOrb->StatusBlockAddress);
  1007. //
  1008. // write to the Management Agent register, to signal that a management ORB is ready
  1009. // if we are doing this during a reset, it will have to be done asynchronously
  1010. //
  1011. if (!TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_RESET_IN_PROGRESS)) {
  1012. //
  1013. // Synchronous login case. We will wait on an event until our DPC associated with the login status, fires and sets the event
  1014. //
  1015. ASSERT(InterlockedIncrement(&DeviceExtension->ulPendingEvents) == 1);
  1016. KeInitializeEvent(DeviceExtension->ManagementOrbContext.Reserved, NotificationEvent, FALSE);
  1017. DEBUGPRINT2(("Sbp2Port: MgmtXact: waiting for login status\n"));
  1018. status = Sbp2AccessRegister(DeviceExtension,&DeviceExtension->ManagementOrbContext.Address,MANAGEMENT_AGENT_REG | REG_WRITE_SYNC);
  1019. if (!NT_SUCCESS(status)) {
  1020. DEBUGPRINT2(("Sbp2Port: MgmtXact: can't access mgmt reg ext=x%p, FAIL LOGIN\n", DeviceExtension));
  1021. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1022. return status;
  1023. }
  1024. //
  1025. // set the login timeout value, to what we read from the registry (LOGIN_TIMEOUT)
  1026. // divide by 2, to convert to seconds
  1027. //
  1028. temp = max (SBP2_LOGIN_TIMEOUT, (DeviceExtension->DeviceInfo->UnitCharacteristics.u.LowPart >> 9));
  1029. waitValue.QuadPart = -temp * 1000 * 1000 * 10;
  1030. status = KeWaitForSingleObject(DeviceExtension->ManagementOrbContext.Reserved,Executive,KernelMode,FALSE,&waitValue);
  1031. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1032. if (status == STATUS_TIMEOUT) {
  1033. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_LOGIN_IN_PROGRESS)) {
  1034. DEBUGPRINT1(("Sbp2Port: MgmtXact: login timed out, ext=x%p\n", DeviceExtension));
  1035. //
  1036. // In Win2k, etc we would mark the device stopped here &
  1037. // turn off the login in progress flag. Since this timeout
  1038. // might be the result of a bus reset, we want to allow
  1039. // for a retry here.
  1040. //
  1041. status = STATUS_UNSUCCESSFUL;
  1042. } else {
  1043. status = STATUS_SUCCESS;
  1044. }
  1045. }
  1046. if (!NT_SUCCESS(DeviceExtension->LastTransactionStatus)) {
  1047. status = DeviceExtension->LastTransactionStatus;
  1048. } else if (!DeviceExtension->LoginResponse->Csr_Off_Low.QuadPart) {
  1049. status = STATUS_UNSUCCESSFUL;
  1050. }
  1051. return status;
  1052. } else {
  1053. //
  1054. // Asynchronous login case. Start a timer to track the login..
  1055. //
  1056. // get the Management_Timeout values from the ConfigRom LUN Characteristics entry
  1057. //
  1058. DeviceExtension->DueTime.HighPart = -1;
  1059. DeviceExtension->DueTime.LowPart = -(DeviceExtension->DeviceInfo->UnitCharacteristics.u.LowPart >> 9) * 1000 * 1000 * 10; // divide by 2, to convert to seconds;
  1060. KeSetTimer(&DeviceExtension->DeviceManagementTimer,DeviceExtension->DueTime,&DeviceExtension->DeviceManagementTimeoutDpc);
  1061. status = Sbp2AccessRegister(DeviceExtension,&DeviceExtension->ManagementOrbContext.Address,MANAGEMENT_AGENT_REG | REG_WRITE_ASYNC);
  1062. if (!NT_SUCCESS(status)) {
  1063. DEBUGPRINT2((
  1064. "Sbp2Port: MgmtXact: can't access mgmt reg ext=x%p, FAIL LOGIN\n",
  1065. DeviceExtension
  1066. ));
  1067. return status;
  1068. }
  1069. //
  1070. // for now return pending. the callback will complete this request
  1071. //
  1072. return STATUS_PENDING;
  1073. }
  1074. break;
  1075. case TRANSACTION_QUERY_LOGINS:
  1076. queryOrb = (PORB_QUERY_LOGIN) sbpRequest;
  1077. RtlZeroMemory(
  1078. DeviceExtension->QueryLoginResponse,
  1079. sizeof(QUERY_LOGIN_RESPONSE)
  1080. );
  1081. //
  1082. // Fill in the login ORB, the address of the response buffer
  1083. //
  1084. queryOrb->QueryResponseAddress.BusAddress = DeviceExtension->QueryLoginRespContext.Address.BusAddress;
  1085. queryOrb->LengthInfo.u.HighPart= 0 ; // password length is 0
  1086. queryOrb->LengthInfo.u.LowPart= sizeof(QUERY_LOGIN_RESPONSE); //set size of response buffer
  1087. //
  1088. // Set the notify bit ot one, Exclusive bit to 0, rq_fmt bit to 0
  1089. // Then set our LUN number
  1090. //
  1091. queryOrb->OrbInfo.QuadPart =0;
  1092. queryOrb->OrbInfo.u.HighPart |= (ORB_NOTIFY_BIT_MASK | ORB_MNG_RQ_FMT_VALUE);
  1093. queryOrb->OrbInfo.u.LowPart = DeviceExtension->DeviceInfo->Lun.u.LowPart;
  1094. queryOrb->Reserved.OctletPart = 0;
  1095. //
  1096. // Set the type of the management transaction in the ORB
  1097. //
  1098. queryOrb->OrbInfo.u.HighPart |=0x00FF & Type;
  1099. octbswap(queryOrb->QueryResponseAddress);
  1100. queryOrb->OrbInfo.QuadPart = bswap(queryOrb->OrbInfo.QuadPart);
  1101. queryOrb->LengthInfo.QuadPart = bswap(queryOrb->LengthInfo.QuadPart);
  1102. queryOrb->StatusBlockAddress.BusAddress = DeviceExtension->ManagementOrbStatusContext.Address.BusAddress;
  1103. octbswap(queryOrb->StatusBlockAddress);
  1104. //
  1105. // write to the Management Agent register, to signal that a management ORB is ready
  1106. //
  1107. ASSERT(InterlockedIncrement(&DeviceExtension->ulPendingEvents) == 1);
  1108. waitValue.QuadPart = -8 * 1000 * 1000 * 10;
  1109. KeInitializeEvent(DeviceExtension->ManagementOrbContext.Reserved, NotificationEvent, FALSE);
  1110. status = Sbp2AccessRegister(DeviceExtension,&DeviceExtension->ManagementOrbContext.Address,MANAGEMENT_AGENT_REG | REG_WRITE_SYNC);
  1111. if (!NT_SUCCESS(status)) {
  1112. DEBUGPRINT2((
  1113. "Sbp2Port: MgmtXact: QUERY_LOGIN, can't access mgmt reg, sts=x%x\n",
  1114. status
  1115. ));
  1116. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1117. return status;
  1118. }
  1119. status = KeWaitForSingleObject(DeviceExtension->ManagementOrbContext.Reserved,Executive,KernelMode,FALSE,&waitValue);
  1120. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1121. if (status == STATUS_TIMEOUT) {
  1122. DEBUGPRINT2((
  1123. "Sbp2Port: MgmtXact: QUERY_LOGIN: req timed out, ext=x%p\n",
  1124. DeviceExtension
  1125. ));
  1126. return STATUS_UNSUCCESSFUL;
  1127. }
  1128. return status;
  1129. break;
  1130. case TRANSACTION_RECONNECT:
  1131. DEBUGPRINT2((
  1132. "Sbp2Port: MgmXact: reconnecting to ext=x%p\n",
  1133. DeviceExtension
  1134. ));
  1135. default:
  1136. status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, NULL);
  1137. if (!NT_SUCCESS(status)) {
  1138. return(status);
  1139. }
  1140. sbpRequest->OrbInfo.QuadPart = 0;
  1141. sbpRequest->OrbInfo.u.HighPart |= (ORB_NOTIFY_BIT_MASK | ORB_MNG_RQ_FMT_VALUE);
  1142. //
  1143. // login ID
  1144. //
  1145. sbpRequest->OrbInfo.u.LowPart = DeviceExtension->LoginResponse->LengthAndLoginId.u.LowPart;
  1146. //
  1147. // Set the type of the management transaction in the ORB
  1148. //
  1149. sbpRequest->OrbInfo.u.HighPart |= 0x00FF & Type;
  1150. //
  1151. // Convert to big endian
  1152. //
  1153. sbpRequest->OrbInfo.QuadPart = bswap (sbpRequest->OrbInfo.QuadPart);
  1154. sbpRequest->StatusBlockAddress.BusAddress = DeviceExtension->ManagementOrbStatusContext.Address.BusAddress;
  1155. octbswap(sbpRequest->StatusBlockAddress);
  1156. if (KeGetCurrentIrql() < DISPATCH_LEVEL) {
  1157. ASSERT(InterlockedIncrement(&DeviceExtension->ulPendingEvents) == 1);
  1158. waitValue.QuadPart = -8 * 1000 * 1000 * 10;
  1159. KeInitializeEvent(DeviceExtension->ManagementOrbContext.Reserved, NotificationEvent, FALSE);
  1160. status = Sbp2AccessRegister(DeviceExtension,&DeviceExtension->ManagementOrbContext.Address,MANAGEMENT_AGENT_REG | REG_WRITE_SYNC);
  1161. if (!NT_SUCCESS(status)) {
  1162. DEBUGPRINT2(("Sbp2Port: MgmtXact: type=%d, can't access mgmt reg, sts=x%x\n",Type,status));
  1163. IoReleaseRemoveLock(&DeviceExtension->RemoveLock, NULL);
  1164. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1165. return status;
  1166. }
  1167. status = KeWaitForSingleObject(DeviceExtension->ManagementOrbContext.Reserved,Executive,KernelMode,FALSE,&waitValue);
  1168. ASSERT(InterlockedDecrement(&DeviceExtension->ulPendingEvents) == 0);
  1169. if (status == STATUS_TIMEOUT) {
  1170. DEBUGPRINT2(("Sbp2Port: MgmtXact: type=%d, ext=x%p, req timeout\n",Type, DeviceExtension));
  1171. IoReleaseRemoveLock(&DeviceExtension->RemoveLock, NULL);
  1172. return STATUS_UNSUCCESSFUL;
  1173. }
  1174. } else {
  1175. status = Sbp2AccessRegister(DeviceExtension,&DeviceExtension->ManagementOrbContext.Address,MANAGEMENT_AGENT_REG | REG_WRITE_ASYNC);
  1176. }
  1177. IoReleaseRemoveLock(&DeviceExtension->RemoveLock, NULL);
  1178. return status;
  1179. break;
  1180. }
  1181. //
  1182. // all MANAGEMENT ORBs except login,query login, are done asynchronously
  1183. //
  1184. if (!NT_SUCCESS(status)) {
  1185. return status;
  1186. }
  1187. return STATUS_PENDING;
  1188. }
  1189. #if PASSWORD_SUPPORT
  1190. NTSTATUS
  1191. Sbp2SetPasswordTransaction(
  1192. IN PDEVICE_EXTENSION DeviceExtension,
  1193. IN ULONG Type
  1194. )
  1195. /*++
  1196. Routine Description:
  1197. This routine creates and sends down set password transaction.
  1198. Arguments:
  1199. deviceExtension - Sbp2 device extension
  1200. Return Value:
  1201. NTSTATUS
  1202. --*/
  1203. {
  1204. PDEVICE_OBJECT deviceObject = DeviceExtension->DeviceObject;
  1205. NTSTATUS status;
  1206. KIRQL cIrql;
  1207. PORB_SET_PASSWORD passwordOrb = DeviceExtension->PasswordOrb;
  1208. LARGE_INTEGER waitValue;
  1209. LONG temp;
  1210. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED)) {
  1211. status = STATUS_DEVICE_DOES_NOT_EXIST;
  1212. goto Exit_Sbp2SetPasswordTransaction;
  1213. }
  1214. RtlZeroMemory(passwordOrb, sizeof(ORB_SET_PASSWORD));
  1215. //
  1216. // Password
  1217. //
  1218. if (Type == SBP2REQ_SET_PASSWORD_EXCLUSIVE) {
  1219. passwordOrb->Password.u.HighQuad.QuadPart =
  1220. DeviceExtension->DeviceInfo->ConfigRom->CR_Node_UniqueID[1];
  1221. passwordOrb->Password.u.LowQuad.QuadPart =
  1222. DeviceExtension->DeviceInfo->ConfigRom->CR_Node_UniqueID[0];
  1223. } else {
  1224. passwordOrb->Password.OctletPart = 0;
  1225. }
  1226. //
  1227. // Reserved
  1228. //
  1229. passwordOrb->Reserved.OctletPart = 0;
  1230. //
  1231. // OrbInfo
  1232. //
  1233. passwordOrb->OrbInfo.QuadPart = 0;
  1234. passwordOrb->OrbInfo.u.HighPart |=
  1235. (ORB_NOTIFY_BIT_MASK | ORB_MNG_RQ_FMT_VALUE);
  1236. passwordOrb->OrbInfo.u.HighPart |=
  1237. 0x00FF & TRANSACTION_SET_PASSWORD;
  1238. passwordOrb->OrbInfo.u.LowPart =
  1239. DeviceExtension->LoginResponse->LengthAndLoginId.u.LowPart;
  1240. //
  1241. // LengthInfo
  1242. //
  1243. passwordOrb->LengthInfo.u.HighPart = 0;
  1244. //
  1245. // StatusBlockAddress
  1246. //
  1247. passwordOrb->StatusBlockAddress.BusAddress =
  1248. DeviceExtension->PasswordOrbStatusContext.Address.BusAddress;
  1249. //
  1250. // Bswap everything...
  1251. //
  1252. octbswap (passwordOrb->Password);
  1253. passwordOrb->OrbInfo.QuadPart = bswap (passwordOrb->OrbInfo.QuadPart);
  1254. passwordOrb->LengthInfo.QuadPart = bswap(passwordOrb->LengthInfo.QuadPart);
  1255. octbswap (passwordOrb->StatusBlockAddress);
  1256. //
  1257. // Write to the Management Agent register, to signal that
  1258. // a management ORB is ready
  1259. //
  1260. waitValue.LowPart = SBP2_SET_PASSWORD_TIMEOUT;
  1261. waitValue.HighPart = -1;
  1262. KeInitializeEvent(
  1263. DeviceExtension->PasswordOrbContext.Reserved,
  1264. NotificationEvent,
  1265. FALSE
  1266. );
  1267. status = Sbp2AccessRegister(
  1268. DeviceExtension,
  1269. &DeviceExtension->PasswordOrbContext.Address,
  1270. MANAGEMENT_AGENT_REG | REG_WRITE_SYNC
  1271. );
  1272. if (!NT_SUCCESS(status)) {
  1273. DEBUGPRINT1((
  1274. "Sbp2Port: SetPasswdXact: can't access mgmt reg, sts=x%x\n",
  1275. status
  1276. ));
  1277. goto Exit_Sbp2SetPasswordTransaction;
  1278. }
  1279. status = KeWaitForSingleObject(
  1280. DeviceExtension->PasswordOrbContext.Reserved,
  1281. Executive,
  1282. KernelMode,
  1283. FALSE,
  1284. &waitValue
  1285. );
  1286. if (status == STATUS_TIMEOUT) {
  1287. DEBUGPRINT1((
  1288. "Sbp2Port: SetPasswdXact: req timed out, ext=x%p\n",
  1289. DeviceExtension
  1290. ));
  1291. status = STATUS_UNSUCCESSFUL;
  1292. goto Exit_Sbp2SetPasswordTransaction;
  1293. }
  1294. status = CheckStatusResponseValue(&DeviceExtension->PasswordOrbStatusBlock);
  1295. Exit_Sbp2SetPasswordTransaction:
  1296. return(status);
  1297. }
  1298. #endif
  1299. ///////////////////////////////////////////////////////////////////////////////
  1300. // Callback routines
  1301. ///////////////////////////////////////////////////////////////////////////////
  1302. RCODE
  1303. Sbp2GlobalStatusCallback(
  1304. IN PNOTIFICATION_INFO NotificationInfo
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. Callback routine for writes to our login Status Block. the 1394 driver will call this routine, after
  1309. the target has updated the status in our memory.
  1310. Arguments:
  1311. (Check 1394Bus.doc) or 1394.h
  1312. Return Value:
  1313. 0
  1314. --*/
  1315. {
  1316. PIRP requestIrp, irp;
  1317. ULONG temp, rcode;
  1318. ULONG currentOrbListDepth, initialOrbListDepth;
  1319. PVOID *tempPointer;
  1320. PUCHAR senseBuffer;
  1321. BOOLEAN cancelledTimer;
  1322. NTSTATUS status;
  1323. PLIST_ENTRY entry;
  1324. PDEVICE_OBJECT deviceObject;
  1325. PDEVICE_EXTENSION deviceExtension;
  1326. PSTATUS_FIFO_BLOCK statusBlock;
  1327. PASYNC_REQUEST_CONTEXT orbContext, nextListItem;
  1328. //
  1329. // NOTE: Uncomment these when enabling ordered execution code below
  1330. //
  1331. // ULONG completedPrecedingOrbs;
  1332. // LIST_ENTRY listHead;
  1333. // PLIST_ENTRY nextEntry;
  1334. //
  1335. if (NotificationInfo->Context != NULL) {
  1336. deviceObject = ((PADDRESS_CONTEXT)NotificationInfo->Context)->DeviceObject;
  1337. deviceExtension = deviceObject->DeviceExtension;
  1338. } else {
  1339. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: NotifyInfo %p Context NULL!!\n", NotificationInfo));
  1340. return RCODE_RESPONSE_COMPLETE;
  1341. }
  1342. statusBlock = MmGetMdlVirtualAddress (NotificationInfo->Fifo->FifoMdl);
  1343. octbswap (statusBlock->AddressAndStatus);
  1344. status = CheckStatusResponseValue (statusBlock);
  1345. //
  1346. // check if we got a remove before the DPC fired.
  1347. // If we did, dont do anything....
  1348. //
  1349. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_REMOVED )) {
  1350. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: dev removed and got status=x%x, State=%x\n",
  1351. statusBlock,deviceExtension->DeviceFlags));
  1352. ExInterlockedPushEntrySList(&deviceExtension->StatusFifoListHead,
  1353. (PSINGLE_LIST_ENTRY) &NotificationInfo->Fifo->FifoList,
  1354. &deviceExtension->StatusFifoLock);
  1355. return RCODE_RESPONSE_COMPLETE;
  1356. }
  1357. if ((statusBlock->AddressAndStatus.BusAddress.Off_Low ==
  1358. deviceExtension->ManagementOrbContext.Address.BusAddress.Off_Low) &&
  1359. (statusBlock->AddressAndStatus.BusAddress.Off_High ==
  1360. deviceExtension->ManagementOrbContext.Address.BusAddress.Off_High)) {
  1361. //
  1362. // Management status callback
  1363. //
  1364. Sbp2LoginCompletion (NotificationInfo, status);
  1365. rcode = RCODE_RESPONSE_COMPLETE;
  1366. goto exitGlobalCallback;
  1367. }
  1368. //
  1369. // Data( Command ORB) status callback
  1370. //
  1371. if (statusBlock->AddressAndStatus.u.HighQuad.u.HighPart &
  1372. STATUS_BLOCK_UNSOLICITED_BIT_MASK) {
  1373. DEBUGPRINT3(("Sbp2Port: GlobalStatusCb: unsolicited recv'd\n"));
  1374. //
  1375. // this is a status unrelated to any pending ORB's, reenable the unsolicited reg
  1376. //
  1377. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,UNSOLICITED_STATUS_REG | REG_WRITE_ASYNC);
  1378. //
  1379. // intepret the unsolicited status and take appropriate action
  1380. //
  1381. Sbp2HandleUnsolicited(deviceExtension,statusBlock);
  1382. rcode= RCODE_RESPONSE_COMPLETE;
  1383. goto exitGlobalCallback;
  1384. }
  1385. if (deviceExtension->OrbPoolContext.Reserved == NULL) {
  1386. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: Stopped or Removed and got status %x, State %x.\n",
  1387. statusBlock, deviceExtension->DeviceFlags));
  1388. ExInterlockedPushEntrySList(&deviceExtension->StatusFifoListHead,
  1389. (PSINGLE_LIST_ENTRY) &NotificationInfo->Fifo->FifoList,
  1390. &deviceExtension->StatusFifoLock);
  1391. return RCODE_RESPONSE_COMPLETE;
  1392. }
  1393. //
  1394. // This GOT to be a NORMAL command ORB
  1395. // calculate base address of the ORB, relative to start address of ORB pool
  1396. //
  1397. temp = statusBlock->AddressAndStatus.BusAddress.Off_Low -
  1398. deviceExtension->OrbPoolContext.Address.BusAddress.Off_Low;
  1399. if (temp > (MAX_ORB_LIST_DEPTH * sizeof (ARCP_ORB))) {
  1400. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: status has invalid addr=x%x\n",temp));
  1401. //ASSERT(temp <= (MAX_ORB_LIST_DEPTH * sizeof (ARCP_ORB)));
  1402. Sbp2CreateRequestErrorLog(deviceExtension->DeviceObject,NULL,STATUS_DEVICE_PROTOCOL_ERROR);
  1403. rcode = RCODE_ADDRESS_ERROR;
  1404. goto exitGlobalCallback;
  1405. }
  1406. //
  1407. // Retrieve the pointer to the context which wraps this ORB.
  1408. // The pointer is stored sizeof(PVOID) bytes behind the ORB's
  1409. // buffer address in host memory.
  1410. //
  1411. tempPointer = (PVOID) (((PUCHAR) deviceExtension->OrbPoolContext.Reserved)
  1412. + temp - FIELD_OFFSET (ARCP_ORB, Orb));
  1413. orbContext = (PASYNC_REQUEST_CONTEXT) *tempPointer;
  1414. if (!orbContext || (orbContext->Tag != SBP2_ASYNC_CONTEXT_TAG)) {
  1415. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: status has invalid addr(2)=x%x\n",temp));
  1416. //ASSERT(orbContext!=NULL);
  1417. Sbp2CreateRequestErrorLog(deviceExtension->DeviceObject,NULL,STATUS_DEVICE_PROTOCOL_ERROR);
  1418. rcode = RCODE_ADDRESS_ERROR;
  1419. goto exitGlobalCallback;
  1420. }
  1421. DEBUGPRINT4(("Sbp2Port: GlobalStatusCb: ctx=x%p compl\n", orbContext));
  1422. KeAcquireSpinLockAtDpcLevel (&deviceExtension->OrbListSpinLock);
  1423. if (TEST_FLAG (orbContext->Flags, ASYNC_CONTEXT_FLAG_COMPLETED)) {
  1424. //
  1425. // request marked completed before we got the chance to do so. means our lists got hosed or the target
  1426. // finised same request twice..
  1427. //
  1428. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1429. DEBUGPRINT1(("Sbp2Port: GlobalStatusCb: req=x%p already marked compl??\n",orbContext));
  1430. ASSERT(orbContext->Srb == NULL);
  1431. rcode= RCODE_RESPONSE_COMPLETE;
  1432. goto exitGlobalCallback;
  1433. }
  1434. SET_FLAG (orbContext->Flags, ASYNC_CONTEXT_FLAG_COMPLETED);
  1435. requestIrp = (PIRP) orbContext->Srb->OriginalRequest;
  1436. #if 1
  1437. //
  1438. // If this is the oldest request in the queue then cancel the timer
  1439. //
  1440. if ((PASYNC_REQUEST_CONTEXT) deviceExtension->PendingOrbList.Flink ==
  1441. orbContext) {
  1442. KeCancelTimer (&orbContext->Timer);
  1443. CLEAR_FLAG (orbContext->Flags,ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1444. cancelledTimer = TRUE;
  1445. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1446. } else {
  1447. //
  1448. // Older request(s) still in progress, no timer associated with
  1449. // this request
  1450. //
  1451. cancelledTimer = FALSE;
  1452. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1453. }
  1454. #else
  1455. //
  1456. // ISSUE: The following is #if'd out for Windows XP because
  1457. // it's possible with MP machines & ordered execution
  1458. // devices for requests to complete in order, yet have
  1459. // completion notifications show up here out of order due
  1460. // to multiple DPCs firing. This can cause problems because
  1461. // by the time we get here on thread #1 thread #2 might
  1462. // have already completed this request (in the ordered exec
  1463. // handler below), and the request context object may have
  1464. // been reallocated for a new request, and it could get
  1465. // erroneously completed here. (There's currently no way
  1466. // to associate a request instance with a completion
  1467. // notification instance.)
  1468. //
  1469. // This means that we might incur some timeouts if some
  1470. // vendor chooses to implement an ordered execution device
  1471. // which will actually complete a request & assume implicit
  1472. // completion of older requests. At this time, Oxford Semi
  1473. // is the only vendor we know of that does ordered execution,
  1474. // and they guarantee one completion per request.
  1475. //
  1476. // NOTE: !! When enabling this code make sure to uncomment other
  1477. // refs (above & below) to the "completedPrecedingOrbs", etc
  1478. // variables.
  1479. //
  1480. // DanKn, 21-July-2001
  1481. //
  1482. //
  1483. // If this is the oldest request in the queue then cancel the timer,
  1484. // else check the ordered execution bit in the LUN (0x14) key to see
  1485. // whether we need to complete preceding requests or not
  1486. //
  1487. completedPrecedingOrbs = 0;
  1488. if ((PASYNC_REQUEST_CONTEXT) deviceExtension->PendingOrbList.Flink ==
  1489. orbContext) {
  1490. KeCancelTimer (&orbContext->Timer);
  1491. CLEAR_FLAG (orbContext->Flags,ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1492. cancelledTimer = TRUE;
  1493. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1494. } else if (!(deviceExtension->DeviceInfo->Lun.QuadPart & 0x00400000)) {
  1495. //
  1496. // Unordered execution device, older request(s) still in progress,
  1497. // no timer associated with this request
  1498. //
  1499. cancelledTimer = FALSE;
  1500. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1501. } else {
  1502. //
  1503. // Ordered execution device. Per section 4.6 of spec :
  1504. // "A consequence of ordering is that completion status for one
  1505. // task implicitly indicates successful completion status for
  1506. // all tasks that preceded it in the ordered list."
  1507. //
  1508. //
  1509. // Cancel the oldest request's timer if necessary
  1510. //
  1511. nextListItem = RETRIEVE_CONTEXT(
  1512. deviceExtension->PendingOrbList.Flink,
  1513. OrbList
  1514. );
  1515. if (nextListItem->Flags & ASYNC_CONTEXT_FLAG_TIMER_STARTED) {
  1516. KeCancelTimer (&nextListItem->Timer);
  1517. CLEAR_FLAG (nextListItem->Flags, ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1518. cancelledTimer = TRUE;
  1519. ASSERT (!(orbContext->Flags & ASYNC_CONTEXT_FLAG_COMPLETED));
  1520. } else {
  1521. cancelledTimer = FALSE;
  1522. }
  1523. //
  1524. // Remove preceding, uncompleted entries from the
  1525. // PendingOrbList and put them in a local list
  1526. //
  1527. InitializeListHead (&listHead);
  1528. for(
  1529. entry = deviceExtension->PendingOrbList.Flink;
  1530. entry != (PLIST_ENTRY) &orbContext->OrbList;
  1531. entry = nextEntry
  1532. )
  1533. {
  1534. nextEntry = entry->Flink;
  1535. nextListItem = RETRIEVE_CONTEXT (entry, OrbList);
  1536. if (!(nextListItem->Flags & ASYNC_CONTEXT_FLAG_COMPLETED)) {
  1537. RemoveEntryList (entry);
  1538. InsertTailList (&listHead, entry);
  1539. }
  1540. }
  1541. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1542. //
  1543. // Now complete the entries in the local list
  1544. //
  1545. while (!IsListEmpty (&listHead)) {
  1546. nextListItem = RETRIEVE_CONTEXT (listHead.Flink, OrbList);
  1547. RemoveEntryList (listHead.Flink);
  1548. nextListItem->Srb->SrbStatus = SRB_STATUS_SUCCESS;
  1549. nextListItem->Srb->ScsiStatus = SCSISTAT_GOOD;
  1550. Sbp2_SCSI_RBC_Conversion (nextListItem); // unwind RBC hacks
  1551. irp = (PIRP) nextListItem->Srb->OriginalRequest;
  1552. DEBUGPRINT2((
  1553. "Sbp2Port: GlobalStatusCb: IMPLICIT COMPL arc=x%p\n",
  1554. nextListItem
  1555. ));
  1556. DEBUGPRINT2((
  1557. "Sbp2Port: GlobalStatusCb: ... irp=x%p, cdb=x%x\n",
  1558. irp,
  1559. nextListItem->Srb->Cdb[0]
  1560. ));
  1561. irp->IoStatus.Information = // ISSUE: only set this !=0 on reads?
  1562. nextListItem->Srb->DataTransferLength;
  1563. nextListItem->Srb = NULL;
  1564. FreeAsyncRequestContext (deviceExtension, nextListItem);
  1565. irp->IoStatus.Status = STATUS_SUCCESS;
  1566. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  1567. IoCompleteRequest (irp, IO_NO_INCREMENT);
  1568. completedPrecedingOrbs++;
  1569. }
  1570. }
  1571. #endif
  1572. //
  1573. // Get sense data if length is larger than 1 (indicates error status).
  1574. //
  1575. // Annex B.2 of SBP2 spec : "When a command completes with GOOD status,
  1576. // only the first two quadlets of the status block shall be stored at
  1577. // the status_FIFO address; the len field shall be 1."
  1578. //
  1579. if (((statusBlock->AddressAndStatus.u.HighQuad.u.HighPart >> 8) & 0x07) > 1) {
  1580. orbContext->Srb->SrbStatus = SRB_STATUS_ERROR;
  1581. orbContext->Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  1582. orbContext->Srb->SrbStatus &= ~SRB_STATUS_AUTOSENSE_VALID;
  1583. if (orbContext->Srb->SenseInfoBuffer && !TEST_FLAG(orbContext->Srb->SrbFlags, SRB_FLAGS_DISABLE_AUTOSENSE)) {
  1584. if (TEST_FLAG(deviceExtension->DeviceFlags, DEVICE_FLAG_SPC_CMD_SET)) {
  1585. if (ConvertSbp2SenseDataToScsi(statusBlock,
  1586. orbContext->Srb->SenseInfoBuffer,
  1587. orbContext->Srb->SenseInfoBufferLength) ){
  1588. orbContext->Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
  1589. }
  1590. senseBuffer = (PUCHAR) orbContext->Srb->SenseInfoBuffer;
  1591. if ((orbContext->Srb->Cdb[0] != SCSIOP_TEST_UNIT_READY) ||
  1592. (senseBuffer[2] != SCSI_SENSE_NOT_READY) ||
  1593. (senseBuffer[12] != SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)) {
  1594. DEBUGPRINT2((
  1595. "Sbp2Port: GlobalStatusCb: ERROR, ext=x%p, cdb=x%x s/a/q=x%x/%x/%x\n",
  1596. deviceExtension,
  1597. orbContext->Srb->Cdb[0],
  1598. senseBuffer[2],
  1599. senseBuffer[12],
  1600. senseBuffer[13]
  1601. ));
  1602. }
  1603. } else {
  1604. DEBUGPRINT2((
  1605. "Sbp2Port: GlobalStatusCb: ERROR, ext=x%p, cdb=x%x, cmd set NOT SCSI\n",\
  1606. deviceExtension,
  1607. orbContext->Srb->Cdb[0]
  1608. ));
  1609. if (orbContext->Srb->SenseInfoBuffer) {
  1610. RtlCopyMemory(orbContext->Srb->SenseInfoBuffer,statusBlock,min(sizeof(STATUS_FIFO_BLOCK),orbContext->Srb->SenseInfoBufferLength));
  1611. }
  1612. }
  1613. } else {
  1614. DEBUGPRINT2(("Sbp2Port: GlobalStatusCb: ext=x%p, cdb=x%x, ERROR no sense buf\n",
  1615. deviceExtension,
  1616. orbContext->Srb->Cdb[0]));
  1617. }
  1618. } else if (((statusBlock->AddressAndStatus.u.HighQuad.u.HighPart & 0x3000) == 0x1000) ||
  1619. ((statusBlock->AddressAndStatus.u.HighQuad.u.HighPart & 0x3000) == 0x2000)) {
  1620. //
  1621. // Per section 5.3 of SBP2 spec, values of 1 or 2 in the resp
  1622. // field indicate TRANSPORT FAILURE and ILLEGAL REQUEST,
  1623. // respectively.
  1624. //
  1625. // For now we'll continue to consider a resp value of 3
  1626. // (VENDOR DEPENDENT) a success, like we did in Win2k & WinMe.
  1627. //
  1628. DEBUGPRINT2((
  1629. "Sbp2Port: GlobalStatusCb: ERROR, ext=x%p, cdb=x%x, sts=x%x\n",\
  1630. deviceExtension,
  1631. orbContext->Srb->Cdb[0],
  1632. statusBlock->AddressAndStatus.u.HighQuad.u.HighPart
  1633. ));
  1634. orbContext->Srb->SrbStatus = SRB_STATUS_ERROR;
  1635. orbContext->Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
  1636. orbContext->Srb->SrbStatus &= ~SRB_STATUS_AUTOSENSE_VALID;
  1637. } else {
  1638. orbContext->Srb->SrbStatus = SRB_STATUS_SUCCESS;
  1639. orbContext->Srb->ScsiStatus = SCSISTAT_GOOD;
  1640. }
  1641. Sbp2_SCSI_RBC_Conversion (orbContext); // unwind RBC hacks
  1642. requestIrp->IoStatus.Information = // ISSUE: only set this !=0 on read ok?
  1643. (orbContext->Srb->SrbStatus == SRB_STATUS_SUCCESS ?
  1644. orbContext->Srb->DataTransferLength : 0);
  1645. Free1394DataMapping (deviceExtension, orbContext);
  1646. //
  1647. // Pull the request out of the list & see if we need to set a timer
  1648. //
  1649. KeAcquireSpinLockAtDpcLevel (&deviceExtension->OrbListSpinLock);
  1650. RemoveEntryList (&orbContext->OrbList);
  1651. if (cancelledTimer) {
  1652. //
  1653. // Make the oldest, non-completed request track the timeout
  1654. // (iff one exists)
  1655. //
  1656. for(
  1657. entry = deviceExtension->PendingOrbList.Flink;
  1658. entry != &deviceExtension->PendingOrbList;
  1659. entry = entry->Flink
  1660. )
  1661. {
  1662. nextListItem = RETRIEVE_CONTEXT (entry, OrbList);
  1663. if (!(nextListItem->Flags & ASYNC_CONTEXT_FLAG_COMPLETED)) {
  1664. deviceExtension->DueTime.QuadPart = ((LONGLONG) orbContext->Srb->TimeOutValue) * (-10*1000*1000);
  1665. SET_FLAG(nextListItem->Flags, ASYNC_CONTEXT_FLAG_TIMER_STARTED);
  1666. KeSetTimer(&nextListItem->Timer, deviceExtension->DueTime, &nextListItem->TimerDpc);
  1667. break;
  1668. }
  1669. }
  1670. }
  1671. orbContext->Srb = NULL;
  1672. //
  1673. // Check if the target transitioned to the dead state because of a failed command
  1674. // If it did, do a reset...
  1675. //
  1676. #if 1
  1677. initialOrbListDepth = deviceExtension->OrbListDepth;
  1678. #else
  1679. // NOTE: use this path when enabling ordered execution code above
  1680. initialOrbListDepth = deviceExtension->OrbListDepth +
  1681. completedPrecedingOrbs;
  1682. #endif
  1683. if (statusBlock->AddressAndStatus.u.HighQuad.u.HighPart & STATUS_BLOCK_DEAD_BIT_MASK) {
  1684. //
  1685. // reset the target fetch agent .
  1686. //
  1687. Sbp2AccessRegister (deviceExtension, &deviceExtension->Reserved, AGENT_RESET_REG | REG_WRITE_ASYNC);
  1688. //
  1689. // in order to wake up the agent we now need to write to ORB_POINTER with the head of lined list
  1690. // of un-processed ORBS.
  1691. //
  1692. FreeAsyncRequestContext (deviceExtension, orbContext);
  1693. if (deviceExtension->NextContextToFree) {
  1694. FreeAsyncRequestContext(
  1695. deviceExtension,
  1696. deviceExtension->NextContextToFree
  1697. );
  1698. deviceExtension->NextContextToFree = NULL;
  1699. }
  1700. if (!IsListEmpty (&deviceExtension->PendingOrbList)) {
  1701. //
  1702. // signal target to restart processing at the head of the list
  1703. //
  1704. orbContext = RETRIEVE_CONTEXT(
  1705. deviceExtension->PendingOrbList.Flink,
  1706. OrbList
  1707. );
  1708. Sbp2AccessRegister(
  1709. deviceExtension,
  1710. &orbContext->CmdOrbAddress,
  1711. ORB_POINTER_REG | REG_WRITE_ASYNC
  1712. );
  1713. }
  1714. } else {
  1715. if (statusBlock->AddressAndStatus.u.HighQuad.u.HighPart & STATUS_BLOCK_ENDOFLIST_BIT_MASK) {
  1716. //
  1717. // At the time this ORB was most recently fetched by the
  1718. // target the next_ORB field was "null",
  1719. //
  1720. // so we can't free this context yet since the next ORB we
  1721. // submit may have to "piggyback" on it (but we can free the
  1722. // previous request, if any, that was in the same situation)
  1723. //
  1724. if (deviceExtension->NextContextToFree) {
  1725. FreeAsyncRequestContext(
  1726. deviceExtension,
  1727. deviceExtension->NextContextToFree
  1728. );
  1729. }
  1730. deviceExtension->NextContextToFree = orbContext;
  1731. //
  1732. // This was the end of list at the time the device completed
  1733. // it, but it may not be end of list now (in which case we
  1734. // don't want to append to it again). Check to see if
  1735. // the NextOrbAddress is "null" or not.
  1736. //
  1737. if (orbContext->CmdOrb->NextOrbAddress.OctletPart ==
  1738. 0xFFFFFFFFFFFFFFFF) {
  1739. deviceExtension->AppendToNextContextToFree = TRUE;
  1740. } else {
  1741. deviceExtension->AppendToNextContextToFree = FALSE;
  1742. }
  1743. } else {
  1744. //
  1745. // At the time this ORB was most recently fetched by the
  1746. // target the next_ORB field was not "null",
  1747. //
  1748. // so we can safely free this context since target already
  1749. // knows about the next ORB in the list
  1750. //
  1751. FreeAsyncRequestContext (deviceExtension, orbContext);
  1752. }
  1753. }
  1754. currentOrbListDepth = deviceExtension->OrbListDepth;
  1755. KeReleaseSpinLockFromDpcLevel (&deviceExtension->OrbListSpinLock);
  1756. requestIrp->IoStatus.Status = status;
  1757. IoReleaseRemoveLock (&deviceExtension->RemoveLock, NULL);
  1758. IoCompleteRequest (requestIrp, IO_NO_INCREMENT);
  1759. //
  1760. // Only start another packet if the Ext.OrbListDepth was initially
  1761. // maxed and we then freed at least one request context above.
  1762. // In this case the last orb that was placed on the list was
  1763. // not followed (in Sbp2InsertTailList) by a call to StartNextPacket,
  1764. // so we have to do that here to restart the queue.
  1765. //
  1766. if ((initialOrbListDepth == deviceExtension->MaxOrbListDepth) &&
  1767. (initialOrbListDepth > currentOrbListDepth)) {
  1768. Sbp2StartNextPacketByKey(
  1769. deviceObject,
  1770. deviceExtension->CurrentKey
  1771. );
  1772. }
  1773. DEBUGPRINT3(("Sbp2Port: GlobalStatusCb: leaving callback, depth=%d\n",deviceExtension->OrbListDepth));
  1774. rcode = RCODE_RESPONSE_COMPLETE;
  1775. exitGlobalCallback:
  1776. //
  1777. // return the status fifo back to the list
  1778. //
  1779. ExInterlockedPushEntrySList(&deviceExtension->StatusFifoListHead,
  1780. &NotificationInfo->Fifo->FifoList,
  1781. &deviceExtension->StatusFifoLock);
  1782. return (ULONG) rcode;
  1783. }
  1784. RCODE
  1785. Sbp2ManagementOrbStatusCallback(
  1786. IN PNOTIFICATION_INFO NotificationInfo
  1787. )
  1788. /*++
  1789. Routine Description:
  1790. Callback routine for writes to our Task Status Block. the 1394 driver will call this routine, after
  1791. the target has updated the status in our memory. A Task function is usually a recovery attempt.
  1792. Arguments:
  1793. (Check 1394Bus.doc)
  1794. Return Value:
  1795. 0
  1796. --*/
  1797. {
  1798. PDEVICE_OBJECT deviceObject;
  1799. PDEVICE_EXTENSION deviceExtension;
  1800. PADDRESS_CONTEXT context = (PADDRESS_CONTEXT) NotificationInfo->Context;
  1801. NTSTATUS status;
  1802. if (NotificationInfo->Context != NULL ) {
  1803. deviceObject = ((PADDRESS_CONTEXT)NotificationInfo->Context)->DeviceObject;
  1804. deviceExtension = deviceObject->DeviceExtension;
  1805. } else {
  1806. return RCODE_RESPONSE_COMPLETE;
  1807. }
  1808. if (TEST_FLAG(NotificationInfo->fulNotificationOptions, NOTIFY_FLAGS_AFTER_READ)){
  1809. //
  1810. // This shouldn't happen since we set our flags to NOTIFY_AFTER_WRITE
  1811. //
  1812. return RCODE_TYPE_ERROR;
  1813. }
  1814. octbswap(deviceExtension->ManagementOrbStatusBlock.AddressAndStatus);
  1815. deviceExtension->ManagementOrb->OrbInfo.QuadPart =
  1816. bswap(deviceExtension->ManagementOrb->OrbInfo.QuadPart);
  1817. status = CheckStatusResponseValue(&deviceExtension->ManagementOrbStatusBlock);
  1818. switch (deviceExtension->ManagementOrb->OrbInfo.u.HighPart & 0x00FF) {
  1819. case TRANSACTION_RECONNECT:
  1820. //
  1821. // If there was a pending reset, cancel it
  1822. //
  1823. KeAcquireSpinLockAtDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  1824. if (TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_RECONNECT)) {
  1825. DEBUGPRINT1((
  1826. "Sbp2Port: MgmtOrbStatusCb: RECONNECT, sts=x%x, ext=x%p, fl=x%x\n",
  1827. status,
  1828. deviceExtension,
  1829. deviceExtension->DeviceFlags
  1830. ));
  1831. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  1832. if (NT_SUCCESS(status)) {
  1833. CLEAR_FLAG(deviceExtension->DeviceFlags,(DEVICE_FLAG_RESET_IN_PROGRESS | DEVICE_FLAG_DEVICE_FAILED | DEVICE_FLAG_RECONNECT | DEVICE_FLAG_STOPPED));
  1834. KeReleaseSpinLockFromDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  1835. KeAcquireSpinLockAtDpcLevel(&deviceExtension->OrbListSpinLock);
  1836. if (TEST_FLAG(
  1837. deviceExtension->DeviceFlags,
  1838. DEVICE_FLAG_QUEUE_LOCKED
  1839. ) &&
  1840. (deviceExtension->DeferredPowerRequest != NULL)
  1841. ) {
  1842. //
  1843. // A START_STOP_UNIT was caught in the middle of a bus
  1844. // reset and was deferred until after we reconnected.
  1845. // Complete here so the class driver never knew anything
  1846. // happened..
  1847. //
  1848. PIRP pIrp = deviceExtension->DeferredPowerRequest;
  1849. deviceExtension->DeferredPowerRequest = NULL;
  1850. KeReleaseSpinLockFromDpcLevel(
  1851. &deviceExtension->OrbListSpinLock
  1852. );
  1853. Sbp2StartIo (deviceObject, pIrp);
  1854. } else {
  1855. KeReleaseSpinLockFromDpcLevel(
  1856. &deviceExtension->OrbListSpinLock
  1857. );
  1858. Sbp2StartNextPacketByKey(
  1859. deviceExtension->DeviceObject,
  1860. deviceExtension->CurrentKey
  1861. );
  1862. }
  1863. KeSetEvent(deviceExtension->ManagementOrbContext.Reserved,IO_NO_INCREMENT,FALSE);
  1864. } else {
  1865. //
  1866. // probably too late, we need to a re-login
  1867. //
  1868. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_RECONNECT);
  1869. SET_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_LOGIN_IN_PROGRESS);
  1870. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  1871. KeReleaseSpinLockFromDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  1872. Sbp2UpdateNodeInformation(deviceExtension);
  1873. //
  1874. // see if can access the device
  1875. //
  1876. DEBUGPRINT1((
  1877. "Sbp2Port: MgmtOrbStatusCb: ...(RECONNECT err) " \
  1878. "trying re-login\n"
  1879. ));
  1880. Sbp2ManagementTransaction(deviceExtension, TRANSACTION_LOGIN);
  1881. }
  1882. } else {
  1883. KeReleaseSpinLockFromDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  1884. }
  1885. break;
  1886. case TRANSACTION_QUERY_LOGINS:
  1887. //
  1888. // set the management event, indicating that the request was processed
  1889. //
  1890. DEBUGPRINT1((
  1891. "Sbp2Port: MgmtOrbStatusCb: QUERY_LOGIN, sts=x%x, ext=x%p, fl=x%x\n",
  1892. status,
  1893. deviceExtension,
  1894. deviceExtension->DeviceFlags
  1895. ));
  1896. if (NT_SUCCESS(status)) {
  1897. //
  1898. // check if there somebody logged in..
  1899. //
  1900. deviceExtension->QueryLoginResponse->LengthAndNumLogins.QuadPart =
  1901. bswap(deviceExtension->QueryLoginResponse->LengthAndNumLogins.QuadPart);
  1902. if ((deviceExtension->QueryLoginResponse->LengthAndNumLogins.u.LowPart == 1) &&
  1903. (deviceExtension->QueryLoginResponse->LengthAndNumLogins.u.HighPart > 4)){
  1904. //
  1905. // exclusive login so we have to worry about it...
  1906. //
  1907. deviceExtension->QueryLoginResponse->Elements[0].NodeAndLoginId.QuadPart =
  1908. bswap(deviceExtension->QueryLoginResponse->Elements[0].NodeAndLoginId.QuadPart);
  1909. //
  1910. // Assume the only initiator logged in is the bios...
  1911. // Log out the bios using it login ID...
  1912. //
  1913. deviceExtension->LoginResponse->LengthAndLoginId.u.LowPart =
  1914. deviceExtension->QueryLoginResponse->Elements[0].NodeAndLoginId.u.LowPart;
  1915. //
  1916. // Dont set the vent, so we stall and the BIOS is implicitly logged out
  1917. // since it cant reconnect..
  1918. //
  1919. DEBUGPRINT1(("\nSbp2Port: MgmtOrbStatusCb: somebody else logged in, stalling so it gets logged out\n"));
  1920. }
  1921. } else {
  1922. KeSetEvent(deviceExtension->ManagementOrbContext.Reserved,IO_NO_INCREMENT,FALSE);
  1923. }
  1924. break;
  1925. case TRANSACTION_LOGIN:
  1926. //
  1927. // Per the Sbp2 spec we'd normally expect all login notifications
  1928. // to show up at Sbp2GlobalStatusCallback. In practice, however,
  1929. // we see completion notifications showing up here when an
  1930. // async login is submitted after a failed reconnect.
  1931. //
  1932. Sbp2LoginCompletion (NotificationInfo, status);
  1933. DEBUGPRINT1((
  1934. "Sbp2Port: MgmtOrbStatusCb: ...wrong place for login completions!\n"
  1935. ));
  1936. break;
  1937. default:
  1938. DEBUGPRINT1((
  1939. "Sbp2Port: MgmtOrbStatusCb: type=%d, sts=x%x, ext=x%p, fl=x%x\n",
  1940. deviceExtension->ManagementOrb->OrbInfo.u.HighPart & 0x00FF,
  1941. status,
  1942. deviceExtension,
  1943. deviceExtension->DeviceFlags
  1944. ));
  1945. KeSetEvent(deviceExtension->ManagementOrbContext.Reserved,IO_NO_INCREMENT,FALSE);
  1946. break;
  1947. }
  1948. return RCODE_RESPONSE_COMPLETE;
  1949. }
  1950. #if PASSWORD_SUPPORT
  1951. RCODE
  1952. Sbp2SetPasswordOrbStatusCallback(
  1953. IN PNOTIFICATION_INFO NotificationInfo
  1954. )
  1955. {
  1956. RCODE returnCode = RCODE_RESPONSE_COMPLETE;
  1957. PDEVICE_OBJECT deviceObject;
  1958. PDEVICE_EXTENSION deviceExtension;
  1959. PADDRESS_CONTEXT context = (PADDRESS_CONTEXT) NotificationInfo->Context;
  1960. NTSTATUS status;
  1961. if (NotificationInfo->Context != NULL ) {
  1962. deviceObject = ((PADDRESS_CONTEXT)NotificationInfo->Context)->
  1963. DeviceObject;
  1964. deviceExtension = deviceObject->DeviceExtension;
  1965. } else {
  1966. return RCODE_RESPONSE_COMPLETE;
  1967. }
  1968. if (TEST_FLAG(
  1969. NotificationInfo->fulNotificationOptions,
  1970. NOTIFY_FLAGS_AFTER_READ
  1971. )){
  1972. //
  1973. // This shouldn't happen since we set our flags to NOTIFY_AFTER_WRITE
  1974. //
  1975. returnCode = RCODE_TYPE_ERROR;
  1976. goto Exit_Sbp2SetPasswordOrbStatusCallback;
  1977. }
  1978. octbswap(deviceExtension->PasswordOrbStatusBlock.AddressAndStatus);
  1979. deviceExtension->PasswordOrb->OrbInfo.QuadPart =
  1980. bswap(deviceExtension->PasswordOrb->OrbInfo.QuadPart);
  1981. status = CheckStatusResponseValue(
  1982. &deviceExtension->PasswordOrbStatusBlock
  1983. );
  1984. if ((deviceExtension->PasswordOrb->OrbInfo.u.HighPart & 0x00FF) ==
  1985. TRANSACTION_SET_PASSWORD) {
  1986. DEBUGPRINT1(("Sbp2Port: TRANSACTION_SET_PASSWORD Callback\n"));
  1987. DEBUGPRINT1((
  1988. "Sbp2Port: PasswdOrbStatusCb: type=%d, sts=x%x, ext=x%p, fl=x%x\n",
  1989. deviceExtension->PasswordOrb->OrbInfo.u.HighPart & 0x00FF,
  1990. status,
  1991. deviceExtension,
  1992. deviceExtension->DeviceFlags
  1993. ));
  1994. }
  1995. else {
  1996. DEBUGPRINT1(("Sbp2Port: PasswdOrbStatusCb: Wrong xact type=x%x\n",
  1997. (deviceExtension->PasswordOrb->OrbInfo.u.HighPart & 0x00FF)));
  1998. }
  1999. Exit_Sbp2SetPasswordOrbStatusCallback:
  2000. KeSetEvent(
  2001. deviceExtension->PasswordOrbContext.Reserved,
  2002. IO_NO_INCREMENT,
  2003. FALSE
  2004. );
  2005. return returnCode;
  2006. }
  2007. #endif
  2008. VOID
  2009. Sbp2LoginCompletion(
  2010. PNOTIFICATION_INFO NotificationInfo,
  2011. NTSTATUS Status
  2012. )
  2013. {
  2014. PDEVICE_OBJECT deviceObject;
  2015. PDEVICE_EXTENSION deviceExtension;
  2016. if (NotificationInfo->Context != NULL ) {
  2017. deviceObject = ((PADDRESS_CONTEXT) NotificationInfo->Context)->
  2018. DeviceObject;
  2019. deviceExtension = deviceObject->DeviceExtension;
  2020. } else {
  2021. return;
  2022. }
  2023. KeCancelTimer (&deviceExtension->DeviceManagementTimer);
  2024. KeAcquireSpinLockAtDpcLevel (&deviceExtension->ExtensionDataSpinLock);
  2025. if (TEST_FLAG (deviceExtension->DeviceFlags, DEVICE_FLAG_LOGIN_IN_PROGRESS)){
  2026. if (Status != STATUS_SUCCESS) {
  2027. //
  2028. // Login failed... We can't to much else.
  2029. //
  2030. CLEAR_FLAG(
  2031. deviceExtension->DeviceFlags,
  2032. (DEVICE_FLAG_RECONNECT | DEVICE_FLAG_LOGIN_IN_PROGRESS)
  2033. );
  2034. SET_FLAG(
  2035. deviceExtension->DeviceFlags,
  2036. (DEVICE_FLAG_STOPPED | DEVICE_FLAG_DEVICE_FAILED)
  2037. );
  2038. deviceExtension->LastTransactionStatus = Status;
  2039. KeReleaseSpinLockFromDpcLevel(
  2040. &deviceExtension->ExtensionDataSpinLock
  2041. );
  2042. DEBUGPRINT1((
  2043. "Sbp2Port: LoginCompl: sts=x%x, ext=x%p, fl=x%x\n",
  2044. Status,
  2045. deviceExtension,
  2046. deviceExtension->DeviceFlags
  2047. ));
  2048. deviceExtension->LoginResponse->Csr_Off_Low.QuadPart = 0;
  2049. if (!TEST_FLAG(
  2050. deviceExtension->DeviceFlags,
  2051. DEVICE_FLAG_RESET_IN_PROGRESS
  2052. )) {
  2053. KeSetEvent(
  2054. deviceExtension->ManagementOrbContext.Reserved,
  2055. IO_NO_INCREMENT,
  2056. FALSE
  2057. );
  2058. } else {
  2059. if (deviceExtension->DeferredPowerRequest) {
  2060. PIRP irp = deviceExtension->DeferredPowerRequest;
  2061. deviceExtension->DeferredPowerRequest = NULL;
  2062. Sbp2StartIo (deviceObject, irp);
  2063. } else {
  2064. Sbp2StartNextPacketByKey(
  2065. deviceObject,
  2066. deviceExtension->CurrentKey
  2067. );
  2068. }
  2069. IoInvalidateDeviceState (deviceObject);
  2070. }
  2071. return;
  2072. }
  2073. //
  2074. // Succesful login, read the response buffer (it has our login ID)
  2075. //
  2076. DEBUGPRINT2((
  2077. "Sbp2Port: LoginCompl: success, ext=x%p, fl=x%x\n",
  2078. deviceExtension,
  2079. deviceExtension->DeviceFlags
  2080. ));
  2081. deviceExtension->LastTransactionStatus = Status;
  2082. deviceExtension->LoginResponse->LengthAndLoginId.QuadPart =
  2083. bswap(deviceExtension->LoginResponse->LengthAndLoginId.QuadPart);
  2084. deviceExtension->LoginResponse->Csr_Off_High.QuadPart =
  2085. bswap(deviceExtension->LoginResponse->Csr_Off_High.QuadPart);
  2086. deviceExtension->LoginResponse->Csr_Off_Low.QuadPart =
  2087. bswap(deviceExtension->LoginResponse->Csr_Off_Low.QuadPart);
  2088. //
  2089. // Store the register base for target fetch agents
  2090. //
  2091. deviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_High =
  2092. deviceExtension->LoginResponse->Csr_Off_High.u.LowPart;
  2093. deviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low =
  2094. deviceExtension->LoginResponse->Csr_Off_Low.QuadPart;
  2095. //
  2096. // this callback fired becuase the asynchronous login succeeded
  2097. // clear our device flags to indicate the device is operating fine
  2098. //
  2099. CLEAR_FLAG(
  2100. deviceExtension->DeviceFlags,
  2101. (DEVICE_FLAG_LOGIN_IN_PROGRESS | DEVICE_FLAG_STOPPED |
  2102. DEVICE_FLAG_REMOVED | DEVICE_FLAG_DEVICE_FAILED)
  2103. );
  2104. if (!TEST_FLAG(
  2105. deviceExtension->DeviceFlags,
  2106. DEVICE_FLAG_RESET_IN_PROGRESS
  2107. )) {
  2108. KeReleaseSpinLockFromDpcLevel(
  2109. &deviceExtension->ExtensionDataSpinLock
  2110. );
  2111. KeSetEvent(
  2112. deviceExtension->ManagementOrbContext.Reserved,
  2113. IO_NO_INCREMENT,
  2114. FALSE
  2115. );
  2116. } else {
  2117. CLEAR_FLAG(
  2118. deviceExtension->DeviceFlags,
  2119. DEVICE_FLAG_RESET_IN_PROGRESS
  2120. );
  2121. KeReleaseSpinLockFromDpcLevel(
  2122. &deviceExtension->ExtensionDataSpinLock
  2123. );
  2124. if (TEST_FLAG(
  2125. deviceExtension->DeviceFlags,
  2126. DEVICE_FLAG_QUEUE_LOCKED
  2127. )) {
  2128. KeAcquireSpinLockAtDpcLevel(&deviceExtension->OrbListSpinLock);
  2129. if (deviceExtension->DeferredPowerRequest) {
  2130. //
  2131. // A request was caught in the middle of a bus reset
  2132. // and was deferred until after we reconnected.
  2133. // Complete here so the class driver never knew anything
  2134. // happened.
  2135. //
  2136. PIRP pIrp = deviceExtension->DeferredPowerRequest;
  2137. deviceExtension->DeferredPowerRequest = NULL;
  2138. KeReleaseSpinLockFromDpcLevel(
  2139. &deviceExtension->OrbListSpinLock
  2140. );
  2141. Sbp2StartIo (deviceObject, pIrp);
  2142. } else {
  2143. KeReleaseSpinLockFromDpcLevel(
  2144. &deviceExtension->OrbListSpinLock
  2145. );
  2146. Sbp2StartNextPacketByKey(
  2147. deviceObject,
  2148. deviceExtension->CurrentKey
  2149. );
  2150. }
  2151. } else {
  2152. Sbp2StartNextPacketByKey(
  2153. deviceObject,
  2154. deviceExtension->CurrentKey
  2155. );
  2156. }
  2157. }
  2158. //
  2159. // make retry limit high for busy transactions
  2160. //
  2161. deviceExtension->Reserved = BUSY_TIMEOUT_SETTING;
  2162. Sbp2AccessRegister(
  2163. deviceExtension,
  2164. &deviceExtension->Reserved,
  2165. CORE_BUSY_TIMEOUT_REG | REG_WRITE_ASYNC
  2166. );
  2167. } else {
  2168. KeReleaseSpinLockFromDpcLevel(
  2169. &deviceExtension->ExtensionDataSpinLock
  2170. );
  2171. }
  2172. }
  2173. RCODE
  2174. Sbp2TaskOrbStatusCallback(
  2175. IN PNOTIFICATION_INFO NotificationInfo
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. Callback routine for writes to our Task Status Block. the 1394 driver will call this routine, after
  2180. the target has updated the status in our memory. A Task function is an ABORT_TASK_SET or TARGET_RESET,
  2181. for this implementation
  2182. Arguments:
  2183. NotificationInfo - bus supplied context for this notification
  2184. Return Value:
  2185. 0
  2186. --*/
  2187. {
  2188. PDEVICE_OBJECT deviceObject;
  2189. PDEVICE_EXTENSION deviceExtension;
  2190. PADDRESS_CONTEXT context = (PADDRESS_CONTEXT) NotificationInfo->Context;
  2191. NTSTATUS status;
  2192. if (NotificationInfo->Context != NULL ) {
  2193. deviceObject = ((PADDRESS_CONTEXT)NotificationInfo->Context)->DeviceObject;
  2194. deviceExtension = deviceObject->DeviceExtension;
  2195. } else {
  2196. return RCODE_RESPONSE_COMPLETE;
  2197. }
  2198. if (TEST_FLAG(NotificationInfo->fulNotificationOptions, NOTIFY_FLAGS_AFTER_READ)){
  2199. //
  2200. // This shouldn't happen since we set our flags to NOTIFY_AFTER_WRITE
  2201. //
  2202. return RCODE_TYPE_ERROR;
  2203. } else if (NotificationInfo->fulNotificationOptions & NOTIFY_FLAGS_AFTER_WRITE){
  2204. //
  2205. // now cleanup our lists, if the abort task set completed succesfully ( if not rejected)
  2206. //
  2207. if (!TEST_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_RESET_IN_PROGRESS)) {
  2208. DEBUGPRINT1(("Sbp2Port: TaskOrbStatusCb: bogus call, rejected\n"));
  2209. return (ULONG)RCODE_RESPONSE_COMPLETE;
  2210. }
  2211. KeCancelTimer(&deviceExtension->DeviceManagementTimer);
  2212. octbswap(deviceExtension->TaskOrbStatusBlock.AddressAndStatus);
  2213. status = CheckStatusResponseValue(&deviceExtension->TaskOrbStatusBlock);
  2214. if (status!=STATUS_SUCCESS) {
  2215. if (deviceExtension->TaskOrbContext.TransactionType != TRANSACTION_TARGET_RESET) {
  2216. DEBUGPRINT1(("Sbp2Port: TaskOrbStatusCb: ABORT TASK SET func err\n"));
  2217. } else {
  2218. //
  2219. // a target reset didn't complete succesfully. Fatal error...
  2220. //
  2221. DEBUGPRINT1(("Sbp2Port: TaskOrbStatusCb: Target RESET err, try CMD_RESET & relogin\n"));
  2222. Sbp2CreateRequestErrorLog(deviceExtension->DeviceObject,NULL,STATUS_DEVICE_OFF_LINE);
  2223. deviceExtension->Reserved = 0;
  2224. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,CORE_RESET_REG | REG_WRITE_ASYNC);
  2225. KeAcquireSpinLockAtDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  2226. SET_FLAG(deviceExtension->DeviceFlags,(DEVICE_FLAG_RECONNECT | DEVICE_FLAG_STOPPED));
  2227. KeReleaseSpinLockFromDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  2228. deviceExtension->DueTime.HighPart = -1;
  2229. deviceExtension->DueTime.LowPart = SBP2_RELOGIN_DELAY;
  2230. KeSetTimer(&deviceExtension->DeviceManagementTimer,deviceExtension->DueTime, &deviceExtension->DeviceManagementTimeoutDpc);
  2231. return (ULONG) RCODE_RESPONSE_COMPLETE;
  2232. }
  2233. }
  2234. deviceExtension->Reserved = BUSY_TIMEOUT_SETTING;
  2235. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,CORE_BUSY_TIMEOUT_REG | REG_WRITE_ASYNC);
  2236. //
  2237. // reset the fetch agent
  2238. //
  2239. Sbp2AccessRegister(deviceExtension,&deviceExtension->Reserved,AGENT_RESET_REG | REG_WRITE_ASYNC);
  2240. DEBUGPRINT2(("Sbp2Port: TaskOrbStatusCb: TASK func succes\n"));
  2241. KeAcquireSpinLockAtDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  2242. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_RESET_IN_PROGRESS);
  2243. if (deviceExtension->TaskOrbContext.TransactionType == TRANSACTION_TARGET_RESET) {
  2244. CLEAR_FLAG(deviceExtension->DeviceFlags,DEVICE_FLAG_STOPPED);
  2245. }
  2246. //
  2247. // decrease number of possible outstanding requests.
  2248. //
  2249. deviceExtension->MaxOrbListDepth = max(MIN_ORB_LIST_DEPTH,deviceExtension->MaxOrbListDepth/2);
  2250. KeReleaseSpinLockFromDpcLevel(&deviceExtension->ExtensionDataSpinLock);
  2251. CleanupOrbList(deviceExtension,STATUS_REQUEST_ABORTED);
  2252. Sbp2StartNextPacketByKey (deviceExtension->DeviceObject, 0);
  2253. }
  2254. return (ULONG) RCODE_RESPONSE_COMPLETE;
  2255. }
  2256. VOID
  2257. Sbp2HandleUnsolicited(
  2258. IN PDEVICE_EXTENSION DeviceExtension,
  2259. IN PSTATUS_FIFO_BLOCK StatusFifo
  2260. )
  2261. /*++
  2262. Routine Description:
  2263. Inteprets the unsolicited status recieved and takes action if necessery
  2264. If the unsolicted requets called for power transition, request a power irp
  2265. ..
  2266. Arguments:
  2267. DeviceExtension - Pointer to device extension.
  2268. StatusFifo - fifo send by the device
  2269. Return Value:
  2270. --*/
  2271. {
  2272. UCHAR senseBuffer[SENSE_BUFFER_SIZE];
  2273. POWER_STATE state;
  2274. NTSTATUS status;
  2275. if (TEST_FLAG(DeviceExtension->DeviceFlags,DEVICE_FLAG_SPC_CMD_SET)) {
  2276. switch (DeviceExtension->DeviceInfo->Lun.u.HighPart & 0x001F) {
  2277. case RBC_DEVICE:
  2278. //
  2279. // use RBC spec for intepreting status contents
  2280. // the sense keys tells us what type of status this was
  2281. //
  2282. if (ConvertSbp2SenseDataToScsi(StatusFifo, senseBuffer,sizeof(senseBuffer))) {
  2283. if ((senseBuffer[2] == 0x06) && (senseBuffer[12] == 0x7F)) {
  2284. switch (senseBuffer[13]) {
  2285. case RBC_UNSOLICITED_CLASS_ASQ_DEVICE:
  2286. case RBC_UNSOLICITED_CLASS_ASQ_MEDIA:
  2287. break;
  2288. case RBC_UNSOLICITED_CLASS_ASQ_POWER:
  2289. //
  2290. // initiate power transtion, per device request
  2291. //
  2292. state.DeviceState = PowerDeviceD0;
  2293. DEBUGPRINT1(("Sbp2Port: HandleUnsolicited: send D irp state=x%x\n ",state));
  2294. status = PoRequestPowerIrp(
  2295. DeviceExtension->DeviceObject,
  2296. IRP_MN_SET_POWER,
  2297. state,
  2298. NULL,
  2299. NULL,
  2300. NULL);
  2301. if (!NT_SUCCESS(status)) {
  2302. //
  2303. // not good, we cant power up the device..
  2304. //
  2305. DEBUGPRINT1(("Sbp2Port: HandleUnsolicited: D irp err=x%x\n ",status));
  2306. }
  2307. break;
  2308. }
  2309. }
  2310. }
  2311. break;
  2312. }
  2313. }
  2314. }
  2315. NTSTATUS
  2316. Sbp2GetControllerInfo(
  2317. IN PDEVICE_EXTENSION DeviceExtension
  2318. )
  2319. /*++
  2320. Routine Description:
  2321. Find the maximum packet size that can be sent across. If there is
  2322. any error, return the minimum size.
  2323. Arguments:
  2324. DeviceExtension - Pointer to device extension.
  2325. IrP - Pointer to Irp. If this is NULL, we have to allocate our own.
  2326. Irb - Pointer to Irb. If this is NULL, we have to allocate our own.
  2327. Return Value:
  2328. NTSTATUS
  2329. --*/
  2330. {
  2331. PIRBIRP packet = NULL;
  2332. NTSTATUS status;
  2333. GET_LOCAL_HOST_INFO7 getLocalHostInfo7;
  2334. AllocateIrpAndIrb (DeviceExtension, &packet);
  2335. if (!packet) {
  2336. return STATUS_INSUFFICIENT_RESOURCES;
  2337. }
  2338. //
  2339. // Get the max speed between devices so that we can calculate the
  2340. // maximum number of bytes we can send
  2341. //
  2342. packet->Irb->FunctionNumber = REQUEST_GET_SPEED_BETWEEN_DEVICES;
  2343. packet->Irb->Flags = 0;
  2344. packet->Irb->u.GetMaxSpeedBetweenDevices.ulNumberOfDestinations = 0;
  2345. packet->Irb->u.GetMaxSpeedBetweenDevices.fulFlags = USE_LOCAL_NODE;
  2346. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  2347. if (!NT_SUCCESS (status)) {
  2348. goto exitFindHostInfo;
  2349. }
  2350. //
  2351. // Calculate the max block size based on the speed
  2352. //
  2353. DeviceExtension->MaxControllerPhySpeed = packet->Irb->u.GetMaxSpeedBetweenDevices.fulSpeed >> 1;
  2354. switch (DeviceExtension->MaxControllerPhySpeed) {
  2355. case SCODE_100_RATE:
  2356. DeviceExtension->OrbWritePayloadMask = (0x00F0 & 0x0070);
  2357. DeviceExtension->OrbReadPayloadMask = (0x00F0 & 0x0070);
  2358. break;
  2359. case SCODE_200_RATE:
  2360. DeviceExtension->OrbWritePayloadMask = (0x00F0 & 0x0080);
  2361. DeviceExtension->OrbReadPayloadMask = (0x00F0 & 0x0080);
  2362. break;
  2363. case SCODE_400_RATE:
  2364. DeviceExtension->OrbWritePayloadMask = (0x00F0 & 0x0090);
  2365. DeviceExtension->OrbReadPayloadMask = (0x00F0 & 0x0090);
  2366. break;
  2367. }
  2368. //
  2369. // find what the host adaptor below us supports...
  2370. // it might support less than the payload for this phy speed
  2371. //
  2372. packet->Irb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  2373. packet->Irb->Flags = 0;
  2374. packet->Irb->u.GetLocalHostInformation.nLevel = GET_HOST_CAPABILITIES;
  2375. packet->Irb->u.GetLocalHostInformation.Information = &DeviceExtension->HostControllerInformation;
  2376. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  2377. if (!NT_SUCCESS(status)) {
  2378. goto exitFindHostInfo;
  2379. }
  2380. switch (DeviceExtension->HostControllerInformation.MaxAsyncWriteRequest) {
  2381. case ASYNC_PAYLOAD_100_RATE:
  2382. DeviceExtension->OrbWritePayloadMask = min((0x00F0 & 0x0070),DeviceExtension->OrbWritePayloadMask);
  2383. break;
  2384. case ASYNC_PAYLOAD_200_RATE:
  2385. DeviceExtension->OrbWritePayloadMask = min((0x00F0 & 0x0080),DeviceExtension->OrbWritePayloadMask);
  2386. break;
  2387. }
  2388. switch (DeviceExtension->HostControllerInformation.MaxAsyncReadRequest) {
  2389. case ASYNC_PAYLOAD_100_RATE:
  2390. DeviceExtension->OrbReadPayloadMask = min((0x00F0 & 0x0070),DeviceExtension->OrbReadPayloadMask);
  2391. break;
  2392. case ASYNC_PAYLOAD_200_RATE:
  2393. DeviceExtension->OrbReadPayloadMask = min((0x00F0 & 0x0080),DeviceExtension->OrbReadPayloadMask);
  2394. break;
  2395. }
  2396. //
  2397. // Get the direct mapping routine from the host adaptor(if it support this)
  2398. // status is not important in this case sinc this is an optional capability
  2399. //
  2400. packet->Irb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  2401. packet->Irb->Flags = 0;
  2402. packet->Irb->u.GetLocalHostInformation.nLevel = GET_PHYS_ADDR_ROUTINE;
  2403. packet->Irb->u.GetLocalHostInformation.Information = &DeviceExtension->HostRoutineAPI;
  2404. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  2405. if (!NT_SUCCESS(status)) {
  2406. //
  2407. // the host controller under us is no supported..
  2408. //
  2409. DEBUGPRINT1(("Sbp2Port: GetCtlrInfo: failed to get phys map rout, fatal\n"));
  2410. goto exitFindHostInfo;
  2411. }
  2412. //
  2413. // find what the host adaptor below us supports...
  2414. // it might support less than the payload for this phy speed
  2415. //
  2416. packet->Irb->FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  2417. packet->Irb->Flags = 0;
  2418. packet->Irb->u.GetLocalHostInformation.nLevel = GET_HOST_DMA_CAPABILITIES;
  2419. packet->Irb->u.GetLocalHostInformation.Information = &getLocalHostInfo7;
  2420. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  2421. if (!NT_SUCCESS(status)) {
  2422. DEBUGPRINT1(("Sbp2Port: GetCtlrInfo: err getting DMA info, def MaxXfer = 64k\n"));
  2423. DeviceExtension->DeviceInfo->MaxClassTransferSize = SBP2_MAX_DIRECT_BUFFER_SIZE+1;
  2424. status = STATUS_SUCCESS;
  2425. } else {
  2426. DeviceExtension->DeviceInfo->MaxClassTransferSize = (ULONG) min(DeviceExtension->DeviceInfo->MaxClassTransferSize,\
  2427. min(getLocalHostInfo7.MaxDmaBufferSize.QuadPart,\
  2428. SBP2_MAX_TRANSFER_SIZE));
  2429. DEBUGPRINT2(("Sbp2Port: GetCtlrInfo: ctlr maxDma=x%x%08x, maxXfer=x%x\n",
  2430. getLocalHostInfo7.MaxDmaBufferSize.HighPart,
  2431. getLocalHostInfo7.MaxDmaBufferSize.LowPart,
  2432. DeviceExtension->DeviceInfo->MaxClassTransferSize));
  2433. }
  2434. exitFindHostInfo:
  2435. DeAllocateIrpAndIrb(DeviceExtension,packet);
  2436. return status;
  2437. }
  2438. NTSTATUS
  2439. Sbp2AccessRegister(
  2440. PDEVICE_EXTENSION DeviceExtension,
  2441. PVOID Data,
  2442. USHORT RegisterAndDirection
  2443. )
  2444. /*++
  2445. Routine Description:
  2446. Knows the how to access SBP2 and 1394 specific target registers. It wills send requests
  2447. of the appropriate size and of the supported type (READ or WRITE) for the specific register
  2448. Arguments:
  2449. DeviceExtension - Pointer to device extension.
  2450. Data - Calue to write to the register
  2451. RegisterAndDirection - BitMask that indicates which register to write and if its a WRITE or a READ
  2452. Return Value:
  2453. NTSTATUS
  2454. --*/
  2455. {
  2456. NTSTATUS status;
  2457. PIRBIRP packet = NULL;
  2458. if (TEST_FLAG(DeviceExtension->DeviceFlags, DEVICE_FLAG_REMOVED)) {
  2459. return STATUS_DEVICE_DOES_NOT_EXIST;
  2460. }
  2461. AllocateIrpAndIrb(DeviceExtension,&packet);
  2462. if (!packet) {
  2463. return STATUS_INSUFFICIENT_RESOURCES;
  2464. }
  2465. //
  2466. // update SBP specific registers at the node
  2467. // We better have all the addressing info before this function is called
  2468. //
  2469. packet->Irb->Flags = 0;
  2470. //
  2471. // check which register we need to whack
  2472. //
  2473. switch (RegisterAndDirection & REG_TYPE_MASK) {
  2474. //
  2475. // write only quadlet sized registers
  2476. //
  2477. case TEST_REG:
  2478. case CORE_BUSY_TIMEOUT_REG:
  2479. case CORE_RESET_REG:
  2480. case UNSOLICITED_STATUS_REG:
  2481. case DOORBELL_REG:
  2482. case AGENT_RESET_REG:
  2483. packet->Irb->FunctionNumber = REQUEST_ASYNC_WRITE;
  2484. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High =
  2485. INITIAL_REGISTER_SPACE_HI;
  2486. packet->Irb->u.AsyncWrite.fulFlags = 0;
  2487. switch(RegisterAndDirection & REG_TYPE_MASK) {
  2488. case TEST_REG:
  2489. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = INITIAL_REGISTER_SPACE_LO
  2490. | TEST_REG_OFFSET;
  2491. *((PULONG)Data) = bswap(*((PULONG)Data));
  2492. break;
  2493. case CORE_BUSY_TIMEOUT_REG:
  2494. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = INITIAL_REGISTER_SPACE_LO
  2495. | 0x00000210;
  2496. *((PULONG)Data) = bswap(*((PULONG)Data));
  2497. break;
  2498. case CORE_RESET_REG:
  2499. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low = INITIAL_REGISTER_SPACE_LO
  2500. | 0x0000000C;
  2501. break;
  2502. case DOORBELL_REG:
  2503. //
  2504. // we dont care if this suceeds or not, and also we dont want to take an INT hit when this is send
  2505. //
  2506. packet->Irb->u.AsyncWrite.fulFlags |= ASYNC_FLAGS_NO_STATUS;
  2507. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  2508. (DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low + DOORBELL_REG_OFFSET) | INITIAL_REGISTER_SPACE_LO;
  2509. break;
  2510. case AGENT_RESET_REG:
  2511. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  2512. (DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low + AGENT_RESET_REG_OFFSET) | INITIAL_REGISTER_SPACE_LO;
  2513. break;
  2514. case UNSOLICITED_STATUS_REG:
  2515. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  2516. (DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low + UNSOLICITED_STATUS_REG_OFFSET) | INITIAL_REGISTER_SPACE_LO;
  2517. break;
  2518. }
  2519. //
  2520. // for all of the above writes, where the data is not signigficant(ping)
  2521. // we have reserved an mdl so we dont have to allocate each time
  2522. //
  2523. packet->Irb->u.AsyncWrite.Mdl = DeviceExtension->ReservedMdl;
  2524. packet->Irb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(QUADLET);
  2525. packet->Irb->u.AsyncWrite.nBlockSize = 0;
  2526. packet->Irb->u.AsyncWrite.ulGeneration = DeviceExtension->CurrentGeneration;
  2527. break;
  2528. case MANAGEMENT_AGENT_REG:
  2529. case ORB_POINTER_REG:
  2530. if ((RegisterAndDirection & REG_WRITE_SYNC) || (RegisterAndDirection & REG_WRITE_ASYNC) ){
  2531. //
  2532. // Swap the stuff we want ot write to the register.
  2533. // the caller always passes the octlet in little endian
  2534. //
  2535. packet->Octlet = *(POCTLET)Data;
  2536. octbswap(packet->Octlet);
  2537. packet->Irb->FunctionNumber = REQUEST_ASYNC_WRITE;
  2538. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_High =
  2539. INITIAL_REGISTER_SPACE_HI;
  2540. if (RegisterAndDirection & ORB_POINTER_REG) {
  2541. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  2542. (DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low + ORB_POINTER_REG_OFFSET) | INITIAL_REGISTER_SPACE_LO;
  2543. } else {
  2544. packet->Irb->u.AsyncWrite.DestinationAddress.IA_Destination_Offset.Off_Low =
  2545. DeviceExtension->DeviceInfo->ManagementAgentBaseReg.BusAddress.Off_Low | INITIAL_REGISTER_SPACE_LO;
  2546. }
  2547. packet->Irb->u.AsyncWrite.Mdl = IoAllocateMdl(&packet->Octlet, sizeof(OCTLET),FALSE,FALSE,NULL);
  2548. if (!packet->Irb->u.AsyncWrite.Mdl) {
  2549. DeAllocateIrpAndIrb(DeviceExtension,packet);
  2550. return STATUS_INSUFFICIENT_RESOURCES;
  2551. }
  2552. packet->Irb->u.AsyncWrite.nNumberOfBytesToWrite = sizeof(OCTLET);
  2553. packet->Irb->u.AsyncWrite.nBlockSize = 0;
  2554. packet->Irb->u.AsyncWrite.fulFlags = 0;
  2555. packet->Irb->u.AsyncWrite.ulGeneration = DeviceExtension->CurrentGeneration;
  2556. MmBuildMdlForNonPagedPool(packet->Irb->u.AsyncWrite.Mdl);
  2557. } else {
  2558. packet->Irb->FunctionNumber = REQUEST_ASYNC_READ;
  2559. if (RegisterAndDirection & ORB_POINTER_REG) {
  2560. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low =
  2561. (DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_Low + ORB_POINTER_REG_OFFSET);
  2562. } else {
  2563. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_Low =
  2564. DeviceExtension->DeviceInfo->ManagementAgentBaseReg.BusAddress.Off_Low;
  2565. }
  2566. packet->Irb->u.AsyncRead.DestinationAddress.IA_Destination_Offset.Off_High =
  2567. DeviceExtension->DeviceInfo->CsrRegisterBase.BusAddress.Off_High;
  2568. packet->Irb->u.AsyncRead.Mdl = IoAllocateMdl(Data, sizeof(OCTLET),FALSE,FALSE,NULL);
  2569. if (!packet->Irb->u.AsyncRead.Mdl) {
  2570. DeAllocateIrpAndIrb(DeviceExtension,packet);
  2571. return STATUS_INSUFFICIENT_RESOURCES;
  2572. }
  2573. packet->Irb->u.AsyncRead.nNumberOfBytesToRead = sizeof(OCTLET);
  2574. packet->Irb->u.AsyncRead.nBlockSize = 0;
  2575. packet->Irb->u.AsyncRead.fulFlags = 0;
  2576. packet->Irb->u.AsyncRead.ulGeneration = DeviceExtension->CurrentGeneration;
  2577. MmBuildMdlForNonPagedPool(packet->Irb->u.AsyncRead.Mdl);
  2578. }
  2579. break;
  2580. }
  2581. if (RegisterAndDirection & REG_WRITE_ASYNC) {
  2582. status = Sbp2SendRequest (DeviceExtension, packet, ASYNC_1394_REQUEST);
  2583. } else {
  2584. status = Sbp2SendRequest (DeviceExtension, packet, SYNC_1394_REQUEST);
  2585. if (NT_SUCCESS(status)) {
  2586. if (RegisterAndDirection & REG_READ_SYNC) {
  2587. //
  2588. // convert from big -> little endian for read data
  2589. //
  2590. switch (RegisterAndDirection & REG_TYPE_MASK) {
  2591. case ORB_POINTER_REG:
  2592. case MANAGEMENT_AGENT_REG:
  2593. packet->Octlet = *((POCTLET)Data);
  2594. octbswap(packet->Octlet);
  2595. *((POCTLET)Data) = packet->Octlet;
  2596. break;
  2597. }
  2598. }
  2599. }
  2600. if (packet->Irb->u.AsyncWrite.nNumberOfBytesToWrite == sizeof(OCTLET)) {
  2601. IoFreeMdl(packet->Irb->u.AsyncRead.Mdl);
  2602. }
  2603. DeAllocateIrpAndIrb(DeviceExtension,packet);
  2604. }
  2605. return status;
  2606. }