Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
10 KiB

  1. /*++
  2. Copyright (C) 1990 - 99 Microsoft Corporation
  3. Module Name:
  4. port.c
  5. Abstract:
  6. This is the NT SCSI port driver.
  7. Authors:
  8. Mike Glass
  9. Jeff Havens
  10. Environment:
  11. kernel mode only
  12. Notes:
  13. This module is a dll for the kernel.
  14. Revision History:
  15. --*/
  16. #include "ideport.h"
  17. //#include "port.h"
  18. VOID
  19. IdePortNotification(
  20. IN IDE_NOTIFICATION_TYPE NotificationType,
  21. IN PVOID HwDeviceExtension,
  22. ...
  23. )
  24. /*++
  25. Routine Description:
  26. Arguments:
  27. Return Value:
  28. --*/
  29. {
  30. PFDO_EXTENSION deviceExtension = (PFDO_EXTENSION) HwDeviceExtension - 1;
  31. PLOGICAL_UNIT_EXTENSION logicalUnit;
  32. PSRB_DATA srbData;
  33. PSCSI_REQUEST_BLOCK srb;
  34. UCHAR pathId;
  35. UCHAR targetId;
  36. UCHAR lun;
  37. va_list ap;
  38. va_start(ap, HwDeviceExtension);
  39. switch (NotificationType) {
  40. case IdeNextRequest:
  41. //
  42. // Start next packet on adapter's queue.
  43. //
  44. deviceExtension->InterruptData.InterruptFlags |= PD_READY_FOR_NEXT_REQUEST;
  45. break;
  46. case IdeRequestComplete:
  47. srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
  48. ASSERT(srb->SrbStatus != SRB_STATUS_PENDING);
  49. ASSERT(srb->SrbStatus != SRB_STATUS_SUCCESS || srb->ScsiStatus == SCSISTAT_GOOD || srb->Function != SRB_FUNCTION_EXECUTE_SCSI);
  50. //
  51. // If this srb has already been completed then return.
  52. //
  53. if (!(srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) {
  54. va_end(ap);
  55. return;
  56. }
  57. //
  58. // Clear the active flag.
  59. //
  60. CLRMASK (srb->SrbFlags, SRB_FLAGS_IS_ACTIVE);
  61. //
  62. // Treat abort completions as a special case.
  63. //
  64. if (srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
  65. PIRP irp;
  66. PIO_STACK_LOCATION irpStack;
  67. irp = srb->OriginalRequest;
  68. irpStack = IoGetCurrentIrpStackLocation(irp);
  69. logicalUnit = IDEPORT_GET_LUNEXT_IN_IRP(irpStack);
  70. logicalUnit->CompletedAbort =
  71. deviceExtension->InterruptData.CompletedAbort;
  72. deviceExtension->InterruptData.CompletedAbort = logicalUnit;
  73. } else {
  74. PIDE_REGISTERS_1 baseIoAddress1 = &(deviceExtension->
  75. HwDeviceExtension->BaseIoAddress1);
  76. //
  77. // Get the SRB data and link it into the completion list.
  78. //
  79. srbData = IdeGetSrbData(deviceExtension, srb);
  80. ASSERT(srbData);
  81. ASSERT(srbData->CurrentSrb != NULL && srbData->CompletedRequests == NULL);
  82. if ((srb->SrbStatus == SRB_STATUS_SUCCESS) &&
  83. ((srb->Cdb[0] == SCSIOP_READ) ||
  84. (srb->Cdb[0] == SCSIOP_WRITE))) {
  85. ASSERT(srb->DataTransferLength);
  86. }
  87. ASSERT (deviceExtension->InterruptData.CompletedRequests == NULL);
  88. srbData->CompletedRequests =
  89. deviceExtension->InterruptData.CompletedRequests;
  90. deviceExtension->InterruptData.CompletedRequests = srbData;
  91. //
  92. // Save the task file registers
  93. //
  94. IdeLogSaveTaskFile(srbData, baseIoAddress1);
  95. }
  96. break;
  97. case IdeResetDetected:
  98. {
  99. PIRP irp;
  100. PIO_STACK_LOCATION irpStack;
  101. //
  102. // Notifiy the port driver that a reset has been reported.
  103. //
  104. srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
  105. if (srb) {
  106. irp = srb->OriginalRequest;
  107. irpStack = IoGetCurrentIrpStackLocation(irp);
  108. logicalUnit = IDEPORT_GET_LUNEXT_IN_IRP(irpStack);
  109. } else {
  110. logicalUnit = NULL;
  111. }
  112. ASSERT(deviceExtension->InterruptData.PdoExtensionResetBus == NULL);
  113. deviceExtension->InterruptData.InterruptFlags |= PD_RESET_REPORTED;
  114. deviceExtension->InterruptData.PdoExtensionResetBus = logicalUnit;
  115. break;
  116. }
  117. case IdeRequestTimerCall:
  118. //
  119. // The driver wants to set the miniport timer.
  120. // Save the timer parameters.
  121. //
  122. deviceExtension->InterruptData.InterruptFlags |=
  123. PD_TIMER_CALL_REQUEST;
  124. deviceExtension->InterruptData.HwTimerRequest =
  125. va_arg(ap, PHW_INTERRUPT);
  126. deviceExtension->InterruptData.MiniportTimerValue =
  127. va_arg(ap, ULONG);
  128. break;
  129. case IdeAllDeviceMissing:
  130. deviceExtension->InterruptData.InterruptFlags |= PD_ALL_DEVICE_MISSING;
  131. break;
  132. case IdeResetRequest:
  133. //
  134. // A reset was requested
  135. //
  136. deviceExtension->InterruptData.InterruptFlags |= PD_RESET_REQUEST;
  137. break;
  138. default:
  139. ASSERT(0);
  140. }
  141. va_end(ap);
  142. //
  143. // Request a DPC be queued after the interrupt completes.
  144. //
  145. deviceExtension->InterruptData.InterruptFlags |= PD_NOTIFICATION_REQUIRED;
  146. } // end IdePortNotification()
  147. VOID
  148. IdePortLogError(
  149. IN PVOID HwDeviceExtension,
  150. IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
  151. IN UCHAR PathId,
  152. IN UCHAR TargetId,
  153. IN UCHAR Lun,
  154. IN ULONG ErrorCode,
  155. IN ULONG UniqueId
  156. )
  157. /*++
  158. Routine Description:
  159. This routine saves the error log information, and queues a DPC if necessary.
  160. Arguments:
  161. HwDeviceExtension - Supplies the HBA miniport driver's adapter data storage.
  162. Srb - Supplies an optional pointer to srb if there is one.
  163. TargetId, Lun and PathId - specify device address on a SCSI bus.
  164. ErrorCode - Supplies an error code indicating the type of error.
  165. UniqueId - Supplies a unique identifier for the error.
  166. Return Value:
  167. None.
  168. --*/
  169. {
  170. PFDO_EXTENSION deviceExtension =
  171. ((PFDO_EXTENSION) HwDeviceExtension) - 1;
  172. PDEVICE_OBJECT DeviceObject = deviceExtension->DeviceObject;
  173. PSRB_DATA srbData;
  174. PERROR_LOG_ENTRY errorLogEntry;
  175. //
  176. // If the error log entry is already full, then dump the error.
  177. //
  178. if (deviceExtension->InterruptData.InterruptFlags & PD_LOG_ERROR) {
  179. #if DBG
  180. DebugPrint((1,"IdePortLogError: Dumping scsi error log packet.\n"));
  181. DebugPrint((1,
  182. "PathId = %2x, TargetId = %2x, Lun = %2x, ErrorCode = %x, UniqueId = %x.",
  183. PathId,
  184. TargetId,
  185. Lun,
  186. ErrorCode,
  187. UniqueId
  188. ));
  189. #endif
  190. return;
  191. }
  192. //
  193. // Save the error log data in the log entry.
  194. //
  195. errorLogEntry = &deviceExtension->InterruptData.LogEntry;
  196. errorLogEntry->ErrorCode = ErrorCode;
  197. errorLogEntry->TargetId = TargetId;
  198. errorLogEntry->Lun = Lun;
  199. errorLogEntry->PathId = PathId;
  200. errorLogEntry->UniqueId = UniqueId;
  201. //
  202. // Get the sequence number from the SRB data.
  203. //
  204. if (Srb != NULL) {
  205. srbData = IdeGetSrbData(deviceExtension, Srb);
  206. if (srbData == NULL) {
  207. return;
  208. }
  209. errorLogEntry->SequenceNumber = srbData->SequenceNumber;
  210. errorLogEntry->ErrorLogRetryCount = srbData->ErrorLogRetryCount++;
  211. } else {
  212. errorLogEntry->SequenceNumber = 0;
  213. errorLogEntry->ErrorLogRetryCount = 0;
  214. }
  215. //
  216. // Indicate that the error log entry is in use.
  217. //
  218. deviceExtension->InterruptData.InterruptFlags |= PD_LOG_ERROR;
  219. //
  220. // Request a DPC be queued after the interrupt completes.
  221. //
  222. deviceExtension->InterruptData.InterruptFlags |= PD_NOTIFICATION_REQUIRED;
  223. return;
  224. } // end IdePortLogError()
  225. VOID
  226. IdePortCompleteRequest(
  227. IN PVOID HwDeviceExtension,
  228. IN PSCSI_REQUEST_BLOCK Srb,
  229. IN UCHAR SrbStatus
  230. )
  231. /*++
  232. Routine Description:
  233. Complete all active requests for the specified logical unit.
  234. Arguments:
  235. DeviceExtenson - Supplies the HBA miniport driver's adapter data storage.
  236. TargetId, Lun and PathId - specify device address on a SCSI bus.
  237. SrbStatus - Status to be returned in each completed SRB.
  238. Return Value:
  239. None.
  240. --*/
  241. {
  242. PFDO_EXTENSION fdoExtension = ((PFDO_EXTENSION) HwDeviceExtension) - 1;
  243. PLOGICAL_UNIT_EXTENSION logUnitExtension;
  244. PIO_STACK_LOCATION irpStack;
  245. PIRP Irp;
  246. PSRB_DATA srbData;
  247. PLIST_ENTRY entry;
  248. ULONG limit = 0;
  249. Irp = (PIRP) Srb->OriginalRequest;
  250. irpStack = IoGetCurrentIrpStackLocation(Irp);
  251. logUnitExtension = IDEPORT_GET_LUNEXT_IN_IRP(irpStack);
  252. DebugPrint((2,
  253. "IdePortCompleteRequest: Complete requests for targetid %d\n",
  254. logUnitExtension->TargetId));
  255. //
  256. // Complete any pending abort reqeusts.
  257. //
  258. if (logUnitExtension->AbortSrb != NULL) {
  259. logUnitExtension->AbortSrb->SrbStatus = SrbStatus;
  260. IdePortNotification(
  261. IdeRequestComplete,
  262. HwDeviceExtension,
  263. logUnitExtension->AbortSrb
  264. );
  265. }
  266. IdeCompleteRequest(fdoExtension, &logUnitExtension->SrbData, SrbStatus);
  267. return;
  268. } // end IdePortCompleteRequest()
  269. BOOLEAN
  270. TestForEnumProbing (
  271. IN PSCSI_REQUEST_BLOCK Srb
  272. )
  273. {
  274. BOOLEAN enumProbing = FALSE;
  275. if (Srb) {
  276. if ((Srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH) ||
  277. (Srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH)) {
  278. PATA_PASS_THROUGH ataPassThroughData;
  279. ataPassThroughData = Srb->DataBuffer;
  280. enumProbing = ataPassThroughData->IdeReg.bReserved & ATA_PTFLAGS_ENUM_PROBING ? TRUE: FALSE;
  281. }
  282. }
  283. return enumProbing;
  284. }