1027 lines
24 KiB
C
1027 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
drvx.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code to initialize the video hardware
|
|
|
|
--*/
|
|
|
|
#include "minixp.h"
|
|
#include <nvntioctl.h>
|
|
#include "nv32.h"
|
|
#include "nvddobj.h"
|
|
#include <nvos.h>
|
|
|
|
//
|
|
// Sends an IOCTL to the miniport by calling MxDeviceIoControl. To use this macro
|
|
// your shoud have these 'status' and 'BytesReturned' locals defined and CleanupAndExit label
|
|
//
|
|
|
|
#define IOCTL_CMD(Code, InBuf, InLen, OutBuf, OutLen) { \
|
|
status = MxDeviceIoControl(Code, InBuf, InLen, OutBuf, OutLen, &BytesReturned); \
|
|
if (!NT_SUCCESS(status)) goto CleanupAndExit; }
|
|
|
|
//
|
|
// Helper macro to check status of the return call
|
|
//
|
|
#define CHECKSTATUS(x) { status = (x); if (!NT_SUCCESS(status)) goto CleanupAndExit; }
|
|
|
|
|
|
extern PMINIX_DRIVER_EXTENSION MxDriverExtension;
|
|
|
|
|
|
|
|
typedef struct _VIDEOMODEDEF
|
|
{
|
|
USHORT Mode;
|
|
USHORT Width;
|
|
USHORT Height;
|
|
UCHAR Depth;
|
|
UCHAR Refresh;
|
|
|
|
} VIDEOMODEDEF, *PVIDEOMODEDEF;
|
|
|
|
|
|
VIDEOMODEDEF g_VideoModeDef[] =
|
|
{
|
|
#define DEF_VIDEOMODE(Mode, Width, Height, Depth, Refresh) {Mode, Width, Height, Depth, Refresh},
|
|
#include "modes.h"
|
|
#undef DEF_VIDOEMODE
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
NVStartIO(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_REQUEST_PACKET RequestPacket
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
pVideoPortMapToNtStatus(
|
|
IN PSTATUS_BLOCK StatusBlock
|
|
);
|
|
|
|
|
|
//
|
|
// Nvidia object ids
|
|
//
|
|
|
|
#define DD_DEVICE_OBJECT_HANDLE (0x00002002)
|
|
#define DD_FRAME_BUFFER_OBJECT_HANDLE (0x000C0006)
|
|
|
|
#define DD_CONTEXT_DMA_IN_MEMORY_VIDEO_MEM (0x00001022)
|
|
|
|
//
|
|
// Nvidia alloc context dma flags
|
|
//
|
|
#define ALLOC_CTX_DMA_FLAGS_ACCESS_RD_WR 0x00000000
|
|
#define ALLOC_CTX_DMA_FLAGS_ACCESS_READ_ONLY 0x00000001
|
|
#define ALLOC_CTX_DMA_FLAGS_ACCESS_WRITE_ONLY 0x00000002
|
|
|
|
#define ALLOC_CTX_DMA_FLAGS_CONTIGUOUS_PHYSICALITY 0x00000000
|
|
#define ALLOC_CTX_DMA_FLAGS_NONCONTIGUOUS_PHYSICALITY 0x00000010
|
|
|
|
#define ALLOC_CTX_DMA_FLAGS_LOCKED_ALWAYS 0x00000000
|
|
#define ALLOC_CTX_DMA_FLAGS_LOCKED_IN_TRANSIT 0x00000100
|
|
|
|
#define ALLOC_CTX_DMA_FLAGS_COHERENCY_UNCACHED 0x00000000
|
|
#define ALLOC_CTX_DMA_FLAGS_COHERENCY_CACHED 0x00001000
|
|
|
|
#define ALLOC_CTX_DMA_FLAGS_LOCKED_CACHED ALLOC_CTX_DMA_FLAGS_LOCKED_ALWAYS + ALLOC_CTX_DMA_FLAGS_COHERENCY_CACHED
|
|
|
|
|
|
|
|
NTSTATUS
|
|
MxDeviceIoControl(
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer OPTIONAL,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer OPTIONAL,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PULONG BytesReturned
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine builds an vrp and calls miniport start io function directly.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Status of the operation
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
KEVENT event;
|
|
STATUS_BLOCK StatusBlock;
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension;
|
|
PVIDEO_DEVICE_EXTENSION VideoDeviceExtension;
|
|
VIDEO_REQUEST_PACKET vrp;
|
|
|
|
|
|
//
|
|
// we only support METHOD_BUFFERED
|
|
//
|
|
|
|
if ((IoControlCode & 3) != METHOD_BUFFERED) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
HwDeviceExtension = &(MxDriverExtension->HwExtension);
|
|
VideoDeviceExtension = &(MxDriverExtension->VideoExtension);
|
|
|
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
|
|
|
|
|
//
|
|
// Initialize the vrp
|
|
//
|
|
RtlZeroMemory(&StatusBlock, sizeof(STATUS_BLOCK));
|
|
|
|
vrp.IoControlCode = IoControlCode;
|
|
vrp.StatusBlock = &StatusBlock;
|
|
vrp.InputBuffer = InputBuffer;
|
|
vrp.InputBufferLength = InputBufferLength;
|
|
vrp.OutputBuffer = OutputBuffer;
|
|
vrp.OutputBufferLength = OutputBufferLength;
|
|
|
|
//
|
|
// Call the start io routine directly
|
|
//
|
|
|
|
ACQUIRE_DEVICE_LOCK(VideoDeviceExtension);
|
|
|
|
VideoDeviceExtension->HwStartIO(HwDeviceExtension, &vrp);
|
|
|
|
RELEASE_DEVICE_LOCK(VideoDeviceExtension);
|
|
|
|
if (StatusBlock.Status != NO_ERROR) {
|
|
pVideoPortMapToNtStatus(&StatusBlock);
|
|
}
|
|
|
|
status = StatusBlock.Status;
|
|
|
|
//
|
|
// If the call is synchronous, the IO is always completed
|
|
// and the Status is the same as the Iosb.Status.
|
|
//
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
KeWaitForSingleObject(&event, UserRequest, KernelMode, TRUE, NULL);
|
|
}
|
|
|
|
*BytesReturned = StatusBlock.Information;
|
|
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
pVideoPortMapToNtStatus(
|
|
IN PSTATUS_BLOCK StatusBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function maps a Win32 error code to an NT error code, making sure
|
|
the inverse translation will map back to the original status code.
|
|
|
|
Arguments:
|
|
|
|
StatusBlock - Pointer to the status block
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PNTSTATUS status = &StatusBlock->Status;
|
|
|
|
switch (*status) {
|
|
|
|
case ERROR_INVALID_FUNCTION:
|
|
*status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
*status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
|
|
case ERROR_INVALID_PARAMETER:
|
|
*status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
*status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
//
|
|
// Make sure we zero out the information block if we get an
|
|
// insufficient buffer.
|
|
//
|
|
|
|
StatusBlock->Information = 0;
|
|
break;
|
|
|
|
case ERROR_MORE_DATA:
|
|
*status = STATUS_BUFFER_OVERFLOW;
|
|
break;
|
|
|
|
case ERROR_DEV_NOT_EXIST:
|
|
*status = STATUS_DEVICE_DOES_NOT_EXIST;
|
|
break;
|
|
|
|
case ERROR_IO_PENDING:
|
|
ASSERT(FALSE);
|
|
// Fall through.
|
|
|
|
case NO_ERROR:
|
|
*status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
|
|
ASSERT(FALSE);
|
|
|
|
*status = STATUS_UNSUCCESSFUL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocRoot(
|
|
ULONG hClass,
|
|
ULONG *phClient
|
|
)
|
|
{
|
|
NVOS01_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
parms.hClass = hClass;
|
|
pParms = &parms;
|
|
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_ROOT,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
(ULONG)sizeof(NVOS01_PARAMETERS));
|
|
|
|
*phClient = (ULONG)parms.hObjectNew;
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocDevice(
|
|
ULONG hClient,
|
|
ULONG hDevice,
|
|
ULONG hClass,
|
|
PUCHAR szName
|
|
)
|
|
{
|
|
NVOS06_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
parms.hObjectParent = (NvV32)hClient;
|
|
parms.hObjectNew = (NvV32)hDevice;
|
|
parms.hClass = (NvV32)hClass;
|
|
|
|
#ifdef NV20MINIX
|
|
parms.szName = (NvP64)szName;
|
|
#else
|
|
parms.szName = (NvV32)szName;
|
|
#endif
|
|
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_DEVICE,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS06_PARAMETERS));
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocContextDma(
|
|
ULONG hClient,
|
|
ULONG hDma,
|
|
ULONG hClass,
|
|
ULONG flags,
|
|
PVOID base,
|
|
ULONG limit
|
|
)
|
|
{
|
|
NVOS03_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
parms.hObjectParent = (NvV32)hClient;
|
|
parms.hObjectNew = (NvV32)hDma;
|
|
parms.hClass = (NvV32)hClass;
|
|
parms.flags = (NvV32)flags;
|
|
#ifdef NV20MINIX
|
|
parms.pBase = (NvP64)base;
|
|
parms.limit = (NvU64)limit;
|
|
#else
|
|
parms.pBase.selector = 0x00000000;
|
|
parms.pBase.offset = (NvU32)base;
|
|
parms.limit.high = 0x00000000;
|
|
parms.limit.low = (NvU32)limit;
|
|
#endif
|
|
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_CONTEXT_DMA,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS03_PARAMETERS));
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocObject(
|
|
ULONG hClient,
|
|
ULONG hChannel,
|
|
ULONG hObject,
|
|
ULONG hClass
|
|
)
|
|
{
|
|
NVOS05_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
|
|
// set input parameters
|
|
parms.hRoot = (NvV32)hClient;
|
|
parms.hObjectParent = (NvV32)hChannel;
|
|
parms.hObjectNew = (NvV32)hObject;
|
|
parms.hClass = (NvV32)hClass;
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_OBJECT,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS05_PARAMETERS));
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocEvent(
|
|
ULONG hClient,
|
|
ULONG hParent,
|
|
ULONG hObject,
|
|
ULONG hClass,
|
|
ULONG index,
|
|
ULONG hEvent
|
|
)
|
|
{
|
|
NVOS10_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
// set input parameters
|
|
parms.hRoot = (NvV32)hClient;
|
|
parms.hObjectParent = (NvV32)hParent;
|
|
parms.hObjectNew = (NvV32)hObject;
|
|
parms.hClass = (NvV32)hClass;
|
|
parms.index = (NvV32)index;
|
|
|
|
#ifdef NV20MINIX
|
|
parms.hEvent = (NvU64)hEvent;
|
|
#else
|
|
parms.hEvent.low = (NvV32)hEvent;
|
|
parms.hEvent.high = (NvV32)0;
|
|
#endif
|
|
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_EVENT,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS10_PARAMETERS));
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvFree(
|
|
ULONG hClient,
|
|
ULONG hParent,
|
|
ULONG hObject
|
|
)
|
|
{
|
|
NVOS00_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
parms.hRoot = (NvV32)hClient;
|
|
parms.hObjectParent = (NvV32)hParent;
|
|
parms.hObjectOld = (NvV32)hObject;
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_FREE,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS00_PARAMETERS));
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NvAllocMemory(
|
|
ULONG hClient,
|
|
ULONG hParent,
|
|
ULONG hMemory,
|
|
ULONG hClass,
|
|
ULONG flags,
|
|
PVOID *ppAddress,
|
|
ULONG *pLimit
|
|
)
|
|
{
|
|
NVOS02_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
|
|
// set input parameters
|
|
parms.hRoot = (NvV32)hClient;
|
|
parms.hObjectParent = (NvV32)hParent;
|
|
parms.hObjectNew = (NvV32)hMemory;
|
|
parms.hClass = (NvV32)hClass;
|
|
parms.flags = (NvV32)flags;
|
|
|
|
#ifdef NV20MINIX
|
|
parms.pMemory = (NvP64)*ppAddress;
|
|
parms.pLimit = (NvU64)*pLimit;
|
|
#else
|
|
parms.pMemory.selector = 0x00000000;
|
|
parms.pMemory.offset = (NvU32)*ppAddress;
|
|
parms.pLimit.high = 0x00000000;
|
|
parms.pLimit.low = (NvU32)*pLimit;
|
|
#endif
|
|
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV01_ALLOC_MEMORY,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS02_PARAMETERS));
|
|
|
|
#ifdef NV20MINIX
|
|
*ppAddress = (PVOID)((ULONG)parms.pMemory);
|
|
*pLimit = (ULONG)parms.pLimit;
|
|
#else
|
|
*ppAddress = (PVOID)parms.pMemory.offset;
|
|
*pLimit = (ULONG)parms.pLimit.low;
|
|
#endif
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
NvAllocChannelDma(
|
|
ULONG hClient,
|
|
ULONG hDevice,
|
|
ULONG hChannel,
|
|
ULONG hClass,
|
|
ULONG hErrorCtx,
|
|
ULONG hDataCtx,
|
|
ULONG offset,
|
|
PVOID *ppChannel
|
|
)
|
|
{
|
|
NVOS07_PARAMETERS parms;
|
|
PVOID pParms;
|
|
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
parms.hRoot = (NvV32)hClient;
|
|
parms.hObjectParent = (NvV32)hDevice;
|
|
parms.hObjectNew = (NvV32)hChannel;
|
|
parms.hClass = (NvV32)hClass;
|
|
parms.hObjectError = (NvV32)hErrorCtx;
|
|
parms.hObjectBuffer = (NvV32)hDataCtx;
|
|
parms.offset = (NvU32)offset;
|
|
pParms = &parms;
|
|
|
|
IOCTL_CMD((ULONG)IOCTL_NV03_ALLOC_CHANNEL_DMA,
|
|
(&pParms),
|
|
sizeof(PVOID),
|
|
(&parms),
|
|
sizeof(NVOS07_PARAMETERS));
|
|
|
|
#ifdef NV20MINIX
|
|
*ppChannel = (PVOID)((ULONG)parms.pControl);
|
|
#else
|
|
*ppChannel = (PVOID)parms.pControl.offset;
|
|
#endif
|
|
|
|
status = (parms.status == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LONG
|
|
MxAllocContextDma(
|
|
IN ULONG Dma,
|
|
IN ULONG Class,
|
|
IN ULONG Flags,
|
|
IN PVOID Base,
|
|
IN ULONG Limit
|
|
)
|
|
{
|
|
return NvAllocContextDma(MxDriverExtension->Client, Dma, Class, Flags, Base, Limit);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
MxCreateObjects(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Create objects
|
|
//
|
|
|
|
#if defined(NV20MINIX) && defined(KELVIN)
|
|
|
|
CHECKSTATUS(NvAllocObject(MxDriverExtension->Client,
|
|
NV_DD_DEV_DMA,
|
|
D3D_KELVIN_PRIMITIVE,
|
|
NV20_KELVIN_PRIMITIVE));
|
|
|
|
#else
|
|
|
|
CHECKSTATUS(NvAllocObject(MxDriverExtension->Client,
|
|
NV_DD_DEV_DMA,
|
|
D3D_CELSIUS_PRIMITIVE,
|
|
NV10_CELSIUS_PRIMITIVE));
|
|
|
|
CHECKSTATUS(NvAllocObject(MxDriverExtension->Client,
|
|
NV_DD_DEV_DMA,
|
|
D3D_RENDER_SOLID_RECTANGLE,
|
|
NV4_RENDER_SOLID_RECTANGLE));
|
|
|
|
#endif
|
|
|
|
CHECKSTATUS(NvAllocObject(MxDriverExtension->Client,
|
|
NV_DD_DEV_DMA,
|
|
NV_DD_SURFACES_2D,
|
|
NV10_CONTEXT_SURFACES_2D));
|
|
|
|
CHECKSTATUS(NvAllocObject(MxDriverExtension->Client,
|
|
NV_DD_DEV_DMA,
|
|
NV_DD_VIDEO_LUT_CURSOR_DAC,
|
|
NV05_VIDEO_LUT_CURSOR_DAC));
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
MxAllocContextDmas(
|
|
IN PMINIX_MODE_INFO ModeInfo,
|
|
IN PVOID VidMemAddress,
|
|
IN ULONG VidMemLength
|
|
)
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
DD_CONTEXT_DMA_IN_MEMORY_VIDEO_MEM,
|
|
NV01_CONTEXT_DMA,
|
|
NVOS03_FLAGS_ACCESS_READ_WRITE,
|
|
VidMemAddress,
|
|
VidMemLength));
|
|
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_CONTEXT_DMA_IN_VIDEO_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_RD_WR |
|
|
ALLOC_CTX_DMA_FLAGS_COHERENCY_UNCACHED),
|
|
VidMemAddress,
|
|
VidMemLength));
|
|
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_CONTEXT_DMA_FROM_VIDEO_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_READ_ONLY |
|
|
ALLOC_CTX_DMA_FLAGS_COHERENCY_UNCACHED),
|
|
VidMemAddress,
|
|
VidMemLength));
|
|
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_CONTEXT_DMA_TO_VIDEO_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_WRITE_ONLY |
|
|
ALLOC_CTX_DMA_FLAGS_COHERENCY_UNCACHED),
|
|
VidMemAddress,
|
|
VidMemLength));
|
|
|
|
//
|
|
// Create DMA contexts for notifications
|
|
//
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_PUSHER_SYNC_NOTIFIER_CONTEXT_DMA_TO_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
ALLOC_CTX_DMA_FLAGS_ACCESS_WRITE_ONLY,
|
|
(PVOID)ModeInfo->NotificationBase,
|
|
(2 * sizeof(NvNotification) - 1)) );
|
|
|
|
|
|
//
|
|
// Create DMA context for host memory
|
|
//
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
D3D_CONTEXT_DMA_HOST_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_READ_ONLY |
|
|
ALLOC_CTX_DMA_FLAGS_LOCKED_CACHED),
|
|
(PVOID)ModeInfo->HostMemoryBase,
|
|
ModeInfo->HostMemoryLimit));
|
|
|
|
|
|
//
|
|
// Allocate context DMA for the push buffer
|
|
//
|
|
|
|
#if defined(NV20MINIX) && defined(KELVIN)
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_PUSHER_CONTEXT_DMA_FROM_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_READ_ONLY |
|
|
ALLOC_CTX_DMA_FLAGS_LOCKED_CACHED),
|
|
(PVOID)ModeInfo->HostMemoryBase,
|
|
ModeInfo->HostMemoryLimit));
|
|
|
|
#else !KELVIN
|
|
|
|
CHECKSTATUS(NvAllocContextDma(MxDriverExtension->Client,
|
|
NV_DD_DMA_PUSHER_CONTEXT_DMA_FROM_MEMORY,
|
|
NV01_CONTEXT_DMA,
|
|
(ALLOC_CTX_DMA_FLAGS_ACCESS_READ_ONLY |
|
|
ALLOC_CTX_DMA_FLAGS_LOCKED_CACHED),
|
|
(PVOID)ModeInfo->PushBase,
|
|
ModeInfo->PushLimit));
|
|
|
|
#endif !KELVIN
|
|
|
|
CleanupAndExit:
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
MxSetVideoMode(
|
|
IN OUT PMINIX_MODE_INFO ModeInfo
|
|
)
|
|
{
|
|
ULONG BytesReturned;
|
|
NTSTATUS status;
|
|
|
|
ULONG Device;
|
|
ULONG DeviceReference;
|
|
|
|
VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange[16];
|
|
|
|
VIDEO_MEMORY VideoMemory;
|
|
VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
|
|
|
|
union
|
|
{
|
|
ULONG osName;
|
|
CHAR devName[128];
|
|
} NameBuffer;
|
|
|
|
|
|
ULONG Mode;
|
|
ULONG ModeIndex;
|
|
PVIDEOMODEDEF ModeDef;
|
|
|
|
BOOLEAN HwVidOvl;
|
|
|
|
VIDEO_MODE_INFORMATION VideoModeInfo;
|
|
TV_CURSOR_ADJUST_INFO CursorAdjustInfo;
|
|
|
|
PVOID VidMemAddress;
|
|
PVOID Temp;
|
|
ULONG VidMemLength;
|
|
ULONG VidMemHandle;
|
|
|
|
BOOLEAN FullInit;
|
|
|
|
|
|
Device = DD_DEVICE_OBJECT_HANDLE;
|
|
VidMemAddress = 0;
|
|
|
|
//
|
|
// Determine if we need to do full initialization
|
|
//
|
|
FullInit = (BOOLEAN)(ModeInfo->PushBase != 0);
|
|
|
|
|
|
|
|
if (FullInit) {
|
|
|
|
//
|
|
// Enable P6 write combining when mapping the video memory
|
|
//
|
|
IOCTL_CMD(IOCTL_VIDEO_ENABLE_WRITE_COMBINING,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
//
|
|
// Get the device reference from the miniport to the device class
|
|
//
|
|
IOCTL_CMD(IOCTL_VIDEO_GET_DEVICE_REF,
|
|
NULL,
|
|
0,
|
|
&DeviceReference,
|
|
sizeof(ULONG));
|
|
|
|
|
|
//
|
|
// Get virtual addresses for the memory ranges
|
|
//
|
|
IOCTL_CMD(IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
|
|
NULL,
|
|
0,
|
|
VideoAccessRange,
|
|
sizeof(VideoAccessRange));
|
|
|
|
|
|
//
|
|
// Get the linear memory address range for the video memory
|
|
//
|
|
VideoMemory.RequestedVirtualAddress = NULL;
|
|
|
|
IOCTL_CMD(IOCTL_VIDEO_MAP_VIDEO_MEMORY,
|
|
&VideoMemory,
|
|
sizeof(VIDEO_MEMORY),
|
|
&VideoMemoryInfo,
|
|
sizeof(VideoMemoryInfo));
|
|
|
|
VidMemAddress = VideoMemoryInfo.FrameBufferBase;
|
|
|
|
//
|
|
// Register the client
|
|
//
|
|
CHECKSTATUS(NvAllocRoot(NV01_ROOT, &(MxDriverExtension->Client)));
|
|
|
|
//
|
|
// Allocate the device
|
|
//
|
|
NameBuffer.osName = DeviceReference;
|
|
|
|
CHECKSTATUS(NvAllocDevice(MxDriverExtension->Client, Device, NV03_DEVICE_XX, NameBuffer.devName));
|
|
}
|
|
|
|
//
|
|
// Set the video mode
|
|
//
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
ModeDef = &g_VideoModeDef[0];
|
|
for (ModeIndex = 0; ModeIndex < (sizeof(g_VideoModeDef) / sizeof(g_VideoModeDef[0]));
|
|
ModeIndex++) {
|
|
|
|
if (ModeInfo->Width == ModeDef->Width &&
|
|
ModeInfo->Height == ModeDef->Height &&
|
|
ModeInfo->BitDepth == ModeDef->Depth) {
|
|
|
|
Mode = ModeDef->Mode;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
ModeDef++;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
goto CleanupAndExit;
|
|
}
|
|
|
|
|
|
IOCTL_CMD(IOCTL_VIDEO_SET_CURRENT_MODE,
|
|
&Mode,
|
|
sizeof(ULONG),
|
|
&HwVidOvl,
|
|
sizeof(BOOLEAN));
|
|
|
|
|
|
//
|
|
// Get video mode information
|
|
//
|
|
IOCTL_CMD(IOCTL_VIDEO_QUERY_CURRENT_MODE,
|
|
NULL,
|
|
0,
|
|
&VideoModeInfo,
|
|
sizeof(VideoModeInfo));
|
|
|
|
|
|
//
|
|
// Get cursor adjust information
|
|
//
|
|
IOCTL_CMD(IOCTL_VIDEO_GET_TV_CURSOR_ADJUST_INFO,
|
|
NULL,
|
|
0,
|
|
&CursorAdjustInfo,
|
|
sizeof(CursorAdjustInfo));
|
|
|
|
|
|
if (FullInit) {
|
|
|
|
//
|
|
// Get the size for video memory from RM
|
|
//
|
|
Temp = (PVOID)1; // NO_MAPPING
|
|
VidMemHandle = DD_FRAME_BUFFER_OBJECT_HANDLE;
|
|
CHECKSTATUS(NvAllocMemory(MxDriverExtension->Client, Device, VidMemHandle, NV01_MEMORY_LOCAL_USER, 0,
|
|
&Temp, &VidMemLength));
|
|
|
|
|
|
//
|
|
// Return the video memory address
|
|
//
|
|
ModeInfo->VidMemAddress = VidMemAddress;
|
|
|
|
//
|
|
// Return the base address of the hardware.
|
|
//
|
|
ModeInfo->NvBase = VideoAccessRange[0].VirtualAddress;
|
|
|
|
// BUGBUG: testcode: clear memory
|
|
memset((PVOID)((unsigned char*)VidMemAddress), 0xFF, VidMemLength);
|
|
// end test code
|
|
|
|
|
|
//
|
|
// Allocate DMA contexts to video memory.
|
|
//
|
|
|
|
CHECKSTATUS(MxAllocContextDmas(ModeInfo, VidMemAddress, VidMemLength));
|
|
|
|
//
|
|
// Allocate channel DMA for the push buffer
|
|
//
|
|
|
|
#if defined(NV20MINIX) && defined(KELVIN)
|
|
|
|
CHECKSTATUS(NvAllocChannelDma(MxDriverExtension->Client,
|
|
Device,
|
|
NV_DD_DEV_DMA,
|
|
NV20_CHANNEL_DMA,
|
|
0,
|
|
NV_DD_DMA_PUSHER_CONTEXT_DMA_FROM_MEMORY,
|
|
0,
|
|
(PVOID*)&(ModeInfo->DevFlatDma)));
|
|
#else
|
|
|
|
CHECKSTATUS(NvAllocChannelDma(MxDriverExtension->Client,
|
|
Device,
|
|
NV_DD_DEV_DMA,
|
|
NV10_CHANNEL_DMA,
|
|
0,
|
|
NV_DD_DMA_PUSHER_CONTEXT_DMA_FROM_MEMORY,
|
|
0,
|
|
(PVOID*)&(ModeInfo->DevFlatDma)));
|
|
#endif
|
|
|
|
//
|
|
// Create objects
|
|
//
|
|
|
|
CHECKSTATUS(MxCreateObjects());
|
|
}
|
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
CleanupAndExit:
|
|
|
|
return (LONG)status;
|
|
}
|
|
|
|
|