BOOLEAN NTAPI XboxVmpInitialize(PVOID HwDeviceExtension) { PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension; ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; ULONG Length; VideoPortDebugPrint(Trace, "XboxVmpInitialize\n"); XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION) HwDeviceExtension; Length = XboxVmpDeviceExtension->ControlLength; XboxVmpDeviceExtension->VirtControlStart = NULL; if (NO_ERROR != VideoPortMapMemory(HwDeviceExtension, XboxVmpDeviceExtension->PhysControlStart, &Length, &inIoSpace, &XboxVmpDeviceExtension->VirtControlStart)) { VideoPortDebugPrint(Error, "Failed to map control memory\n"); return FALSE; } VideoPortDebugPrint(Info, "Mapped 0x%x bytes of control mem at 0x%x to virt addr 0x%x\n", XboxVmpDeviceExtension->ControlLength, XboxVmpDeviceExtension->PhysControlStart.u.LowPart, XboxVmpDeviceExtension->VirtControlStart); return TRUE; }
VP_STATUS QueryPublicAccessRanges_m(PVIDEO_REQUEST_PACKET RequestPacket) { PVIDEO_PUBLIC_ACCESS_RANGES portAccess; PHYSICAL_ADDRESS physicalPortBase; ULONG physicalPortLength; if ( RequestPacket->OutputBufferLength < (RequestPacket->StatusBlock->Information = sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) ) { return ERROR_INSUFFICIENT_BUFFER; } portAccess = RequestPacket->OutputBuffer; portAccess->VirtualAddress = (PVOID) NULL; // Requested VA portAccess->InIoSpace = 1; // In IO space portAccess->MappedInIoSpace = portAccess->InIoSpace; physicalPortBase.HighPart = 0x00000000; physicalPortBase.LowPart = 0x00000000; // physicalPortLength = LINEDRAW+2 - physicalPortBase.LowPart; physicalPortLength = 0x10000; // *SANITIZE* If MM available, give MM ports instead. return VideoPortMapMemory(phwDeviceExtension, physicalPortBase, &physicalPortLength, &(portAccess->MappedInIoSpace), &(portAccess->VirtualAddress)); } /* QueryPublicAccessRanges_m() */
BOOLEAN VGAMapVideoMemory(IN PVOID DeviceExtension, IN PVIDEO_MEMORY RequestedAddress, OUT PVIDEO_MEMORY_INFORMATION MapInformation, OUT PSTATUS_BLOCK StatusBlock) { ULONG ReturnedLength; PVOID ReturnedAddress; ULONG IoSpace; PHYSICAL_ADDRESS FrameBufferBase; ReturnedAddress = RequestedAddress->RequestedVirtualAddress; ReturnedLength = 256 * 1024; FrameBufferBase.QuadPart = 0xA0000; IoSpace = VIDEO_MEMORY_SPACE_MEMORY; StatusBlock->Status = VideoPortMapMemory(DeviceExtension, FrameBufferBase, &ReturnedLength, &IoSpace, &ReturnedAddress); if (StatusBlock->Status != 0) { StatusBlock->Information = 0; return TRUE; } MapInformation->VideoRamBase = MapInformation->FrameBufferBase = ReturnedAddress; MapInformation->VideoRamLength = MapInformation->FrameBufferLength = ReturnedLength; StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); return TRUE; }
BOOLEAN FASTCALL XboxVmpMapVideoMemory( PXBOXVMP_DEVICE_EXTENSION DeviceExtension, PVIDEO_MEMORY RequestedAddress, PVIDEO_MEMORY_INFORMATION MapInformation, PSTATUS_BLOCK StatusBlock) { PHYSICAL_ADDRESS FrameBuffer; ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; SYSTEM_BASIC_INFORMATION BasicInfo; ULONG Length; /* FIXME: this should probably be done differently, without native API */ StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); FrameBuffer.u.HighPart = 0; if (ZwQuerySystemInformation(SystemBasicInformation, (PVOID) &BasicInfo, sizeof(SYSTEM_BASIC_INFORMATION), &Length) == NO_ERROR) { FrameBuffer.u.LowPart = BasicInfo.HighestPhysicalPageNumber * PAGE_SIZE; } else { VideoPortDebugPrint(Error, "ZwQueryBasicInformation failed, assuming 64MB total memory\n"); FrameBuffer.u.LowPart = 60 * 1024 * 1024; } FrameBuffer.QuadPart += DeviceExtension->PhysFrameBufferStart.QuadPart; MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress; MapInformation->VideoRamLength = 4 * 1024 * 1024; VideoPortMapMemory(DeviceExtension, FrameBuffer, &MapInformation->VideoRamLength, &inIoSpace, &MapInformation->VideoRamBase); MapInformation->FrameBufferBase = MapInformation->VideoRamBase; MapInformation->FrameBufferLength = MapInformation->VideoRamLength; /* Tell the nVidia controller about the framebuffer */ *((PULONG)((char *) DeviceExtension->VirtControlStart + CONTROL_FRAMEBUFFER_ADDRESS_OFFSET)) = FrameBuffer.u.LowPart; VideoPortDebugPrint(Info, "Mapped 0x%x bytes of phys mem at 0x%lx to virt addr 0x%p\n", MapInformation->VideoRamLength, FrameBuffer.u.LowPart, MapInformation->VideoRamBase); return TRUE; }
int VBoxMPCmnMapAdapterMemory(PVBOXMP_COMMON pCommon, void **ppv, uint32_t ulOffset, uint32_t ulSize) { PVBOXMP_DEVEXT pPEXT = VBoxCommonToPrimaryExt(pCommon); LOGF(("0x%08X[0x%X]", ulOffset, ulSize)); if (!ulSize) { WARN(("Illegal length 0!")); return ERROR_INVALID_PARAMETER; } PHYSICAL_ADDRESS FrameBuffer; FrameBuffer.QuadPart = VBoxCommonFromDeviceExt(pPEXT)->phVRAM.QuadPart + ulOffset; PVOID VideoRamBase = NULL; ULONG VideoRamLength = ulSize; VP_STATUS Status; #ifndef VBOX_WITH_WDDM ULONG inIoSpace = 0; Status = VideoPortMapMemory(pPEXT, FrameBuffer, &VideoRamLength, &inIoSpace, &VideoRamBase); #else NTSTATUS ntStatus = pPEXT->u.primary.DxgkInterface.DxgkCbMapMemory(pPEXT->u.primary.DxgkInterface.DeviceHandle, FrameBuffer, VideoRamLength, FALSE, /* IN BOOLEAN InIoSpace */ FALSE, /* IN BOOLEAN MapToUserMode */ MmNonCached, /* IN MEMORY_CACHING_TYPE CacheType */ &VideoRamBase /*OUT PVOID *VirtualAddress*/ ); Assert(ntStatus == STATUS_SUCCESS); /* this is what VideoPortMapMemory returns according to the docs */ Status = ntStatus == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER; #endif if (Status == NO_ERROR) { *ppv = VideoRamBase; } LOGF(("rc = %d", Status)); return (Status==NO_ERROR) ? VINF_SUCCESS:VERR_INVALID_PARAMETER; }
/* Called for IOCTL_VIDEO_SHARE_VIDEO_MEMORY. * Maps FrameBuffer as a linear frame buffer to a caller's virtual adress space. (obsolete). */ BOOLEAN VBoxMPShareVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_SHARE_MEMORY pShareMem, PVIDEO_SHARE_MEMORY_INFORMATION pShareMemInfo, PSTATUS_BLOCK pStatus) { PHYSICAL_ADDRESS shareAddress; ULONG inIoSpace = 0; ULONG offset, size; PVOID virtualAddress; ULONG ulMaxFBSize; LOGF_ENTER(); ulMaxFBSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize; offset = pShareMem->ViewOffset; size = pShareMem->ViewSize; virtualAddress = pShareMem->ProcessHandle; VBOXMPIOCTL_HIDE(pShareMem); if ((offset>ulMaxFBSize) || ((offset+size)>ulMaxFBSize)) { WARN(("share failed offset:size(%#x:%#x) > %#x fb size.", offset, size, ulMaxFBSize)); pStatus->Status = ERROR_INVALID_PARAMETER; return FALSE; } shareAddress.QuadPart = VBoxCommonFromDeviceExt(pExt)->phVRAM.QuadPart + pExt->ulFrameBufferOffset; pStatus->Status = VideoPortMapMemory(pExt, shareAddress, &size, &inIoSpace, &virtualAddress); if (NO_ERROR == pStatus->Status) { pShareMemInfo->SharedViewOffset = offset; pShareMemInfo->SharedViewSize = size; pShareMemInfo->VirtualAddress = virtualAddress; pStatus->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION); } VBOXMPIOCTL_UNHIDE(); LOGF_LEAVE(); return NO_ERROR == pStatus->Status; }
/* Called for IOCTL_VIDEO_MAP_VIDEO_MEMORY. * Maps FrameBuffer and video RAM to a caller's virtual adress space. */ BOOLEAN VBoxMPMapVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_MEMORY pRequestedAddress, PVIDEO_MEMORY_INFORMATION pMapInfo, PSTATUS_BLOCK pStatus) { PHYSICAL_ADDRESS framebuffer; ULONG inIoSpace = 0; LOGF(("framebuffer offset %#x", pExt->ulFrameBufferOffset)); framebuffer.QuadPart = VBoxCommonFromDeviceExt(pExt)->phVRAM.QuadPart + pExt->ulFrameBufferOffset; pMapInfo->VideoRamBase = pRequestedAddress->RequestedVirtualAddress; VBOXMPIOCTL_HIDE(pRequestedAddress); pMapInfo->VideoRamLength = pExt->pPrimary->u.primary.ulMaxFrameBufferSize; pStatus->Status = VideoPortMapMemory(pExt, framebuffer, &pMapInfo->VideoRamLength, &inIoSpace, &pMapInfo->VideoRamBase); if (NO_ERROR == pStatus->Status) { pMapInfo->FrameBufferBase = (PUCHAR)pMapInfo->VideoRamBase; pMapInfo->FrameBufferLength = VBoxMPXpdmCurrentVideoMode(pExt)->VisScreenHeight* VBoxMPXpdmCurrentVideoMode(pExt)->ScreenStride; pStatus->Information = sizeof(VIDEO_MEMORY_INFORMATION); /* Save the new framebuffer size */ pExt->ulFrameBufferSize = pMapInfo->FrameBufferLength; HGSMIAreaInitialize(&pExt->areaDisplay, pMapInfo->FrameBufferBase, pMapInfo->FrameBufferLength, pExt->ulFrameBufferOffset); } VBOXMPIOCTL_UNHIDE(); LOGF_LEAVE(); return NO_ERROR == pStatus->Status; }
BOOLEAN DGXStartIO( PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket ) /*++ Routine Description: This routine is the main execution routine for the miniport driver. It acceptss a Video Request Packet, performs the request, and then returns with the appropriate status. Arguments: HwDeviceExtension - Supplies a pointer to the miniport's device extension. RequestPacket - Pointer to the video request packet. This structure contains all the parameters passed to the VideoIoControl function. Return Value: --*/ { PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; VP_STATUS status; PVIDEO_MODE_INFORMATION modeInformation; PVIDEO_MEMORY_INFORMATION memoryInformation; ULONG inIoSpace, ulTemp; PVIDEO_CLUT clutBuffer; ULONG modeNumber; PVIDEO_SHARE_MEMORY pShareMemory; PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation; PHYSICAL_ADDRESS shareAddress; PVOID virtualAddress; ULONG sharedViewSize; // // Switch on the IoContolCode in the RequestPacket. It indicates which // function must be performed by the driver. // switch (RequestPacket->IoControlCode) { case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: VideoDebugPrint((2, "DGXStartIO - ShareVideoMemory\n")); if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } pShareMemory = RequestPacket->InputBuffer; if ( (pShareMemory->ViewOffset > hwDeviceExtension->FrameLength) || ((pShareMemory->ViewOffset + pShareMemory->ViewSize) > hwDeviceExtension->FrameLength) ) { status = ERROR_INVALID_PARAMETER; break; } RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION); // // Beware: the input buffer and the output buffer are the same // buffer, and therefore data should not be copied from one to the // other // virtualAddress = pShareMemory->ProcessHandle; sharedViewSize = pShareMemory->ViewSize; inIoSpace = 0; // // NOTE: we are ignoring ViewOffset // shareAddress.QuadPart = hwDeviceExtension->PhysicalFrameAddress.QuadPart; status = VideoPortMapMemory(hwDeviceExtension, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress); pShareMemoryInformation = RequestPacket->OutputBuffer; pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset; pShareMemoryInformation->VirtualAddress = virtualAddress; pShareMemoryInformation->SharedViewSize = sharedViewSize; break; case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: VideoDebugPrint((2, "DGXStartIO - UnshareVideoMemory\n")); if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) { status = ERROR_INSUFFICIENT_BUFFER; break; } pShareMemory = RequestPacket->InputBuffer; status = VideoPortUnmapMemory(hwDeviceExtension, pShareMemory->RequestedVirtualAddress, pShareMemory->ProcessHandle); break; case IOCTL_VIDEO_MAP_VIDEO_MEMORY: VideoDebugPrint((2, "DGXStartIO - MapVideoMemory\n")); if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION)) || (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } RequestPacket->StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); memoryInformation = RequestPacket->OutputBuffer; memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress; memoryInformation->VideoRamLength = hwDeviceExtension->FrameLength; inIoSpace = 0; status = VideoPortMapMemory(hwDeviceExtension, hwDeviceExtension->PhysicalFrameAddress, &(memoryInformation->VideoRamLength), &inIoSpace, &(memoryInformation->VideoRamBase)); // // The frame buffer and virtual memory and equivalent in this // case. // memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase; memoryInformation->FrameBufferLength = memoryInformation->VideoRamLength; break; case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: VideoDebugPrint((2, "DGXStartIO - UnMapVideoMemory\n")); if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) { status = ERROR_INSUFFICIENT_BUFFER; } else { status = VideoPortUnmapMemory(hwDeviceExtension, ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))-> RequestedVirtualAddress, 0); } break; case IOCTL_VIDEO_QUERY_CURRENT_MODE: VideoDebugPrint((2, "DGXStartIO - QueryCurrentModes\n")); modeInformation = RequestPacket->OutputBuffer; if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) { status = ERROR_INSUFFICIENT_BUFFER; } else { RequestPacket->StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION); *((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) = DGXModes[hwDeviceExtension->CurrentModeNumber].modeInformation; status = NO_ERROR; } break; case IOCTL_VIDEO_QUERY_AVAIL_MODES: { UCHAR i; VideoDebugPrint((2, "DGXStartIO - QueryAvailableModes\n")); if (RequestPacket->OutputBufferLength < hwDeviceExtension->NumValidModes * sizeof(VIDEO_MODE_INFORMATION)) { status = ERROR_INSUFFICIENT_BUFFER; } else { RequestPacket->StatusBlock->Information = hwDeviceExtension->NumValidModes * sizeof(VIDEO_MODE_INFORMATION); modeInformation = RequestPacket->OutputBuffer; for (i = 0; i < NumDGXModes; i++) { if (DGXModes[i].bValid) { *modeInformation = DGXModes[i].modeInformation; modeInformation++; } } status = NO_ERROR; } break; } case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: VideoDebugPrint((2, "DGXStartIO - QueryNumAvailableModes\n")); // // Find out the size of the data to be put in the the buffer and // return that in the status information (whether or not the // information is there). If the buffer passed in is not large // enough return an appropriate error code. // // WARNING: This must be changed to take into account which monitor // is present on the machine. // if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) { status = ERROR_INSUFFICIENT_BUFFER; } else { RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES); ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes = hwDeviceExtension->NumValidModes; ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); status = NO_ERROR; } break; case IOCTL_VIDEO_SET_CURRENT_MODE: VideoDebugPrint((2, "DGXStartIO - SetCurrentMode\n")); // // verify data // WARNING: Make sure it is one of the valid modes on the list // calculated using the monitor information. // modeNumber = ((PVIDEO_MODE)(RequestPacket->InputBuffer))->RequestedMode; if ( (modeNumber >= hwDeviceExtension->NumValidModes) || (!DGXModes[modeNumber].bValid) ) { status = ERROR_INVALID_PARAMETER; break; } DevInitDGX(hwDeviceExtension, (PULONG)DGXModes[modeNumber].pVData, DGXModes[modeNumber].Count); if (DGXModes[modeNumber].modeInformation.BitsPerPlane == 16) { DevSet16BppPalette(hwDeviceExtension); } hwDeviceExtension->CurrentModeNumber = modeNumber; status = NO_ERROR; break; case IOCTL_VIDEO_SET_COLOR_REGISTERS: VideoDebugPrint((2, "DGXStartIO - SetColorRegs\n")); clutBuffer = RequestPacket->InputBuffer; // // Check if the size of the data in the input buffer is large enough. // if ( (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) - sizeof(ULONG)) || (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) + (sizeof(ULONG) * (clutBuffer->NumEntries - 1)) ) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } if (DGXModes[hwDeviceExtension->CurrentModeNumber]. modeInformation.BitsPerPlane == 8) { DevSetPalette(hwDeviceExtension, (PULONG)clutBuffer->LookupTable, clutBuffer->FirstEntry, clutBuffer->NumEntries); status = NO_ERROR; } break; case IOCTL_VIDEO_ENABLE_POINTER: VideoDebugPrint((2, "DGXStartIO - EnablePointer\n")); ulTemp = *hwDeviceExtension->pControlRegA; ulTemp &= ~DAC_DISABLEPOINTER; DacDelay(); *hwDeviceExtension->pControlRegA = ulTemp; status = NO_ERROR; break; case IOCTL_VIDEO_DISABLE_POINTER: VideoDebugPrint((2, "DGXStartIO - DisablePointer\n")); DevPointerOff(hwDeviceExtension); status = NO_ERROR; break; case IOCTL_VIDEO_SET_POINTER_POSITION: { PVIDEO_POINTER_POSITION pointerPosition; VideoDebugPrint((2, "DGXStartIO - SetpointerPostion\n")); pointerPosition = RequestPacket->InputBuffer; // // Check if the size of the data in the input buffer is large enough. // if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_POSITION)) { status = ERROR_INSUFFICIENT_BUFFER; } else { hwDeviceExtension->ulPointerX = (ULONG)pointerPosition->Row; hwDeviceExtension->ulPointerY = (ULONG)pointerPosition->Column; DevSetPointerPos(hwDeviceExtension, (ULONG)pointerPosition->Column, (ULONG)pointerPosition->Row); status = NO_ERROR; } break; } case IOCTL_VIDEO_QUERY_POINTER_POSITION: { PVIDEO_POINTER_POSITION pPointerPosition = RequestPacket->OutputBuffer; VideoDebugPrint((2, "DGXStartIO - QuerypointerPostion\n")); // // Make sure the output buffer is big enough. // if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION)) { RequestPacket->StatusBlock->Information = 0; return ERROR_INSUFFICIENT_BUFFER; } // // Return the pointer position // RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_POSITION); pPointerPosition->Row = (SHORT)hwDeviceExtension->ulPointerX; pPointerPosition->Column = (SHORT)hwDeviceExtension->ulPointerY; status = NO_ERROR; break; } case IOCTL_VIDEO_SET_POINTER_ATTR: { PVIDEO_POINTER_ATTRIBUTES pointerAttributes; USHORT *pHWCursorShape; // Temp Buffer USHORT *pHWCursorAddr; // DAC buffer ULONG iCount = 512; VideoDebugPrint((2, "DGXStartIO - SetPointerAttributes\n")); pointerAttributes = RequestPacket->InputBuffer; // // Check if the size of the data in the input buffer is large enough. // if (RequestPacket->InputBufferLength < (sizeof(VIDEO_POINTER_ATTRIBUTES) + ((sizeof(UCHAR) * (CURSOR_WIDTH/8) * CURSOR_HEIGHT) * 2))) { status = ERROR_INSUFFICIENT_BUFFER; break; } // // If the specified cursor width or height is not valid, then // return an invalid parameter error. // if ((pointerAttributes->Width > CURSOR_WIDTH) || (pointerAttributes->Height > CURSOR_HEIGHT)) { status = ERROR_INVALID_PARAMETER; break; } // // Try to copy the pointer to our buffer. When we copy it // we convert it to our 2bpp format. If sucessfull, then // copy it to the DAC and set the position. // if (!(pointerAttributes->Flags & VIDEO_MODE_ANIMATE_UPDATE)) { DevPointerOff(hwDeviceExtension); } if (pointerAttributes->Flags & VIDEO_MODE_MONO_POINTER) { if (CopyMonoCursor(hwDeviceExtension, (PUCHAR)&pointerAttributes->Pixels[0])) { pHWCursorAddr = (USHORT *)hwDeviceExtension->pHardWareCursorAddr; pHWCursorShape = (USHORT *)&hwDeviceExtension->HardwareCursorShape[0]; while (iCount--) { *pHWCursorAddr++ = *pHWCursorShape++; pHWCursorAddr++; DacDelay(); } DevSetPointerPos(hwDeviceExtension, (ULONG)pointerAttributes->Column, (ULONG)pointerAttributes->Row); status = NO_ERROR; break; } } // // Something failed. Remove the current HW Cursor. // DevPointerOff(hwDeviceExtension); status = ERROR_INVALID_PARAMETER; break; } case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: { PVIDEO_POINTER_CAPABILITIES pointerCaps = RequestPacket->OutputBuffer; VideoDebugPrint((2, "DGXStartIO - QueryPointerCapabilities\n")); if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES)) { RequestPacket->StatusBlock->Information = 0; status = ERROR_INSUFFICIENT_BUFFER; } pointerCaps->Flags = VIDEO_MODE_ASYNC_POINTER | VIDEO_MODE_MONO_POINTER; pointerCaps->MaxWidth = CURSOR_WIDTH; pointerCaps->MaxHeight = CURSOR_HEIGHT; pointerCaps->HWPtrBitmapStart = 0; // No VRAM storage for pointer pointerCaps->HWPtrBitmapEnd = 0; // // Number of bytes we're returning. // RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES); status = NO_ERROR; break; } case IOCTL_VIDEO_RESET_DEVICE: VideoDebugPrint((2, "DGXStartIO - RESET_DEVICE\n")); DevDisableDGX(hwDeviceExtension); status = NO_ERROR; break; // // if we get here, an invalid IoControlCode was specified. // default: VideoDebugPrint((1, "Fell through DGX startIO routine - invalid command\n")); status = ERROR_INVALID_FUNCTION; break; } RequestPacket->StatusBlock->Status = status; return TRUE; } // end DGXStartIO() z
VP_STATUS MapVideoMemory_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_MEMORY_INFORMATION memoryInformation; ULONG inIoSpace; /* Scratch variable used by VideoPortMapMemory() */ VP_STATUS status; /* Error code obtained from O/S calls */ memoryInformation = RequestPacket->OutputBuffer; memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress; /* * The VideoRamLength field contains the amount of video memory * on the card. The FrameBufferLength field contains the * size of the aperture in bytes * * Initially assume that the linear aperture is available. * For our 8514/A-compatible cards, we always enable a 4M aperture * if the LFB is available, so map the full 4M even if the * aperture size is greater than the amount of video memory. */ memoryInformation->VideoRamLength = phwDeviceExtension->VideoRamSize; memoryInformation->FrameBufferLength = 4 * ONE_MEG; /* * If the linear aperture is not available (==0), and we are * dealing with a card which can use the VGA 64k aperture, * map it in. */ if (QueryPtr->q_aperture_cfg == 0) { if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) && (QueryPtr->q_VGA_type == 1)) { phwDeviceExtension->FrameLength = 0x10000; phwDeviceExtension->PhysicalFrameAddress.LowPart = 0x0A0000; memoryInformation->FrameBufferLength = phwDeviceExtension->FrameLength; } else{ /* * This card can't use either linear or VGA aperture. * Set frame buffer size to zero and return. */ memoryInformation->VideoRamBase = 0; memoryInformation->FrameBufferLength = 0; memoryInformation->FrameBufferBase = 0; return NO_ERROR; } } inIoSpace = 0; #if 0 /* defined(ALPHA) if display driver can handle dense LFB */ if (QueryPtr->q_bus_type == BUS_PCI) inIoSpace = 4; #endif status = VideoPortMapMemory(phwDeviceExtension, phwDeviceExtension->PhysicalFrameAddress, &(memoryInformation->FrameBufferLength), &inIoSpace, &(memoryInformation->VideoRamBase)); memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase; return status; } /* MapVideoMemory_m() */
VP_STATUS ShareVideoMemory_m(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr) { PVIDEO_SHARE_MEMORY InputPtr; /* Pointer to input structure */ PVIDEO_SHARE_MEMORY_INFORMATION OutputPtr; /* Pointer to output structure */ PHYSICAL_ADDRESS ShareAddress; /* Physical address of video memory */ PVOID VirtualAddress; /* Virtual address to map video memory at */ ULONG SharedViewSize; /* Size of block to share */ ULONG SpaceType; /* Sparse or dense space? */ VP_STATUS Status; /* Status to return */ /* * We can only share the aperture with application programs if there * is an aperture available. If both the LFB and the on-board VGA * and therefore the VGA aperture) are disabled, report that we * can't share the aperture. */ if ((QueryPtr->q_aperture_cfg == 0) && (QueryPtr->q_VGA_type == 0)) return ERROR_INVALID_FUNCTION; InputPtr = RequestPacket->InputBuffer; if ((InputPtr->ViewOffset > phwDeviceExtension->VideoRamSize) || ((InputPtr->ViewOffset + InputPtr->ViewSize) > phwDeviceExtension->VideoRamSize)) { VideoDebugPrint((DEBUG_ERROR, "ShareVideoMemory_m() - access beyond video memory\n")); return ERROR_INVALID_PARAMETER; } RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION); /* * Beware: the input buffer and the output buffer are the same buffer, * and therefore data should not be copied from one to the other. */ VirtualAddress = InputPtr->ProcessHandle; SharedViewSize = InputPtr->ViewSize; SpaceType = 0; #if defined(_ALPHA_) /* * Use dense space mapping whenever we can, because that will * allow us to support DCI and direct GDI access. * * Dense space is extremely slow with ISA cards on the newer Alphas, * because any byte- or word-write requires a read/modify/write * operation, and the ALpha can only ever do 64-bit reads when in * dense mode. As a result, these operations would always require * 4 reads and 2 writes on the ISA bus. Also, some older Alphas * don't support dense space mapping. * * Any Alpha that supports PCI can support dense space mapping, and * because the bus is wider and faster, the read/modify/write has * less of an impact on performance. */ if (QueryPtr->q_bus_type == BUS_PCI) SpaceType = 4; #endif /* * NOTE: we are ignoring ViewOffset */ ShareAddress.QuadPart = phwDeviceExtension->PhysicalFrameAddress.QuadPart; /* * If the LFB is enabled, use ordinary mapping. If we have only * the paged aperture, we must map to banked memory. Since the * LFB is always aligned on a 1M boundary (4M boundary for 4M * aperture), this check for the paged aperture will never falsely * detect a LFB as paged. */ if (phwDeviceExtension->PhysicalFrameAddress.LowPart == 0x0A0000) { /* * On some versions of the DDK, VideoPortMapBankedMemory() is * not available. If this is the case, force an error. * This routine should be available in all versions of * the DDK which support DCI, since it is used for DCI * support on cards with banked apertures. */ #if defined(IOCTL_VIDEO_SHARE_VIDEO_MEMORY) Status = VideoPortMapBankedMemory( phwDeviceExtension, ShareAddress, &SharedViewSize, &SpaceType, &VirtualAddress, 0x10000, /* 64k VGA aperture */ FALSE, /* No separate read/write banks */ BankMap_m, /* Our bank-mapping routine */ (PVOID) phwDeviceExtension); #else Status = ERROR_INVALID_FUNCTION; #endif } else /* LFB */ { Status = VideoPortMapMemory(phwDeviceExtension, ShareAddress, &SharedViewSize, &SpaceType, &VirtualAddress); } OutputPtr = RequestPacket->OutputBuffer; OutputPtr->SharedViewOffset = InputPtr->ViewOffset; OutputPtr->VirtualAddress = VirtualAddress; OutputPtr->SharedViewSize = SharedViewSize; return Status; } /* ShareVideoMemory_m() */
/* Main I/O request handler routine. */ BOOLEAN HwVidStartIO( PVOID HwDevExt, PVIDEO_REQUEST_PACKET ReqPkt ) { PHW_DEV_EXT pExt = HwDevExt; VP_STATUS status = NO_ERROR; PVIDEO_MODE_INFORMATION modeInfo; PVIDEO_MEMORY vidMem; PVIDEO_SHARE_MEMORY pShrMem; PVOID virtualAddress; ULONG inIoSpace; ULONG modeNumber; ULONG ulLen; ULONG i; VideoDebugPrint( (2, "videomp: HwVidStartIO: ") ); /* Process the VRP. Required requests are handled first. */ switch( ReqPkt->IoControlCode ) { case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: { PVIDEO_NUM_MODES numModes; VideoDebugPrint( (2, "QUERY_NUM_AVAIL_MODES\n") ); if( ReqPkt->OutputBufferLength < sizeof( VIDEO_NUM_MODES ) ) { status = ERROR_INSUFFICIENT_BUFFER; } else { ReqPkt->StatusBlock->Information = sizeof( VIDEO_NUM_MODES ); numModes = (PVIDEO_NUM_MODES)ReqPkt->OutputBuffer; numModes->ModeInformationLength = sizeof( VIDEO_MODE_INFORMATION ); numModes->NumModes = pExt->NumValidModes; } break; } case IOCTL_VIDEO_QUERY_AVAIL_MODES: VideoDebugPrint( (2, "QUERY_AVAIL_MODES\n") ); ulLen = pExt->NumValidModes * sizeof( VIDEO_MODE_INFORMATION ); if( ReqPkt->OutputBufferLength < ulLen ) { status = ERROR_INSUFFICIENT_BUFFER; } else { ReqPkt->StatusBlock->Information = ulLen; modeInfo = ReqPkt->OutputBuffer; for( i = 0; i < ulAllModes; ++i ) { if( VideoModes[i].bValid ) { vmpFillModeInfo( modeInfo, VideoModes[i].HorzRes, VideoModes[i].VertRes, VideoModes[i].Bpp ); modeInfo->ModeIndex = i; //VideoModes[i].modeInformation.ModeIndex; modeInfo++; } } } break; case IOCTL_VIDEO_QUERY_CURRENT_MODE: VideoDebugPrint( (2, "QUERY_CURRENT_MODE\n") ); if( ReqPkt->OutputBufferLength < sizeof( VIDEO_MODE_INFORMATION ) ) { status = ERROR_INSUFFICIENT_BUFFER; } else { ReqPkt->StatusBlock->Information = sizeof( VIDEO_MODE_INFORMATION ); modeInfo = ReqPkt->OutputBuffer; vmpFillModeInfo( modeInfo, VideoModes[pExt->CurrentModeNumber].HorzRes, VideoModes[pExt->CurrentModeNumber].VertRes, VideoModes[pExt->CurrentModeNumber].Bpp ); modeInfo->ModeIndex = pExt->CurrentModeNumber; //VideoModes[pExt->CurrentModeNumber].modeInformation.ModeIndex; } break; case IOCTL_VIDEO_SET_CURRENT_MODE: VideoDebugPrint( (2, "SET_CURRENT_MODE\n") ); /* Ensure the mode is valid. */ modeNumber = ((PVIDEO_MODE)(ReqPkt->InputBuffer))->RequestedMode; if( (modeNumber > ulAllModes) || (!VideoModes[modeNumber].bValid) ) { status = ERROR_INVALID_PARAMETER; break; } BOXV_ext_mode_set( pExt, VideoModes[modeNumber].HorzRes, VideoModes[modeNumber].VertRes, VideoModes[modeNumber].Bpp, VideoModes[modeNumber].HorzRes, VideoModes[modeNumber].VertRes ); pExt->CurrentModeNumber = modeNumber; break; case IOCTL_VIDEO_RESET_DEVICE: VideoDebugPrint( (2, "RESET_DEVICE\n") ); /* Not calling the following routine avoids some visual glitches. */ /* BOXV_ext_disable( pExt ); */ break; case IOCTL_VIDEO_MAP_VIDEO_MEMORY: { PVIDEO_MEMORY_INFORMATION memInfo; VideoDebugPrint( (2, "MAP_VIDEO_MEMORY\n") ); if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_MEMORY_INFORMATION )) || (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } ReqPkt->StatusBlock->Information = sizeof( VIDEO_MEMORY_INFORMATION ); vidMem = (PVIDEO_MEMORY)ReqPkt->InputBuffer; memInfo = ReqPkt->OutputBuffer; inIoSpace = FALSE; memInfo->VideoRamBase = vidMem->RequestedVirtualAddress; memInfo->VideoRamLength = pExt->FramebufLen; status = VideoPortMapMemory( pExt, pExt->PhysicalFrameAddress, &memInfo->VideoRamLength, &inIoSpace, &memInfo->VideoRamBase ); /* The framebuffer covers the entire video memory. */ memInfo->FrameBufferBase = memInfo->VideoRamBase; memInfo->FrameBufferLength = memInfo->VideoRamLength; break; } case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: VideoDebugPrint( (2, "UNMAP_VIDEO_MEMORY\n") ); if( ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY ) ) { status = ERROR_INSUFFICIENT_BUFFER; } else { vidMem = (PVIDEO_MEMORY)ReqPkt->InputBuffer; status = VideoPortUnmapMemory( pExt, vidMem->RequestedVirtualAddress, 0 ); } break; /* The following request is required for palettized modes. */ case IOCTL_VIDEO_SET_COLOR_REGISTERS: { PVIDEO_CLUT clutBuffer; VideoDebugPrint( (2, "SET_COLOR_REGISTERS\n") ); clutBuffer = ReqPkt->InputBuffer; if( (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) - sizeof( ULONG )) || (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) + (sizeof( ULONG ) * (clutBuffer->NumEntries - 1)) ) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } if( VideoModes[pExt->CurrentModeNumber].Bpp == 8 ) { BOXV_dac_set( pExt, clutBuffer->FirstEntry, clutBuffer->NumEntries, clutBuffer->LookupTable ); } break; } /* The following requests are optional. */ case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: { PVIDEO_POINTER_CAPABILITIES ptrCaps = ReqPkt->OutputBuffer; VideoDebugPrint( (2, "QUERY_POINTER_CAPABILITIES\n") ); if( ReqPkt->OutputBufferLength < sizeof( VIDEO_POINTER_CAPABILITIES ) ) { ReqPkt->StatusBlock->Information = 0; status = ERROR_INSUFFICIENT_BUFFER; } ptrCaps->Flags = 0; /* Indicate no pointer support. */ ptrCaps->MaxWidth = ptrCaps->MaxHeight = 0; /* Documentation and sample code disagree on whether no display * memory for cursor is indicated by 0 or -1. */ ptrCaps->HWPtrBitmapStart = ptrCaps->HWPtrBitmapEnd = ~0; ReqPkt->StatusBlock->Information = sizeof( VIDEO_POINTER_CAPABILITIES ); break; } /* The share/unshare IOCTLs are new for NT 3.51. */ case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: { PVIDEO_SHARE_MEMORY_INFORMATION pShrMemInfo; PHYSICAL_ADDRESS shareAddress; ULONG sharedViewSize; VideoDebugPrint( (2, "SHARE_VIDEO_MEMORY\n") ); if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_SHARE_MEMORY_INFORMATION )) || (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } pShrMem = ReqPkt->InputBuffer; if( (pShrMem->ViewOffset > pExt->FramebufLen) || ((pShrMem->ViewOffset + pShrMem->ViewSize) > pExt->FramebufLen) ) { status = ERROR_INVALID_PARAMETER; break; } ReqPkt->StatusBlock->Information = sizeof( VIDEO_SHARE_MEMORY_INFORMATION ); /* The input buffer is also the output buffer; remember the input. */ virtualAddress = pShrMem->ProcessHandle; sharedViewSize = pShrMem->ViewSize; inIoSpace = FALSE; /* NB: ViewOffset is not being taken into account. */ shareAddress.QuadPart = pExt->PhysicalFrameAddress.QuadPart; status = VideoPortMapMemory( pExt, shareAddress, &sharedViewSize, &inIoSpace, &virtualAddress ); pShrMemInfo = ReqPkt->OutputBuffer; pShrMemInfo->SharedViewOffset = pShrMem->ViewOffset; pShrMemInfo->VirtualAddress = virtualAddress; pShrMemInfo->SharedViewSize = sharedViewSize; break; } case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: VideoDebugPrint( (2, "UNSHARE_VIDEO_MEMORY\n") ); if( ReqPkt->InputBufferLength < sizeof( VIDEO_SHARE_MEMORY ) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } pShrMem = ReqPkt->InputBuffer; status = VideoPortUnmapMemory( pExt, pShrMem->RequestedVirtualAddress, pShrMem->ProcessHandle ); break; /* The child state IOCTLs are new for NT 5.0 (Windows 2000). */ case IOCTL_VIDEO_GET_CHILD_STATE: { PULONG pChildIndex; PULONG pChildState; VideoDebugPrint( (2, "GET_CHILD_STATE\n") ); if( ReqPkt->InputBufferLength < sizeof( ULONG ) || ReqPkt->OutputBufferLength < sizeof( ULONG ) ) { status = ERROR_INSUFFICIENT_BUFFER; break; } pChildIndex = ReqPkt->InputBuffer; pChildState = ReqPkt->OutputBuffer; /* Always say the child is active. */ *pChildState = VIDEO_CHILD_ACTIVE; break; } /* Any other request is invalid and fails. */ default: VideoDebugPrint( (1, "Unhandled IoControlCode %08x!\n", ReqPkt->IoControlCode) ); status = ERROR_INVALID_FUNCTION; break; } ReqPkt->StatusBlock->Status = status; return( TRUE ); }