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.

798 lines
26 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. detect.c
  5. Abstract:
  6. This module contains the code that controls the PCMCIA slots.
  7. Authors:
  8. Bob Rinne (BobRi) 3-Nov-1994
  9. Neil Sandlin (neilsa) June 1 1999
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Modified for plug'n'play support
  14. Ravisankar Pudipeddi (ravisp) 1 Dec 1996
  15. --*/
  16. #include "pch.h"
  17. NTSTATUS
  18. PcmciaDetectControllers(
  19. IN PDRIVER_OBJECT DriverObject,
  20. IN PUNICODE_STRING RegistryPath,
  21. IN PPCMCIA_DETECT_ROUTINE PcmciaDetectFn
  22. );
  23. NTSTATUS
  24. PcmciaReportDetectedDevice(
  25. IN PFDO_EXTENSION DeviceExtension
  26. );
  27. NTSTATUS
  28. PcmciaAllocateOpenMemoryWindow(
  29. IN PFDO_EXTENSION DeviceExtension,
  30. IN PPHYSICAL_ADDRESS PhysicalAddress,
  31. IN PULONG PhysicalAddressSize
  32. );
  33. #ifdef ALLOC_PRAGMA
  34. // #pragma alloc_text(INIT,PcmciaLegacyDetectionOk)
  35. #pragma alloc_text(INIT,PcmciaDetectPcmciaControllers)
  36. #pragma alloc_text(INIT,PcmciaDetectControllers)
  37. #pragma alloc_text(INIT,PcmciaReportDetectedDevice)
  38. #pragma alloc_text(INIT,PcmciaAllocateOpenMemoryWindow)
  39. #endif
  40. #if 0
  41. BOOLEAN
  42. PcmciaLegacyDetectionOk(
  43. VOID
  44. )
  45. /*++
  46. Routine Description
  47. Checks if legacy detection needs to be done for pcmcia controllers
  48. Arguments
  49. None
  50. Return Value
  51. TRUE - If legacy detection can be done
  52. FALSE - If legacy detection should NOT be attempted
  53. --*/
  54. {
  55. UNICODE_STRING unicodeKey, unicodeValue;
  56. OBJECT_ATTRIBUTES objectAttributes;
  57. HANDLE handle;
  58. UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+
  59. sizeof(ULONG)];
  60. PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
  61. ULONG length;
  62. NTSTATUS status;
  63. PAGED_CODE();
  64. RtlInitUnicodeString(&unicodeKey,
  65. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Pnp");
  66. RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES));
  67. InitializeObjectAttributes(&objectAttributes,
  68. &unicodeKey,
  69. OBJ_CASE_INSENSITIVE,
  70. NULL,
  71. NULL);
  72. if (!NT_SUCCESS(ZwOpenKey(&handle,
  73. KEY_QUERY_VALUE,
  74. &objectAttributes))) {
  75. //
  76. // Key doesn't exist
  77. //
  78. return TRUE;
  79. }
  80. RtlInitUnicodeString(&unicodeValue, L"DisableFirmwareMapper");
  81. status = ZwQueryValueKey(handle,
  82. &unicodeValue,
  83. KeyValuePartialInformation,
  84. value,
  85. sizeof(buffer),
  86. &length);
  87. ZwClose(handle);
  88. if (!NT_SUCCESS(status)) {
  89. //
  90. // Value doesn't exist
  91. //
  92. return TRUE;
  93. }
  94. if (value->Type == REG_DWORD) {
  95. //
  96. // If value is non-zero don't do legacy detection
  97. // otherwise it's ok
  98. //
  99. return ((ULONG) (*((PULONG)value->Data)) ? FALSE : TRUE);
  100. }
  101. return TRUE;
  102. }
  103. #endif
  104. NTSTATUS
  105. PcmciaDetectPcmciaControllers(
  106. IN PDRIVER_OBJECT DriverObject,
  107. IN PUNICODE_STRING RegistryPath
  108. )
  109. /*++
  110. Routine Description:
  111. Detects appropriate PCMCIA controllers both ISA & PCI based
  112. in the system.
  113. Arguments:
  114. DriverObject Just as passed in to DriverEntry
  115. RegistryPath
  116. Return Value:
  117. STATUS_SUCCESS if any PCMCIA controllers were found
  118. STATUS_NO_SUCH_DEVICE otherwise
  119. --*/
  120. {
  121. NTSTATUS pcicIsaStatus = STATUS_UNSUCCESSFUL, tcicStatus = STATUS_UNSUCCESSFUL;
  122. PAGED_CODE();
  123. //
  124. // We enumerate the PCI devices first to ensure that the ISA detect
  125. // doesn't probe those address ports which are already claimed by
  126. // detected PCI devices
  127. //
  128. pcicIsaStatus = PcmciaDetectControllers(DriverObject, RegistryPath, PcicIsaDetect);
  129. tcicStatus = PcmciaDetectControllers(DriverObject, RegistryPath, TcicDetect);
  130. //
  131. // Indicate success if we found any controllers
  132. //
  133. return ((NT_SUCCESS(pcicIsaStatus) ||
  134. NT_SUCCESS(tcicStatus) ) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
  135. }
  136. NTSTATUS
  137. PcmciaDetectControllers(
  138. IN PDRIVER_OBJECT DriverObject,
  139. IN PUNICODE_STRING RegistryPath,
  140. IN PPCMCIA_DETECT_ROUTINE PcmciaDetectFn
  141. )
  142. /*++
  143. Routine Description:
  144. Detects PCMCIA controllers in the system and reports them. This is called
  145. by PcmciaDetectPcmciaControllers. This reports bus specific controllers.
  146. Arguments:
  147. DriverObject, RegistryPath - See DriverEntry
  148. PcmciaDetectFn - Pointer to the function that actually probes the hardware
  149. to find PCMCIA controllers. So this routine can be called
  150. with an ISA detect function or a PCI detect function for eg.
  151. Return Value:
  152. STATUS_SUCCESS Found one or more PCMCIA controllers
  153. STATUS_NO_SUCH_DEVICE No controllers found.
  154. STATUS_INSUFFICIENT_RESOURCES Pool allocation failures etc.
  155. --*/
  156. {
  157. PFDO_EXTENSION deviceExtension = NULL;
  158. NTSTATUS status = STATUS_SUCCESS;
  159. NTSTATUS detectStatus;
  160. BOOLEAN controllerDetected = FALSE;
  161. PAGED_CODE();
  162. //
  163. // Allocate a dummy device extension which is used by the Pcic & Tcic detect modules
  164. // Have to do this since the original detection code required device extensions
  165. // Too painful to change this structure now.
  166. //
  167. deviceExtension = ExAllocatePool(NonPagedPool, sizeof(FDO_EXTENSION));
  168. if (deviceExtension == NULL) {
  169. DebugPrint((PCMCIA_DEBUG_FAIL, "Cannot allocate pool for FDO extension\n"));
  170. return STATUS_INSUFFICIENT_RESOURCES;
  171. }
  172. do {
  173. RtlZeroMemory(deviceExtension, sizeof(FDO_EXTENSION));
  174. deviceExtension->RegistryPath = RegistryPath;
  175. deviceExtension->DriverObject = DriverObject;
  176. detectStatus = (*PcmciaDetectFn)(deviceExtension);
  177. if (detectStatus != STATUS_SUCCESS) {
  178. continue;
  179. }
  180. controllerDetected = TRUE;
  181. status = PcmciaReportDetectedDevice(deviceExtension);
  182. if (!NT_SUCCESS(status)) {
  183. DebugPrint((PCMCIA_DEBUG_FAIL, "PcmciaDetectControllers: PcmciaReportDetectedDevice "
  184. "failed, status %x\n", status));
  185. continue;
  186. }
  187. } while (detectStatus != STATUS_NO_MORE_ENTRIES);
  188. ExFreePool(deviceExtension);
  189. if (controllerDetected) {
  190. return STATUS_SUCCESS;
  191. }
  192. return (STATUS_NO_SUCH_DEVICE);
  193. }
  194. NTSTATUS
  195. PcmciaReportDetectedDevice(
  196. IN PFDO_EXTENSION DeviceExtension
  197. )
  198. /*++
  199. Routine Description:
  200. Reports the PCMCIA controllers detected to the IO subsystem which creates the
  201. madeup devnodes for these DeviceObjects.
  202. Arguments:
  203. DeviceExtension - DeviceExtension for the DeviceObject (FDO) of the PCMCIA controller
  204. being reported
  205. Return Value:
  206. --*/
  207. {
  208. PDEVICE_OBJECT pdo = NULL, fdo, lowerDevice;
  209. PFDO_EXTENSION fdoExtension;
  210. ULONG pcmciaInterruptVector;
  211. KIRQL pcmciaInterruptLevel;
  212. KAFFINITY pcmciaAffinity;
  213. PSOCKET socket;
  214. NTSTATUS status;
  215. ULONG pcmciaIrq;
  216. ULONG count, ioResourceReqSize;
  217. PHYSICAL_ADDRESS halMemoryAddress;
  218. ULONG addressSpace;
  219. PIO_RESOURCE_REQUIREMENTS_LIST ioResourceReq=NULL;
  220. PIO_RESOURCE_LIST ioResourceList;
  221. PIO_RESOURCE_DESCRIPTOR ioResourceDesc;
  222. PCM_RESOURCE_LIST allocatedResources;
  223. PCM_RESOURCE_LIST scratchResources;
  224. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDesc;
  225. BOOLEAN translated;
  226. UCHAR option;
  227. PAGED_CODE();
  228. //
  229. // Do initial setup in our "fake" device extension
  230. //
  231. PcmciaGetControllerRegistrySettings(DeviceExtension);
  232. DeviceExtension->Configuration.InterruptPin = 0;
  233. DeviceExtension->Configuration.Interrupt.u.Interrupt.Vector = 0;
  234. DeviceExtension->Configuration.Interrupt.u.Interrupt.Level = 0;
  235. count=0;
  236. //
  237. // Get an 'open' memory window
  238. //
  239. status = PcmciaAllocateOpenMemoryWindow(DeviceExtension,
  240. &DeviceExtension->PhysicalBase,
  241. &DeviceExtension->AttributeMemorySize);
  242. count++;
  243. if (DeviceExtension->Configuration.UntranslatedPortAddress) {
  244. count++;
  245. }
  246. ioResourceReqSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + (count-1)*sizeof(IO_RESOURCE_DESCRIPTOR);
  247. ioResourceReq = ExAllocatePool(PagedPool, ioResourceReqSize);
  248. if (ioResourceReq == NULL) {
  249. return STATUS_INSUFFICIENT_RESOURCES;
  250. }
  251. RtlZeroMemory(ioResourceReq, ioResourceReqSize);
  252. ioResourceReq->ListSize = ioResourceReqSize;
  253. ioResourceReq->InterfaceType = Isa; // DeviceExtension->Configuration.InterfaceType;
  254. ioResourceReq->BusNumber = DeviceExtension->Configuration.BusNumber;
  255. ioResourceReq->SlotNumber= DeviceExtension->Configuration.SlotNumber;
  256. ioResourceReq->AlternativeLists=1;
  257. ioResourceList = &(ioResourceReq->List[0]);
  258. ioResourceList->Version = IO_RESOURCE_LIST_VERSION;
  259. ioResourceList->Revision = IO_RESOURCE_LIST_REVISION;
  260. ioResourceList->Count = count;
  261. ioResourceDesc = ioResourceList->Descriptors;
  262. //
  263. //Request IO
  264. //
  265. if (DeviceExtension->Configuration.UntranslatedPortAddress) {
  266. ioResourceDesc->Option = 0;
  267. ioResourceDesc->Type = CmResourceTypePort;
  268. ioResourceDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  269. ioResourceDesc->Flags = CM_RESOURCE_PORT_IO;
  270. ioResourceDesc->u.Port.MinimumAddress.LowPart = (ULONG)(DeviceExtension->Configuration.UntranslatedPortAddress);
  271. ioResourceDesc->u.Port.MaximumAddress.LowPart = (ULONG)(DeviceExtension->Configuration.UntranslatedPortAddress+
  272. DeviceExtension->Configuration.PortSize - 1);
  273. ioResourceDesc->u.Port.Length = DeviceExtension->Configuration.PortSize;
  274. ioResourceDesc->u.Port.Alignment = 1;
  275. ioResourceDesc++;
  276. }
  277. //
  278. // Request memory
  279. //
  280. ioResourceDesc->Option = 0;
  281. ioResourceDesc->Type = CmResourceTypeMemory;
  282. ioResourceDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  283. ioResourceDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  284. if (DeviceExtension->PhysicalBase.QuadPart) {
  285. ioResourceDesc->u.Memory.MinimumAddress = DeviceExtension->PhysicalBase;
  286. ioResourceDesc->u.Memory.MaximumAddress.QuadPart = DeviceExtension->PhysicalBase.QuadPart+DeviceExtension->AttributeMemorySize-1;
  287. ioResourceDesc->u.Memory.Length = DeviceExtension->AttributeMemorySize;
  288. ioResourceDesc->u.Memory.Alignment = 1;
  289. ioResourceDesc++;
  290. } else {
  291. //
  292. ioResourceDesc->u.Memory.MinimumAddress.LowPart = DeviceExtension->AttributeMemoryLow;
  293. ioResourceDesc->u.Memory.MaximumAddress.LowPart = DeviceExtension->AttributeMemoryHigh;
  294. ioResourceDesc->u.Memory.Length = DeviceExtension->AttributeMemorySize;
  295. switch (DeviceExtension->ControllerType) {
  296. case PcmciaDatabook: {
  297. ioResourceDesc->u.Memory.Alignment = TCIC_WINDOW_ALIGNMENT;
  298. break;
  299. }
  300. default: {
  301. ioResourceDesc->u.Memory.Alignment = PCIC_WINDOW_ALIGNMENT;
  302. break;
  303. }
  304. }
  305. ioResourceDesc++;
  306. }
  307. status = IoAssignResources(DeviceExtension->RegistryPath,
  308. NULL,
  309. DeviceExtension->DriverObject,
  310. NULL,
  311. ioResourceReq,
  312. &allocatedResources
  313. );
  314. if (!NT_SUCCESS(status)) {
  315. //
  316. // Log an event here
  317. //
  318. PcmciaLogError(DeviceExtension, PCMCIA_NO_RESOURCES, 1, 0);
  319. DebugPrint((PCMCIA_DEBUG_FAIL, "PcmciaReportDetectedDevice: IoAssignResources failed status %x\n",
  320. status));
  321. ExFreePool(ioResourceReq);
  322. return status;
  323. }
  324. //
  325. // Fish out the Memory Base allocated to this controller from the
  326. // nether depths of the CM_RESOURCE_LIST
  327. //
  328. count = allocatedResources->List[0].PartialResourceList.Count;
  329. cmResourceDesc = &(allocatedResources->List[0].PartialResourceList.PartialDescriptors[0]);
  330. while (count--) {
  331. switch (cmResourceDesc->Type) {
  332. case CmResourceTypeMemory: {
  333. DeviceExtension->PhysicalBase = cmResourceDesc->u.Memory.Start;
  334. DeviceExtension->AttributeMemorySize = cmResourceDesc->u.Memory.Length;
  335. addressSpace=0;
  336. translated = HalTranslateBusAddress(Isa,
  337. 0,
  338. cmResourceDesc->u.Memory.Start,
  339. &addressSpace,
  340. &halMemoryAddress);
  341. ASSERT(translated);
  342. if (addressSpace) {
  343. DeviceExtension->AttributeMemoryBase = (PUCHAR)(halMemoryAddress.QuadPart);
  344. DeviceExtension->Flags &= ~PCMCIA_ATTRIBUTE_MEMORY_MAPPED;
  345. }
  346. else {
  347. DeviceExtension->AttributeMemoryBase = MmMapIoSpace(halMemoryAddress,
  348. cmResourceDesc->u.Memory.Length,
  349. FALSE);
  350. DeviceExtension->Flags |= PCMCIA_ATTRIBUTE_MEMORY_MAPPED;
  351. }
  352. DebugPrint((PCMCIA_DEBUG_INFO,
  353. "Attribute Memory Physical Base: %x Virtual Addr: %x\n",
  354. DeviceExtension->PhysicalBase,
  355. DeviceExtension->AttributeMemoryBase));
  356. break;
  357. }
  358. // Don't bother to parse IO, it was a fixed resource requirement which we already know about
  359. }
  360. cmResourceDesc++;
  361. }
  362. //
  363. // Free resources so IoReportDetectedDevice can assign them for the PDO
  364. //
  365. IoAssignResources(DeviceExtension->RegistryPath,
  366. NULL,
  367. DeviceExtension->DriverObject,
  368. NULL,
  369. NULL,
  370. &scratchResources
  371. );
  372. pdo = NULL;
  373. status = IoReportDetectedDevice(
  374. DeviceExtension->DriverObject,
  375. InterfaceTypeUndefined,
  376. -1,
  377. -1,
  378. allocatedResources,
  379. ioResourceReq,
  380. FALSE,
  381. &pdo
  382. );
  383. ExFreePool(allocatedResources);
  384. ExFreePool(ioResourceReq);
  385. if (!NT_SUCCESS(status)) {
  386. DebugPrint((PCMCIA_DEBUG_FAIL, "PcmciaReportDetectedDevice: IoReportDetectedDevice failed\n"));
  387. return status;
  388. }
  389. //
  390. // Set up registry params for the madeup pdo so we'll recognize it on the next boot
  391. // when the PNP manager gives us an AddDevice/IRP_MN_START_DEVICE
  392. //
  393. PcmciaSetLegacyDetectedControllerType(pdo, DeviceExtension->ControllerType);
  394. //
  395. // The I/O subsystem has created the true PDO which we will use during this boot. So we
  396. // have to attach to this PDO, and initialize our new FDO extension to values already set
  397. // into our original (fake) FDO extension.
  398. //
  399. status = PcmciaAddDevice(DeviceExtension->DriverObject, pdo);
  400. if (!NT_SUCCESS(status)) {
  401. DebugPrint((PCMCIA_DEBUG_FAIL, "PcmciaReportDetectedDevice: AddDevice failed status %x\n", status));
  402. return status;
  403. }
  404. pdo->Flags &= ~DO_DEVICE_INITIALIZING;
  405. //
  406. // Head of list is our fdo
  407. //
  408. fdo = FdoList;
  409. fdoExtension = fdo->DeviceExtension;
  410. //
  411. // Copy in the rest of the config. from the DeviceExtension
  412. //
  413. fdoExtension->SocketList = DeviceExtension->SocketList;
  414. fdoExtension->Configuration = DeviceExtension->Configuration;
  415. fdoExtension->PhysicalBase = DeviceExtension->PhysicalBase;
  416. fdoExtension->AttributeMemoryBase = DeviceExtension->AttributeMemoryBase;
  417. fdoExtension->AttributeMemorySize = DeviceExtension->AttributeMemorySize;
  418. fdoExtension->Flags = DeviceExtension->Flags;
  419. // Reinitialize the socket's device extensions
  420. //
  421. for (socket = fdoExtension->SocketList; socket!=NULL; socket=socket->NextSocket) {
  422. socket->DeviceExtension = fdoExtension;
  423. }
  424. fdoExtension->Flags |= PCMCIA_DEVICE_STARTED;
  425. //
  426. // This is legacy detected..
  427. //
  428. fdoExtension->Flags |= PCMCIA_DEVICE_LEGACY_DETECTED;
  429. status=PcmciaStartPcmciaController(fdo);
  430. if (!NT_SUCCESS(status)) {
  431. fdoExtension->Flags &= ~PCMCIA_DEVICE_STARTED;
  432. }
  433. return status;
  434. }
  435. NTSTATUS
  436. PcmciaAllocateOpenMemoryWindow(
  437. IN PFDO_EXTENSION DeviceExtension,
  438. IN PPHYSICAL_ADDRESS PhysicalAddress,
  439. IN PULONG PhysicalAddressSize
  440. )
  441. /*++
  442. Routine Description:
  443. Search the 640K to 1MB region for an open area to be used
  444. for mapping PCCARD attribute memory.
  445. Arguments:
  446. Return Value:
  447. A physical address for the window to the card or zero meaning
  448. there is no opening.
  449. --*/
  450. {
  451. #define NUMBER_OF_TEST_BYTES 25
  452. PHYSICAL_ADDRESS physicalMemoryAddress;
  453. PHYSICAL_ADDRESS halMemoryAddress;
  454. BOOLEAN translated;
  455. ULONG untranslatedAddress;
  456. PUCHAR memoryAddress;
  457. PUCHAR bogus;
  458. ULONG addressSpace;
  459. ULONG index;
  460. UCHAR memory[NUMBER_OF_TEST_BYTES];
  461. PCM_RESOURCE_LIST cmResourceList = NULL;
  462. PCM_PARTIAL_RESOURCE_LIST cmPartialResourceList;
  463. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmResourceDesc;
  464. BOOLEAN conflict = TRUE;
  465. NTSTATUS status;
  466. ULONG windowSize, windowAlignment;
  467. PAGED_CODE();
  468. cmResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
  469. if (!cmResourceList) {
  470. return STATUS_INSUFFICIENT_RESOURCES;
  471. }
  472. RtlZeroMemory(cmResourceList, sizeof(CM_RESOURCE_LIST));
  473. cmResourceList->Count = 1;
  474. cmResourceList->List[0].InterfaceType = Isa;
  475. cmPartialResourceList = &(cmResourceList->List[0].PartialResourceList);
  476. cmPartialResourceList->Version = 1;
  477. cmPartialResourceList->Revision = 1;
  478. cmPartialResourceList->Count = 1;
  479. cmResourceDesc = cmPartialResourceList->PartialDescriptors;
  480. cmResourceDesc->Type = CmResourceTypeMemory;
  481. cmResourceDesc->ShareDisposition = CmResourceShareDeviceExclusive;
  482. cmResourceDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
  483. //
  484. // Size of the attr. memory window
  485. //
  486. switch (DeviceExtension->ControllerType) {
  487. case PcmciaDatabook: {
  488. windowSize = TCIC_WINDOW_SIZE;
  489. windowAlignment = TCIC_WINDOW_ALIGNMENT;
  490. break;
  491. }
  492. default: {
  493. windowSize = PCIC_WINDOW_SIZE;
  494. windowAlignment = PCIC_WINDOW_ALIGNMENT;
  495. break;
  496. }
  497. }
  498. for (untranslatedAddress = DeviceExtension->AttributeMemoryLow;
  499. untranslatedAddress < DeviceExtension->AttributeMemoryHigh;
  500. untranslatedAddress += windowAlignment) {
  501. if (untranslatedAddress == 0xc0000) {
  502. //
  503. // This is VGA. Keep this test if the for loop should
  504. // ever change.
  505. //
  506. continue;
  507. }
  508. //
  509. // Check if it's available
  510. //
  511. cmResourceDesc->u.Memory.Start.LowPart = untranslatedAddress;
  512. cmResourceDesc->u.Memory.Length = windowSize;
  513. status=IoReportResourceForDetection(
  514. DeviceExtension->DriverObject,
  515. cmResourceList,
  516. sizeof(CM_RESOURCE_LIST),
  517. NULL,
  518. NULL,
  519. 0,
  520. &conflict);
  521. if (!NT_SUCCESS(status) || conflict) {
  522. //
  523. // This range's already taken. Move on to the next
  524. //
  525. continue;
  526. }
  527. addressSpace = 0;
  528. physicalMemoryAddress.LowPart = untranslatedAddress;
  529. physicalMemoryAddress.HighPart = 0;
  530. translated = HalTranslateBusAddress(Isa,
  531. 0,
  532. physicalMemoryAddress,
  533. &addressSpace,
  534. &halMemoryAddress);
  535. if (!translated) {
  536. //
  537. // HAL doesn't like this translation
  538. //
  539. continue;
  540. }
  541. if (addressSpace) {
  542. memoryAddress = (PUCHAR)(halMemoryAddress.QuadPart);
  543. } else {
  544. memoryAddress = MmMapIoSpace(halMemoryAddress, windowSize, FALSE);
  545. }
  546. //
  547. // Test the memory window to determine if it is a BIOS, video
  548. // memory, or open memory. Only want to keep the window if it
  549. // is not being used by something else.
  550. //
  551. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  552. memory[index] = READ_REGISTER_UCHAR(memoryAddress + index);
  553. if (index) {
  554. if (memory[index] != memory[index - 1]) {
  555. break;
  556. }
  557. }
  558. }
  559. if (index == NUMBER_OF_TEST_BYTES) {
  560. //
  561. // There isn't a BIOS here
  562. //
  563. UCHAR memoryPattern[NUMBER_OF_TEST_BYTES];
  564. BOOLEAN changed = FALSE;
  565. //
  566. // Check for video memory - open memory should always remain
  567. // the same regardless what the changes are. Change the
  568. // pattern previously found.
  569. //
  570. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  571. memoryPattern[index] = ~memory[index];
  572. WRITE_REGISTER_UCHAR(memoryAddress + index,
  573. memoryPattern[index]);
  574. }
  575. //
  576. // See if the pattern in memory changed.
  577. // Some system exhibit a problem where the memory pattern
  578. // seems to be cached. If this code is debugged it will
  579. // work as expected, but if it is run normally it will
  580. // always return that the memory changed. This random
  581. // wandering seems to remove this problem.
  582. //
  583. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  584. memoryPattern[index] = 0;
  585. }
  586. bogus = ExAllocatePool(PagedPool, 64 * 1024);
  587. if (bogus) {
  588. for (index = 0; index < 64 * 1024; index++) {
  589. bogus[index] = 0;
  590. }
  591. ExFreePool(bogus);
  592. }
  593. //
  594. // Now go off and do the actual check to see if the memory
  595. // changed.
  596. //
  597. for (index = 0; index < NUMBER_OF_TEST_BYTES; index++) {
  598. if ((memoryPattern[index] = READ_REGISTER_UCHAR(memoryAddress + index)) != memory[index]) {
  599. //
  600. // It changed - this is not an area of open memory
  601. //
  602. changed = TRUE;
  603. }
  604. WRITE_REGISTER_UCHAR(memoryAddress + index,
  605. memory[index]);
  606. }
  607. if (!changed) {
  608. //
  609. // Area isn't a BIOS and didn't change when written.
  610. // Use this region for the memory window to PCMCIA
  611. // attribute memory.
  612. //
  613. PhysicalAddress->LowPart = untranslatedAddress;
  614. PhysicalAddress->HighPart = 0;
  615. *PhysicalAddressSize = windowSize;
  616. if (!addressSpace) {
  617. MmUnmapIoSpace(memoryAddress, windowSize);
  618. }
  619. ExFreePool(cmResourceList);
  620. return STATUS_SUCCESS;
  621. }
  622. }
  623. if (!addressSpace) {
  624. MmUnmapIoSpace(memoryAddress, windowSize);
  625. }
  626. }
  627. ExFreePool(cmResourceList);
  628. return STATUS_UNSUCCESSFUL;
  629. }