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.

731 lines
18 KiB

  1. /*++
  2. Copyright (c) 1992-1998 Microsoft Corporation
  3. Module Name:
  4. videosim.c
  5. Abstract:
  6. Minport to simulate a frame buffer miniport driver.
  7. video driver.
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #define _NTDRIVER_
  13. #ifndef FAR
  14. #define FAR
  15. #endif
  16. #include "dderror.h"
  17. #include "ntosp.h"
  18. #include "stdarg.h"
  19. #include "stdio.h"
  20. #include "zwapi.h"
  21. #include "ntddvdeo.h"
  22. #include "video.h"
  23. #include "videosim.h"
  24. //
  25. // Function Prototypes
  26. //
  27. // Functions that start with 'Sim' are entry points for the OS port driver.
  28. //
  29. ULONG
  30. DriverEntry(
  31. PVOID Context1,
  32. PVOID Context2
  33. );
  34. VP_STATUS
  35. SimFindAdapter(
  36. PVOID HwDeviceExtension,
  37. PVOID HwContext,
  38. PWSTR ArgumentString,
  39. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  40. PUCHAR Again
  41. );
  42. BOOLEAN
  43. SimInitialize(
  44. PVOID HwDeviceExtension
  45. );
  46. BOOLEAN
  47. SimStartIO(
  48. PVOID HwDeviceExtension,
  49. PVIDEO_REQUEST_PACKET RequestPacket
  50. );
  51. #if defined(ALLOC_PRAGMA)
  52. #pragma alloc_text(PAGE,DriverEntry)
  53. #pragma alloc_text(PAGE,SimFindAdapter)
  54. #pragma alloc_text(PAGE,SimInitialize)
  55. #pragma alloc_text(PAGE,SimStartIO)
  56. #endif
  57. ULONG
  58. DriverEntry (
  59. PVOID Context1,
  60. PVOID Context2
  61. )
  62. /*++
  63. Routine Description:
  64. Installable driver initialization entry point.
  65. This entry point is called directly by the I/O system.
  66. Arguments:
  67. Context1 - First context value passed by the operating system. This is
  68. the value with which the miniport driver calls VideoPortInitialize().
  69. Context2 - Second context value passed by the operating system. This is
  70. the value with which the miniport driver calls VideoPortInitialize().
  71. Return Value:
  72. Status from VideoPortInitialize()
  73. --*/
  74. {
  75. VIDEO_HW_INITIALIZATION_DATA hwInitData;
  76. ULONG status;
  77. ULONG initializationStatus;
  78. //
  79. // Zero out structure.
  80. //
  81. VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
  82. //
  83. // Specify sizes of structure and extension.
  84. //
  85. hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
  86. //
  87. // Set entry points.
  88. //
  89. hwInitData.HwFindAdapter = SimFindAdapter;
  90. hwInitData.HwInitialize = SimInitialize;
  91. hwInitData.HwInterrupt = NULL;
  92. hwInitData.HwStartIO = SimStartIO;
  93. //
  94. // Determine the size we require for the device extension.
  95. //
  96. hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
  97. //
  98. // Always start with parameters for device0 in this case.
  99. //
  100. // hwInitData.StartingDeviceNumber = 0;
  101. //
  102. // Once all the relevant information has been stored, call the video
  103. // port driver to do the initialization.
  104. // For this device we will repeat this call three times, for ISA, EISA
  105. // and MCA.
  106. // We will return the minimum of all return values.
  107. //
  108. hwInitData.AdapterInterfaceType = PCIBus;
  109. return (VideoPortInitialize(Context1,
  110. Context2,
  111. &hwInitData,
  112. NULL));
  113. } // end DriverEntry()
  114. VP_STATUS
  115. SimFindAdapter(
  116. PVOID HwDeviceExtension,
  117. PVOID HwContext,
  118. PWSTR ArgumentString,
  119. PVIDEO_PORT_CONFIG_INFO ConfigInfo,
  120. PUCHAR Again
  121. )
  122. /*++
  123. Routine Description:
  124. This routine is called to determine if the adapter for this driver
  125. is present in the system.
  126. If it is present, the function fills out some information describing
  127. the adapter.
  128. Arguments:
  129. HwDeviceExtension - Supplies the miniport driver's adapter storage. This
  130. storage is initialized to zero before this call.
  131. HwContext - Supplies the context value which was passed to
  132. VideoPortInitialize().
  133. ArgumentString - Suuplies a NULL terminated ASCII string. This string
  134. originates from the user.
  135. ConfigInfo - Returns the configuration information structure which is
  136. filled by the miniport driver. This structure is initialized with
  137. any knwon configuration information (such as SystemIoBusNumber) by
  138. the port driver. Where possible, drivers should have one set of
  139. defaults which do not require any supplied configuration information.
  140. Again - Indicates if the miniport driver wants the port driver to call
  141. its VIDEO_HW_FIND_ADAPTER function again with a new device extension
  142. and the same config info. This is used by the miniport drivers which
  143. can search for several adapters on a bus.
  144. Return Value:
  145. This routine must return:
  146. NO_ERROR - Indicates a host adapter was found and the
  147. configuration information was successfully determined.
  148. ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
  149. error obtaining the configuration information. If possible an error
  150. should be logged.
  151. ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
  152. supplied configuration information.
  153. --*/
  154. {
  155. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  156. NTSTATUS Status;
  157. HANDLE SectionHandle;
  158. ACCESS_MASK SectionAccess;
  159. ULONGLONG SectionSize = 0x100000;
  160. //
  161. // Make sure the size of the structure is at least as large as what we
  162. // are expecting (check version of the config info structure).
  163. //
  164. if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
  165. return ERROR_INVALID_PARAMETER;
  166. }
  167. //
  168. // Only create a device once.
  169. //
  170. if (bLoaded++)
  171. {
  172. return ERROR_DEV_NOT_EXIST;
  173. }
  174. #if 0
  175. //
  176. // Create the frame buffer
  177. //
  178. SectionAccess = SECTION_ALL_ACCESS;
  179. Status = ZwCreateSection(&SectionHandle,
  180. SectionAccess,
  181. (POBJECT_ATTRIBUTES) NULL,
  182. (PLARGE_INTEGER) &SectionSize,
  183. PAGE_READWRITE,
  184. SEC_COMMIT,
  185. NULL);
  186. if (!NT_SUCCESS(Status))
  187. {
  188. return ERROR_DEV_NOT_EXIST;
  189. }
  190. //
  191. // Now reference the section handle.
  192. //
  193. Status = ObReferenceObjectByHandle(SectionHandle,
  194. SECTION_ALL_ACCESS,
  195. NULL,
  196. KernelMode,
  197. &(hwDeviceExtension->SectionPointer),
  198. (POBJECT_HANDLE_INFORMATION) NULL );
  199. ZwClose(SectionHandle);
  200. if (!NT_SUCCESS(Status))
  201. {
  202. return ERROR_DEV_NOT_EXIST;
  203. }
  204. #endif
  205. //
  206. // Clear out the Emulator entries and the state size since this driver
  207. // does not support them.
  208. //
  209. ConfigInfo->NumEmulatorAccessEntries = 0;
  210. ConfigInfo->EmulatorAccessEntries = NULL;
  211. ConfigInfo->EmulatorAccessEntriesContext = 0;
  212. ConfigInfo->HardwareStateSize = 0;
  213. ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000;
  214. ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
  215. ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000;
  216. //
  217. // Initialize the current mode number.
  218. //
  219. hwDeviceExtension->CurrentModeNumber = 0;
  220. //
  221. // Indicate we do not wish to be called over
  222. //
  223. *Again = 0;
  224. //
  225. // Indicate a successful completion status.
  226. //
  227. return NO_ERROR;
  228. } // end SimFindAdapter()
  229. BOOLEAN
  230. SimInitialize(
  231. PVOID HwDeviceExtension
  232. )
  233. /*++
  234. Routine Description:
  235. This routine does one time initialization of the device.
  236. Arguments:
  237. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  238. Return Value:
  239. Always returns TRUE since this routine can never fail.
  240. --*/
  241. {
  242. ULONG i;
  243. //
  244. // Walk through the list of modes and mark the indexes properly
  245. //
  246. for (i = 0; i < SimNumModes; i++) {
  247. SimModes[i].ModeIndex = i;
  248. }
  249. return TRUE;
  250. } // end SimInitialize()
  251. BOOLEAN
  252. SimStartIO(
  253. PVOID HwDeviceExtension,
  254. PVIDEO_REQUEST_PACKET RequestPacket
  255. )
  256. /*++
  257. Routine Description:
  258. This routine is the main execution routine for the miniport driver. It
  259. acceptss a Video Request Packet, performs the request, and then returns
  260. with the appropriate status.
  261. Arguments:
  262. HwDeviceExtension - Supplies a pointer to the miniport's device extension.
  263. RequestPacket - Pointer to the video request packet. This structure
  264. contains all the parameters passed to the VideoIoControl function.
  265. Return Value:
  266. --*/
  267. {
  268. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  269. VP_STATUS status;
  270. PVIDEO_MODE_INFORMATION modeInformation;
  271. PVIDEO_MEMORY_INFORMATION memoryInformation;
  272. PVIDEO_SHARE_MEMORY pShareMemory;
  273. PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
  274. ULONG ulTemp;
  275. NTSTATUS ntStatus;
  276. ULONG ViewSize;
  277. PVOID ViewBase;
  278. LARGE_INTEGER ViewOffset;
  279. HANDLE sectionHandle;
  280. //
  281. // Switch on the IoContolCode in the RequestPacket. It indicates which
  282. // function must be performed by the driver.
  283. //
  284. switch (RequestPacket->IoControlCode) {
  285. case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
  286. VideoDebugPrint((2, "SimStartIO - MapVideoMemory\n"));
  287. if ( (RequestPacket->OutputBufferLength <
  288. sizeof(VIDEO_MEMORY_INFORMATION)) ||
  289. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
  290. RequestPacket->StatusBlock->Information = 0;
  291. status = ERROR_INSUFFICIENT_BUFFER;
  292. break;
  293. }
  294. if (hwDeviceExtension->VideoRamBase == 0)
  295. {
  296. //
  297. // Allocate this once, and hang on to forever after, reusing it
  298. // through successive launches of NetMeeting.
  299. //
  300. hwDeviceExtension->VideoRamBase = ExAllocatePoolWithTag(
  301. NonPagedPool, ONE_MEG, 'ddmN');
  302. }
  303. if (hwDeviceExtension->VideoRamBase == 0)
  304. {
  305. status = ERROR_INVALID_PARAMETER;
  306. break;
  307. }
  308. RequestPacket->StatusBlock->Information =
  309. sizeof(VIDEO_MEMORY_INFORMATION);
  310. memoryInformation = RequestPacket->OutputBuffer;
  311. #if 0
  312. status = ERROR_INVALID_PARAMETER;
  313. ViewSize = 0x100000;
  314. ViewBase = NULL;
  315. ViewOffset.QuadPart = 0;
  316. if (NT_SUCCESS(ObOpenObjectByPointer(hwDeviceExtension->SectionPointer,
  317. 0L,
  318. (PACCESS_STATE) NULL,
  319. SECTION_ALL_ACCESS,
  320. (POBJECT_TYPE) NULL,
  321. KernelMode,
  322. &sectionHandle)))
  323. {
  324. if (NT_SUCCESS(ZwMapViewOfSection(sectionHandle,
  325. NtCurrentProcess(),
  326. &ViewBase,
  327. 0,
  328. ViewSize,
  329. &ViewOffset,
  330. &ViewSize,
  331. ViewUnmap,
  332. 0,
  333. PAGE_READWRITE)))
  334. {
  335. }
  336. ZwClose(sectionHandle);
  337. }
  338. #endif
  339. memoryInformation->VideoRamBase =
  340. memoryInformation->FrameBufferBase = hwDeviceExtension->VideoRamBase;
  341. memoryInformation->VideoRamLength =
  342. memoryInformation->FrameBufferLength = ONE_MEG;
  343. VideoDebugPrint((1, "VideoSim: RamBase = %08lx, RamLength = %08lx\n",
  344. hwDeviceExtension->VideoRamBase,
  345. hwDeviceExtension->VideoRamLength));
  346. status = NO_ERROR;
  347. break;
  348. case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
  349. VideoDebugPrint((1, "SimStartIO - UnMapVideoMemory\n"));
  350. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
  351. status = ERROR_INSUFFICIENT_BUFFER;
  352. }
  353. //
  354. // We have a problem if the MDL is still around when this memory is
  355. // freed. On the next MAP call, we'll allocate a new block of
  356. // memory. But when SHARE is called, to get a user mode pointer
  357. // referring to it, that will use the old MDL, referring to the OLD
  358. // VideoRamBase block.
  359. //
  360. // ASSERT(!hwDeviceExtension->Mdl);
  361. if (hwDeviceExtension->VideoRamBase)
  362. {
  363. ExFreePool(hwDeviceExtension->VideoRamBase);
  364. hwDeviceExtension->VideoRamBase = 0;
  365. }
  366. status = NO_ERROR;
  367. break;
  368. case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
  369. VideoDebugPrint((1, "SimStartIO - ShareVideoMemory\n"));
  370. if ( (RequestPacket->OutputBufferLength <
  371. sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
  372. (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
  373. {
  374. VideoDebugPrint((1,
  375. "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INSUFFICIENT_BUFFER\n"));
  376. status = ERROR_INSUFFICIENT_BUFFER;
  377. break;
  378. }
  379. pShareMemory = RequestPacket->InputBuffer;
  380. RequestPacket->StatusBlock->Information =
  381. sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
  382. //
  383. // Beware: the input buffer and the output buffer are the same
  384. // buffer, and therefore data should not be copied from one to the
  385. // other
  386. //
  387. status = ERROR_INVALID_PARAMETER;
  388. if (hwDeviceExtension->Mdl == NULL)
  389. {
  390. hwDeviceExtension->Mdl = MmCreateMdl(0,
  391. hwDeviceExtension->VideoRamBase,
  392. ONE_MEG);
  393. if (hwDeviceExtension->Mdl)
  394. {
  395. MmBuildMdlForNonPagedPool(hwDeviceExtension->Mdl);
  396. }
  397. }
  398. if (hwDeviceExtension->Mdl)
  399. {
  400. pShareMemoryInformation = RequestPacket->OutputBuffer;
  401. pShareMemoryInformation->VirtualAddress =
  402. MmMapLockedPagesSpecifyCache(hwDeviceExtension->Mdl,
  403. UserMode,
  404. MmCached,
  405. NULL,
  406. FALSE,
  407. NormalPagePriority);
  408. pShareMemoryInformation->SharedViewOffset = 0;
  409. pShareMemoryInformation->SharedViewSize = ONE_MEG;
  410. status = NO_ERROR;
  411. }
  412. break;
  413. case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
  414. VideoDebugPrint((2, "SimStartIO - UnshareVideoMemory\n"));
  415. if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
  416. {
  417. status = ERROR_INSUFFICIENT_BUFFER;
  418. break;
  419. }
  420. pShareMemory = RequestPacket->InputBuffer;
  421. MmUnmapLockedPages(pShareMemory->RequestedVirtualAddress,
  422. hwDeviceExtension->Mdl);
  423. status = NO_ERROR;
  424. break;
  425. case IOCTL_VIDEO_QUERY_CURRENT_MODE:
  426. VideoDebugPrint((2, "SimStartIO - QueryCurrentModes\n"));
  427. modeInformation = RequestPacket->OutputBuffer;
  428. if (RequestPacket->OutputBufferLength <
  429. (RequestPacket->StatusBlock->Information =
  430. sizeof(VIDEO_MODE_INFORMATION)) ) {
  431. status = ERROR_INSUFFICIENT_BUFFER;
  432. } else {
  433. *((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) =
  434. SimModes[hwDeviceExtension->CurrentModeNumber];
  435. status = NO_ERROR;
  436. }
  437. break;
  438. case IOCTL_VIDEO_QUERY_AVAIL_MODES:
  439. {
  440. UCHAR i;
  441. VideoDebugPrint((2, "SimStartIO - QueryAvailableModes\n"));
  442. if (RequestPacket->OutputBufferLength <
  443. (RequestPacket->StatusBlock->Information =
  444. SimNumModes * sizeof(VIDEO_MODE_INFORMATION)) ) {
  445. status = ERROR_INSUFFICIENT_BUFFER;
  446. } else {
  447. modeInformation = RequestPacket->OutputBuffer;
  448. for (i = 0; i < SimNumModes; i++) {
  449. *modeInformation = SimModes[i];
  450. modeInformation++;
  451. }
  452. status = NO_ERROR;
  453. }
  454. break;
  455. }
  456. case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
  457. VideoDebugPrint((2, "SimStartIO - QueryNumAvailableModes\n"));
  458. if (RequestPacket->OutputBufferLength <
  459. (RequestPacket->StatusBlock->Information =
  460. sizeof(VIDEO_NUM_MODES)) ) {
  461. status = ERROR_INSUFFICIENT_BUFFER;
  462. } else {
  463. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
  464. SimNumModes;
  465. ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
  466. sizeof(VIDEO_MODE_INFORMATION);
  467. status = NO_ERROR;
  468. }
  469. break;
  470. case IOCTL_VIDEO_SET_CURRENT_MODE:
  471. VideoDebugPrint((2, "SimStartIO - SetCurrentMode\n"));
  472. if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) {
  473. status = ERROR_INSUFFICIENT_BUFFER;
  474. }
  475. hwDeviceExtension->CurrentModeNumber = ((PVIDEO_MODE)
  476. (RequestPacket->InputBuffer))->RequestedMode;
  477. status = NO_ERROR;
  478. break;
  479. case IOCTL_VIDEO_SET_COLOR_REGISTERS:
  480. VideoDebugPrint((2, "SimStartIO - SetColorRegs\n"));
  481. status = NO_ERROR;
  482. break;
  483. case IOCTL_VIDEO_RESET_DEVICE:
  484. VideoDebugPrint((2, "SimStartIO - RESET_DEVICE\n"));
  485. status = NO_ERROR;
  486. break;
  487. //
  488. // if we get here, an invalid IoControlCode was specified.
  489. //
  490. default:
  491. VideoDebugPrint((1, "Fell through Sim startIO routine - invalid command\n"));
  492. status = ERROR_INVALID_FUNCTION;
  493. break;
  494. }
  495. RequestPacket->StatusBlock->Status = status;
  496. return TRUE;
  497. } // end SimStartIO()