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.

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