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.

1067 lines
35 KiB

  1. /*++
  2. Copyright (C) 1997-99 Microsoft Corporation
  3. Module Name:
  4. detect.c
  5. Abstract:
  6. This contain legacy detection routines
  7. Author:
  8. Joe Dai (joedai)
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "ideport.h"
  15. #if !defined(NO_LEGACY_DRIVERS)
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(INIT, IdePortDetectLegacyController)
  18. #pragma alloc_text(INIT, IdePortCreateDetectionList)
  19. #pragma alloc_text(INIT, IdePortTranslateAddress)
  20. #pragma alloc_text(INIT, IdePortFreeTranslatedAddress)
  21. #pragma alloc_text(INIT, IdePortDetectAlias)
  22. #endif // ALLOC_PRAGMA
  23. NTSTATUS
  24. IdePortDetectLegacyController (
  25. IN PDRIVER_OBJECT DriverObject,
  26. IN PUNICODE_STRING RegistryPath
  27. )
  28. /*++
  29. Routine Description:
  30. Detect legacy IDE controllers and report them to PnP
  31. Arguments:
  32. DriverObject - this driver's driver object
  33. RegistryPath - this driver's registry path
  34. Return Value:
  35. NT Status
  36. --*/
  37. {
  38. ULONG cmResourceListSize;
  39. PCM_RESOURCE_LIST cmResourceList = NULL;
  40. PCM_FULL_RESOURCE_DESCRIPTOR cmFullResourceDescriptor;
  41. PCM_PARTIAL_RESOURCE_LIST cmPartialResourceList;
  42. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDescriptors;
  43. BOOLEAN conflictDetected;
  44. BOOLEAN resourceIsCmdPort;
  45. PDEVICE_OBJECT detectedPhysicalDeviceObject;
  46. PFDO_EXTENSION fdoExtension = NULL;
  47. UNICODE_STRING deviceClassName;
  48. NTSTATUS status;
  49. PDETECTION_PORT detectionPort;
  50. ULONG numPort;
  51. ULONG portNumber;
  52. ULONG deviceNumber;
  53. ULONG descriptorNumber;
  54. ULONG cmdAddressSpace;
  55. ULONG ctrlAddressSpace;
  56. PUCHAR cmdRegBase;
  57. PUCHAR ctrlRegBase;
  58. IDE_REGISTERS_1 baseIoAddress1;
  59. IDE_REGISTERS_2 baseIoAddress2;
  60. PHYSICAL_ADDRESS cmdRegMemoryBase;
  61. PHYSICAL_ADDRESS ctrlRegMemoryBase;
  62. UCHAR statusByte;
  63. ULONG baseIoAddress1Length;
  64. ULONG baseIoAddress2Length;
  65. ULONG maxIdeDevice;
  66. UCHAR altMasterStatus;
  67. UCHAR altSlaveStatus;
  68. #if !defined (ALWAYS_DO_LEGACY_DETECTION)
  69. if (!IdePortOkToDetectLegacy(DriverObject)) {
  70. //
  71. // legacy detection is not enabled
  72. //
  73. return STATUS_SUCCESS;
  74. }
  75. #endif
  76. //
  77. // make up a list of popular legacy I/O ports
  78. //
  79. status = IdePortCreateDetectionList (
  80. DriverObject,
  81. &detectionPort,
  82. &numPort
  83. );
  84. if (!NT_SUCCESS(status)) {
  85. goto GetOut;
  86. }
  87. //
  88. // Resource Requirement List
  89. //
  90. cmResourceListSize = sizeof (CM_RESOURCE_LIST) +
  91. sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (((!IsNEC_98) ? 3 : 12) - 1);
  92. cmResourceList = ExAllocatePool (PagedPool, cmResourceListSize);
  93. if (cmResourceList == NULL){
  94. status = STATUS_NO_MEMORY;
  95. goto GetOut;
  96. }
  97. RtlZeroMemory(cmResourceList, cmResourceListSize);
  98. RtlInitUnicodeString(&deviceClassName, L"ScsiAdapter");
  99. for (portNumber=0; portNumber<numPort; portNumber++) {
  100. //
  101. // Build io address structure.
  102. //
  103. AtapiBuildIoAddress ( (PUCHAR)detectionPort[portNumber].CommandRegisterBase,
  104. (PUCHAR)detectionPort[portNumber].ControlRegisterBase,
  105. &baseIoAddress1,
  106. &baseIoAddress2,
  107. &baseIoAddress1Length,
  108. &baseIoAddress2Length,
  109. &maxIdeDevice,
  110. NULL);
  111. //
  112. // Build resource requirement list
  113. //
  114. cmResourceList->Count = 1;
  115. cmFullResourceDescriptor = cmResourceList->List;
  116. cmFullResourceDescriptor->InterfaceType = Isa;
  117. cmFullResourceDescriptor->BusNumber = 0;
  118. cmPartialResourceList = &cmFullResourceDescriptor->PartialResourceList;
  119. cmPartialResourceList->Version = 1;
  120. cmPartialResourceList->Revision = 1;
  121. cmPartialResourceList->Count = 3;
  122. cmPartialDescriptors = cmPartialResourceList->PartialDescriptors;
  123. cmPartialDescriptors[0].Type = CmResourceTypePort;
  124. cmPartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
  125. cmPartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO |
  126. (!Is98LegacyIde(&baseIoAddress1)? CM_RESOURCE_PORT_10_BIT_DECODE :
  127. CM_RESOURCE_PORT_16_BIT_DECODE);
  128. cmPartialDescriptors[0].u.Port.Length = baseIoAddress1Length;
  129. cmPartialDescriptors[0].u.Port.Start.QuadPart = detectionPort[portNumber].CommandRegisterBase;
  130. cmPartialDescriptors[1].Type = CmResourceTypePort;
  131. cmPartialDescriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
  132. cmPartialDescriptors[1].Flags = CM_RESOURCE_PORT_IO |
  133. (!Is98LegacyIde(&baseIoAddress1)? CM_RESOURCE_PORT_10_BIT_DECODE :
  134. CM_RESOURCE_PORT_16_BIT_DECODE);
  135. cmPartialDescriptors[1].u.Port.Length = 1;
  136. cmPartialDescriptors[1].u.Port.Start.QuadPart = detectionPort[portNumber].ControlRegisterBase;
  137. cmPartialDescriptors[2].Type = CmResourceTypeInterrupt;
  138. cmPartialDescriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
  139. cmPartialDescriptors[2].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
  140. cmPartialDescriptors[2].u.Interrupt.Level = detectionPort[portNumber].IrqLevel;
  141. cmPartialDescriptors[2].u.Interrupt.Vector = detectionPort[portNumber].IrqLevel;
  142. cmPartialDescriptors[2].u.Interrupt.Affinity = -1;
  143. if (Is98LegacyIde(&baseIoAddress1)) {
  144. ULONG resourceCount;
  145. ULONG commandRegisters;
  146. commandRegisters = detectionPort[portNumber].CommandRegisterBase + 2;
  147. resourceCount = 3;
  148. while (commandRegisters < (IDE_NEC98_COMMAND_PORT_ADDRESS + 0x10)) {
  149. cmPartialDescriptors[resourceCount].Type = CmResourceTypePort;
  150. cmPartialDescriptors[resourceCount].ShareDisposition = CmResourceShareDeviceExclusive;
  151. cmPartialDescriptors[resourceCount].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  152. cmPartialDescriptors[resourceCount].u.Port.Length = 1;
  153. cmPartialDescriptors[resourceCount].u.Port.Start.QuadPart = commandRegisters;
  154. resourceCount++;
  155. commandRegisters += 2;
  156. }
  157. cmPartialDescriptors[resourceCount].Type = CmResourceTypePort;
  158. cmPartialDescriptors[resourceCount].ShareDisposition = CmResourceShareDeviceExclusive;
  159. cmPartialDescriptors[resourceCount].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  160. cmPartialDescriptors[resourceCount].u.Port.Length = 2;
  161. cmPartialDescriptors[resourceCount].u.Port.Start.QuadPart = (ULONG_PTR)SELECT_IDE_PORT;
  162. resourceCount++;
  163. cmPartialDescriptors[resourceCount].Type = CmResourceTypePort;
  164. cmPartialDescriptors[resourceCount].ShareDisposition = CmResourceShareDeviceExclusive;
  165. cmPartialDescriptors[resourceCount].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  166. cmPartialDescriptors[resourceCount].u.Port.Length = 1;
  167. cmPartialDescriptors[resourceCount].u.Port.Start.QuadPart = (ULONG_PTR)SELECT_IDE_PORT + 3;
  168. resourceCount++;
  169. cmPartialResourceList->Count = resourceCount;
  170. }
  171. //
  172. // check to see if the resource is available
  173. // if not, assume no legacy IDE controller
  174. // is at the this location
  175. //
  176. for (deviceNumber=0; deviceNumber<2; deviceNumber++) {
  177. status = IoReportResourceForDetection (
  178. DriverObject,
  179. cmResourceList,
  180. cmResourceListSize,
  181. NULL,
  182. NULL,
  183. 0,
  184. &conflictDetected
  185. );
  186. if (NT_SUCCESS(status) && !conflictDetected) {
  187. //
  188. // got our resources
  189. //
  190. break;
  191. } else {
  192. if (NT_SUCCESS(status)) {
  193. IoReportResourceForDetection (
  194. DriverObject,
  195. NULL,
  196. 0,
  197. NULL,
  198. NULL,
  199. 0,
  200. &conflictDetected
  201. );
  202. status = STATUS_UNSUCCESSFUL;
  203. }
  204. //
  205. // try 16 bit decode
  206. //
  207. cmPartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  208. cmPartialDescriptors[1].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  209. if (Is98LegacyIde(&baseIoAddress1)) {
  210. ULONG k;
  211. for (k=3; k<12; k++) {
  212. cmPartialDescriptors[k].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  213. }
  214. }
  215. }
  216. }
  217. if (!NT_SUCCESS(status)) {
  218. continue;
  219. }
  220. //
  221. // translate the i/o port via Hal
  222. //
  223. status = STATUS_SUCCESS;
  224. if (Is98LegacyIde(&baseIoAddress1)) {
  225. for (descriptorNumber=3; descriptorNumber<12; descriptorNumber++) {
  226. cmdRegBase = NULL;
  227. cmdAddressSpace = IO_SPACE;
  228. status = IdePortTranslateAddress (
  229. cmFullResourceDescriptor->InterfaceType,
  230. cmFullResourceDescriptor->BusNumber,
  231. cmPartialDescriptors[descriptorNumber].u.Port.Start,
  232. cmPartialDescriptors[descriptorNumber].u.Port.Length,
  233. &cmdAddressSpace,
  234. &cmdRegBase,
  235. &cmdRegMemoryBase
  236. );
  237. if (!NT_SUCCESS(status)) {
  238. break;
  239. }
  240. }
  241. }
  242. if (NT_SUCCESS(status)) {
  243. cmdRegBase = NULL;
  244. ctrlRegBase = NULL;
  245. cmdAddressSpace = IO_SPACE;
  246. status = IdePortTranslateAddress (
  247. cmFullResourceDescriptor->InterfaceType,
  248. cmFullResourceDescriptor->BusNumber,
  249. cmPartialDescriptors[0].u.Port.Start,
  250. cmPartialDescriptors[0].u.Port.Length,
  251. &cmdAddressSpace,
  252. &cmdRegBase,
  253. &cmdRegMemoryBase
  254. );
  255. }
  256. if (NT_SUCCESS(status)) {
  257. ctrlRegBase = NULL;
  258. ctrlAddressSpace = IO_SPACE;
  259. status = IdePortTranslateAddress (
  260. cmFullResourceDescriptor->InterfaceType,
  261. cmFullResourceDescriptor->BusNumber,
  262. cmPartialDescriptors[1].u.Port.Start,
  263. cmPartialDescriptors[1].u.Port.Length,
  264. &ctrlAddressSpace,
  265. &ctrlRegBase,
  266. &ctrlRegMemoryBase
  267. );
  268. }
  269. if (NT_SUCCESS(status)) {
  270. //
  271. // 2nd build io address structure.
  272. //
  273. AtapiBuildIoAddress ( cmdRegBase,
  274. ctrlRegBase,
  275. &baseIoAddress1,
  276. &baseIoAddress2,
  277. &baseIoAddress1Length,
  278. &baseIoAddress2Length,
  279. &maxIdeDevice,
  280. NULL);
  281. //
  282. // The IBM Aptiva ide channel with the external cdrom doesn't power up with any device selected
  283. // we must select a device; otherwise, we get a 0xff from all IO ports
  284. //
  285. SelectIdeDevice(&baseIoAddress1, 0, 0);
  286. altMasterStatus = IdePortInPortByte(baseIoAddress2.DeviceControl);
  287. SelectIdeDevice(&baseIoAddress1, 1, 0);
  288. altSlaveStatus = IdePortInPortByte(baseIoAddress2.DeviceControl);
  289. if ((!Is98LegacyIde(&baseIoAddress1)) && (altMasterStatus == 0xff) && (altSlaveStatus == 0xff)) {
  290. //
  291. // the alternate status byte is 0xff,
  292. // guessing we have a SCSI adapter (DPT) that emulate IDE controller
  293. // say the channel is empty, let the real SCSI driver picks up
  294. // the controller
  295. //
  296. status = STATUS_UNSUCCESSFUL;
  297. //
  298. // Note: The IDE port on SB16/AWE32 does not have the alternate status
  299. // register. Because of this alternate status test, we will fail to
  300. // detect this IDE port. However, this IDE port should be enumerated
  301. // by ISA-PnP bus driver.
  302. //
  303. } else if (IdePortChannelEmpty (&baseIoAddress1, &baseIoAddress2, maxIdeDevice)) {
  304. //
  305. // channel looks empty
  306. //
  307. status = STATUS_UNSUCCESSFUL;
  308. } else {
  309. BOOLEAN deviceFound;
  310. IDENTIFY_DATA IdentifyData;
  311. ULONG i;
  312. for (i=0; i<maxIdeDevice; i++) {
  313. if (Is98LegacyIde(&baseIoAddress1)) {
  314. UCHAR driveHeadReg;
  315. //
  316. // Check master device only.
  317. //
  318. if ( i & 0x1 ) {
  319. continue;
  320. }
  321. //
  322. // Check device is present.
  323. //
  324. SelectIdeDevice(&baseIoAddress1, i, 0);
  325. driveHeadReg = IdePortInPortByte(baseIoAddress1.DriveSelect);
  326. if (driveHeadReg != ((i & 0x1) << 4 | 0xA0)) {
  327. //
  328. // Bad controller.
  329. //
  330. continue;
  331. }
  332. }
  333. //
  334. // Is there a ATA device?
  335. //
  336. deviceFound = IssueIdentify(
  337. &baseIoAddress1,
  338. &baseIoAddress2,
  339. i,
  340. IDE_COMMAND_IDENTIFY,
  341. TRUE,
  342. &IdentifyData
  343. );
  344. if (deviceFound) {
  345. break;
  346. }
  347. //
  348. // Is there a ATAPI device?
  349. //
  350. deviceFound = IssueIdentify(
  351. &baseIoAddress1,
  352. &baseIoAddress2,
  353. i,
  354. IDE_COMMAND_ATAPI_IDENTIFY,
  355. TRUE,
  356. &IdentifyData
  357. );
  358. if (deviceFound) {
  359. break;
  360. }
  361. }
  362. if (!deviceFound) {
  363. status = STATUS_UNSUCCESSFUL;
  364. }
  365. }
  366. }
  367. if (!NT_SUCCESS (status)) {
  368. //
  369. // if we didn't found anything,
  370. // unmap the reosurce
  371. //
  372. if (cmdRegBase) {
  373. IdePortFreeTranslatedAddress (
  374. cmdRegBase,
  375. cmPartialDescriptors[0].u.Port.Length,
  376. cmdAddressSpace
  377. );
  378. if (Is98LegacyIde(&baseIoAddress1)) {
  379. for (descriptorNumber=3; descriptorNumber<12; descriptorNumber++) {
  380. IdePortFreeTranslatedAddress (
  381. cmdRegBase,
  382. cmPartialDescriptors[descriptorNumber].u.Port.Length,
  383. cmdAddressSpace
  384. );
  385. }
  386. }
  387. }
  388. if (ctrlRegBase) {
  389. IdePortFreeTranslatedAddress (
  390. ctrlRegBase,
  391. cmPartialDescriptors[1].u.Port.Length,
  392. ctrlAddressSpace
  393. );
  394. }
  395. } else {
  396. //
  397. // check for alias ports
  398. //
  399. if (cmPartialDescriptors[0].Flags & CM_RESOURCE_PORT_10_BIT_DECODE) {
  400. if (!IdePortDetectAlias (&baseIoAddress1)) {
  401. cmPartialDescriptors[0].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  402. cmPartialDescriptors[1].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  403. if (Is98LegacyIde(&baseIoAddress1)) {
  404. for (descriptorNumber=3; descriptorNumber<12; descriptorNumber++) {
  405. cmPartialDescriptors[descriptorNumber].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE;
  406. }
  407. }
  408. }
  409. }
  410. }
  411. //
  412. // release the resources we have grab, IoReportDetectedDevice()
  413. // will grab them for us again when we call and it will grab them
  414. // on behalf of the detected PDO.
  415. //
  416. IoReportResourceForDetection (
  417. DriverObject,
  418. NULL,
  419. 0,
  420. NULL,
  421. NULL,
  422. 0,
  423. &conflictDetected
  424. );
  425. if (NT_SUCCESS(status)) {
  426. detectedPhysicalDeviceObject = NULL;
  427. status = IoReportDetectedDevice(DriverObject,
  428. InterfaceTypeUndefined,
  429. -1,
  430. -1,
  431. cmResourceList,
  432. NULL,
  433. FALSE,
  434. &detectedPhysicalDeviceObject);
  435. if (NT_SUCCESS (status)) {
  436. //
  437. // create a FDO and attach it to the detected PDO
  438. //
  439. status = ChannelAddChannel (
  440. DriverObject,
  441. detectedPhysicalDeviceObject,
  442. &fdoExtension
  443. );
  444. if (NT_SUCCESS (status)) {
  445. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList;
  446. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  447. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors;
  448. ULONG i, j;
  449. //
  450. // translate resources
  451. //
  452. fullResourceList = cmResourceList->List;
  453. for (i=0; i<cmResourceList->Count; i++) {
  454. partialResourceList = &(fullResourceList->PartialResourceList);
  455. partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
  456. for (j=0; j<partialResourceList->Count; j++) {
  457. resourceIsCmdPort = FALSE;
  458. if (!Is98LegacyIde(&baseIoAddress1)) {
  459. if ((partialDescriptors[j].Type == CmResourceTypePort) &&
  460. (partialDescriptors[j].u.Port.Length == baseIoAddress1Length)) {
  461. resourceIsCmdPort = TRUE;
  462. }
  463. } else {
  464. if ((partialDescriptors[j].Type == CmResourceTypePort) &&
  465. (partialDescriptors[j].u.Port.Start.QuadPart == IDE_NEC98_COMMAND_PORT_ADDRESS)) {
  466. resourceIsCmdPort = TRUE;
  467. } else if ((partialDescriptors[j].Type == CmResourceTypePort) &&
  468. (partialDescriptors[j].u.Port.Start.QuadPart != IDE_NEC98_COMMAND_PORT_ADDRESS) &&
  469. (partialDescriptors[j].u.Port.Start.QuadPart != (IDE_NEC98_COMMAND_PORT_ADDRESS + 0x10C))) {
  470. //
  471. // This is not the base port address for Legacy ide on NEC98;
  472. //
  473. continue;
  474. }
  475. }
  476. if (resourceIsCmdPort) {
  477. if (cmdAddressSpace == MEMORY_SPACE) {
  478. partialDescriptors[j].Type = CmResourceTypeMemory;
  479. partialDescriptors[j].u.Memory.Start = cmdRegMemoryBase;
  480. partialDescriptors[j].u.Memory.Length = partialDescriptors[j].u.Port.Length;
  481. } else {
  482. partialDescriptors[j].u.Port.Start.QuadPart = (ULONG_PTR) cmdRegBase;
  483. }
  484. } else if ((partialDescriptors[j].Type == CmResourceTypePort) &&
  485. (partialDescriptors[j].u.Port.Length == 1)) {
  486. if (ctrlAddressSpace == MEMORY_SPACE) {
  487. partialDescriptors[j].Type = CmResourceTypeMemory;
  488. partialDescriptors[j].u.Memory.Start = ctrlRegMemoryBase;
  489. partialDescriptors[j].u.Memory.Length = partialDescriptors[j].u.Port.Length;
  490. } else {
  491. partialDescriptors[j].u.Port.Start.QuadPart = (ULONG_PTR) ctrlRegBase;
  492. }
  493. } else if (partialDescriptors[j].Type == CmResourceTypeInterrupt) {
  494. partialDescriptors[j].u.Interrupt.Vector = HalGetInterruptVector(fullResourceList->InterfaceType,
  495. fullResourceList->BusNumber,
  496. partialDescriptors[j].u.Interrupt.Level,
  497. partialDescriptors[j].u.Interrupt.Vector,
  498. (PKIRQL) &partialDescriptors[j].u.Interrupt.Level,
  499. &partialDescriptors[j].u.Interrupt.Affinity);
  500. }
  501. }
  502. fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + j);
  503. }
  504. //
  505. // start the FDO
  506. //
  507. status = ChannelStartChannel (fdoExtension,
  508. cmResourceList); // callee is keeping this if no error
  509. }
  510. if (!NT_SUCCESS (status)) {
  511. //
  512. // go through the remove sequence
  513. //
  514. if (fdoExtension) {
  515. ChannelRemoveChannel (fdoExtension);
  516. IoDetachDevice (fdoExtension->AttacheeDeviceObject);
  517. IoDeleteDevice (fdoExtension->DeviceObject);
  518. }
  519. DebugPrint ((0, "IdePort: Unable to start detected device\n"));
  520. ASSERT (FALSE);
  521. } else {
  522. IoInvalidateDeviceRelations (
  523. fdoExtension->AttacheePdo,
  524. BusRelations
  525. );
  526. }
  527. }
  528. }
  529. }
  530. GetOut:
  531. if (cmResourceList) {
  532. ExFreePool (cmResourceList);
  533. }
  534. if (detectionPort) {
  535. ExFreePool (detectionPort);
  536. }
  537. return status;
  538. } //IdePortDetectLegacyController
  539. NTSTATUS
  540. IdePortCreateDetectionList (
  541. IN PDRIVER_OBJECT DriverObject,
  542. OUT PDETECTION_PORT *DetectionPort,
  543. OUT PULONG NumPort
  544. )
  545. /*++
  546. Routine Description:
  547. create a list of popular legacy ports
  548. Arguments:
  549. DriverObject - this driver's driver object
  550. DetectionPort - pointer to port list
  551. NumPort - number of ports in the list
  552. Return Value:
  553. NT Status
  554. --*/
  555. {
  556. NTSTATUS status;
  557. CCHAR deviceBuffer[50];
  558. ANSI_STRING ansiString;
  559. UNICODE_STRING subKeyPath;
  560. HANDLE subServiceKey;
  561. PDETECTION_PORT detectionPort;
  562. ULONG numDevices;
  563. ULONG i;
  564. ULONG j;
  565. CUSTOM_DEVICE_PARAMETER customDeviceParameter;
  566. PCONFIGURATION_INFORMATION configurationInformation = IoGetConfigurationInformation();
  567. numDevices = 0;
  568. status = STATUS_SUCCESS;
  569. #ifdef DRIVER_PARAMETER_REGISTRY_SUPPORT
  570. //
  571. // look for non-standard legacy port setting in the registry
  572. // 9
  573. do {
  574. sprintf (deviceBuffer, "Parameters\\Device%d", numDevices);
  575. RtlInitAnsiString(&ansiString, deviceBuffer);
  576. status = RtlAnsiStringToUnicodeString(&subKeyPath, &ansiString, TRUE);
  577. if (NT_SUCCESS(status)) {
  578. subServiceKey = IdePortOpenServiceSubKey (
  579. DriverObject,
  580. &subKeyPath
  581. );
  582. RtlFreeUnicodeString (&subKeyPath);
  583. if (subServiceKey) {
  584. numDevices++;
  585. IdePortCloseServiceSubKey (
  586. subServiceKey
  587. );
  588. } else {
  589. status = STATUS_UNSUCCESSFUL;
  590. }
  591. }
  592. } while (NT_SUCCESS(status));
  593. #endif // DRIVER_PARAMETER_REGISTRY_SUPPORT
  594. //
  595. // always have at least 4 to return
  596. //
  597. detectionPort = ExAllocatePool (
  598. PagedPool,
  599. (numDevices + 4) * sizeof (DETECTION_PORT)
  600. );
  601. if (detectionPort) {
  602. for (i = j = 0; i < numDevices; i++) {
  603. #ifdef DRIVER_PARAMETER_REGISTRY_SUPPORT
  604. //
  605. // look for non-standard legacy port setting in the registry
  606. //
  607. sprintf (deviceBuffer, "Parameters\\Device%d", i);
  608. RtlInitAnsiString(&ansiString, deviceBuffer);
  609. status = RtlAnsiStringToUnicodeString(&subKeyPath, &ansiString, TRUE);
  610. if (NT_SUCCESS(status)) {
  611. subServiceKey = IdePortOpenServiceSubKey (
  612. DriverObject,
  613. &subKeyPath
  614. );
  615. RtlFreeUnicodeString (&subKeyPath);
  616. if (subServiceKey) {
  617. RtlZeroMemory (
  618. &customDeviceParameter,
  619. sizeof (CUSTOM_DEVICE_PARAMETER)
  620. );
  621. IdeParseDeviceParameters (
  622. subServiceKey,
  623. &customDeviceParameter
  624. );
  625. if (customDeviceParameter.CommandRegisterBase) {
  626. detectionPort[j].CommandRegisterBase =
  627. customDeviceParameter.CommandRegisterBase;
  628. detectionPort[j].ControlRegisterBase =
  629. customDeviceParameter.CommandRegisterBase + 0x206;
  630. detectionPort[j].IrqLevel =
  631. customDeviceParameter.IrqLevel;
  632. j++;
  633. }
  634. IdePortCloseServiceSubKey (
  635. subServiceKey
  636. );
  637. }
  638. }
  639. #endif // DRIVER_PARAMETER_REGISTRY_SUPPORT
  640. }
  641. //
  642. // populate the list with popular i/o ports
  643. //
  644. if ( !IsNEC_98 ) {
  645. if (configurationInformation->AtDiskPrimaryAddressClaimed == FALSE) {
  646. detectionPort[j].CommandRegisterBase = 0x1f0;
  647. detectionPort[j].ControlRegisterBase = 0x1f0 + 0x206;
  648. detectionPort[j].IrqLevel = 14;
  649. j++;
  650. }
  651. if (configurationInformation->AtDiskSecondaryAddressClaimed == FALSE) {
  652. detectionPort[j].CommandRegisterBase = 0x170;
  653. detectionPort[j].ControlRegisterBase = 0x170 + 0x206;
  654. detectionPort[j].IrqLevel = 15;
  655. j++;
  656. }
  657. detectionPort[j].CommandRegisterBase = 0x1e8;
  658. detectionPort[j].ControlRegisterBase = 0x1e8 + 0x206;
  659. detectionPort[j].IrqLevel = 11;
  660. // DEC Hi-Note hack
  661. // detectionPort[j].ControlRegisterBase = 0x1e8 + 0x1f - 0x2;
  662. // detectionPort[j].IrqLevel = 7;
  663. // DEC Hi-Note hack
  664. j++;
  665. detectionPort[j].CommandRegisterBase = 0x168;
  666. detectionPort[j].ControlRegisterBase = 0x168 + 0x206;
  667. detectionPort[j].IrqLevel = 10;
  668. j++;
  669. } else { // IsNEC_98
  670. if ((configurationInformation->AtDiskPrimaryAddressClaimed == FALSE) &&
  671. (configurationInformation->AtDiskSecondaryAddressClaimed == FALSE)) {
  672. detectionPort[j].CommandRegisterBase = 0x640;
  673. detectionPort[j].ControlRegisterBase = 0x640 + 0x10c; //0x74c
  674. detectionPort[j].IrqLevel = 9;
  675. j++;
  676. }
  677. }
  678. *NumPort = j;
  679. *DetectionPort = detectionPort;
  680. return STATUS_SUCCESS;
  681. } else {
  682. *NumPort = 0;
  683. *DetectionPort = NULL;
  684. return STATUS_INSUFFICIENT_RESOURCES;
  685. }
  686. } // IdePortCreateDetectionList
  687. NTSTATUS
  688. IdePortTranslateAddress (
  689. IN INTERFACE_TYPE InterfaceType,
  690. IN ULONG BusNumber,
  691. IN PHYSICAL_ADDRESS StartAddress,
  692. IN LONG Length,
  693. IN OUT PULONG AddressSpace,
  694. OUT PVOID *TranslatedAddress,
  695. OUT PPHYSICAL_ADDRESS TranslatedMemoryAddress
  696. )
  697. /*++
  698. Routine Description:
  699. translate i/o address
  700. Arguments:
  701. InterfaceType - bus interface
  702. BusNumber - bus number
  703. StartAddress - address to translate
  704. Length - number of byte to translate
  705. AddressSpace - address space for the given address
  706. Return Value:
  707. AddressSpace - address space for the translated address
  708. TranslatedAddress - translated address
  709. TranslatedMemoryAddress - tranlated memory address if translated to memory space
  710. NT Status
  711. --*/
  712. {
  713. PHYSICAL_ADDRESS translatedAddress;
  714. ASSERT (Length);
  715. ASSERT (AddressSpace);
  716. ASSERT (TranslatedAddress);
  717. *TranslatedAddress = NULL;
  718. TranslatedMemoryAddress->QuadPart = (ULONGLONG) NULL;
  719. if (HalTranslateBusAddress(InterfaceType,
  720. BusNumber,
  721. StartAddress,
  722. AddressSpace,
  723. &translatedAddress)) {
  724. if (*AddressSpace == IO_SPACE) {
  725. *TranslatedAddress = (PVOID) translatedAddress.u.LowPart;
  726. } else if (*AddressSpace == MEMORY_SPACE) {
  727. //
  728. // translated address is in memory space,
  729. // need to map it to I/O space.
  730. //
  731. *TranslatedMemoryAddress = translatedAddress;
  732. *TranslatedAddress = MmMapIoSpace(
  733. translatedAddress,
  734. Length,
  735. FALSE);
  736. }
  737. }
  738. if (*TranslatedAddress) {
  739. return STATUS_SUCCESS;
  740. } else {
  741. return STATUS_INVALID_PARAMETER;
  742. }
  743. } // IdePortTranslateAddress
  744. VOID
  745. IdePortFreeTranslatedAddress (
  746. IN PVOID TranslatedAddress,
  747. IN LONG Length,
  748. IN ULONG AddressSpace
  749. )
  750. /*++
  751. Routine Description:
  752. free resources created for a translated address
  753. Arguments:
  754. TranslatedAddress - translated address
  755. Length - number of byte to translated
  756. AddressSpace - address space for the translated address
  757. Return Value:
  758. None
  759. --*/
  760. {
  761. if (TranslatedAddress) {
  762. if (AddressSpace == MEMORY_SPACE) {
  763. MmUnmapIoSpace (
  764. TranslatedAddress,
  765. Length
  766. );
  767. }
  768. }
  769. return;
  770. } // IdePortFreeTranslatedAddress
  771. BOOLEAN
  772. IdePortDetectAlias (
  773. PIDE_REGISTERS_1 CmdRegBase
  774. )
  775. {
  776. PIDE_REGISTERS_1 cmdRegBaseAlias;
  777. PUCHAR cylinderHighAlias;
  778. PUCHAR cylinderLowAlias;
  779. //
  780. // alias port
  781. //
  782. cylinderHighAlias = (PUCHAR) ((ULONG_PTR) CmdRegBase->CylinderHigh | (1 << 15));
  783. cylinderLowAlias = (PUCHAR) ((ULONG_PTR) CmdRegBase->CylinderLow | (1 << 15));
  784. IdePortOutPortByte (CmdRegBase->CylinderHigh, SAMPLE_CYLINDER_HIGH_VALUE);
  785. IdePortOutPortByte (CmdRegBase->CylinderLow, SAMPLE_CYLINDER_LOW_VALUE);
  786. //
  787. // Check if indentifier can be read back via the alias port
  788. //
  789. if ((IdePortInPortByte (cylinderHighAlias) != SAMPLE_CYLINDER_HIGH_VALUE) ||
  790. (IdePortInPortByte (cylinderLowAlias) != SAMPLE_CYLINDER_LOW_VALUE)) {
  791. return FALSE;
  792. } else {
  793. return TRUE;
  794. }
  795. }
  796. #endif // NO_LEGACY_DRIVERS