Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

494 lines
12 KiB

/***************************************************************************\
*
* ************************
* * MINIPORT SAMPLE CODE *
* ************************
*
* Module Name:
*
* i2c.c
*
* Abstract:
*
* This module contains the code that implements the i2c interface feature
*
*
* Environment:
*
* Kernel mode
*
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All Rights Reserved.
*
\***************************************************************************/
#include "perm3.h"
#include "i2c.h"
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,GetCookie)
#pragma alloc_text(PAGE,I2CBusOpenCRT)
#pragma alloc_text(PAGE,I2CBusOpenDFP)
#pragma alloc_text(PAGE,I2CBusOpen)
#pragma alloc_text(PAGE,I2CBusAccessCRT)
#pragma alloc_text(PAGE,I2CBusAccessDFP)
#pragma alloc_text(PAGE,I2CBusAccess)
#pragma alloc_text(PAGE,I2CNull)
#pragma alloc_text(PAGE,I2CRead)
#pragma alloc_text(PAGE,I2CWrite)
#pragma alloc_text(PAGE,I2CStart)
#pragma alloc_text(PAGE,I2CStop)
#pragma alloc_text(PAGE,InterfaceReference)
#pragma alloc_text(PAGE,InterfaceDereference)
#pragma alloc_text(PAGE,Perm3QueryInterface)
#endif
VIDEO_I2C_CONTROL
I2CCallbacksCRT = {
I2CWriteClock,
I2CWriteData,
I2CReadClock,
I2CReadData,
0
};
VIDEO_I2C_CONTROL
I2CCallbacksDFP = {
I2CWriteClockDFP,
I2CWriteDataDFP,
I2CReadClockDFP,
I2CReadDataDFP,
0
};
BOOLEAN
GetCookie(
PVOID DeviceObject,
PULONG Cookie
)
{
*Cookie = 0x12345678;
return TRUE;
}
VP_STATUS
I2CBusOpenCRT(
PVOID DeviceObject,
BOOLEAN bOpen,
PI2CControl I2CControl
)
{
return I2CBusOpen(DeviceObject, bOpen, I2CControl, &I2CCallbacksCRT);
}
VP_STATUS
I2CBusOpenDFP(
PVOID DeviceObject,
BOOLEAN bOpen,
PI2CControl I2CControl
)
{
return I2CBusOpen(DeviceObject, bOpen, I2CControl, &I2CCallbacksDFP);
}
VP_STATUS
I2CBusOpen(
PVOID DeviceObject,
BOOLEAN bOpen,
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks
)
{
PHW_DEVICE_EXTENSION hwDeviceExtension;
VP_STATUS Status = STATUS_UNSUCCESSFUL;
hwDeviceExtension = VideoPortGetAssociatedDeviceExtension(DeviceObject);
VideoPortAcquireDeviceLock(hwDeviceExtension);
I2CControl->Status = I2C_STATUS_NOERROR;
if (bOpen) {
if (I2CControl->ClockRate > MAX_CLOCK_RATE) {
I2CControl->ClockRate = MAX_CLOCK_RATE;
}
I2CCallbacks->I2CDelay = (MAX_CLOCK_RATE / I2CControl->ClockRate) * 10;
if (GetCookie(DeviceObject, &I2CControl->dwCookie)) {
Status = STATUS_SUCCESS;
}
} else {
I2CControl->dwCookie = 0;
Status = STATUS_SUCCESS;
}
VideoPortReleaseDeviceLock(hwDeviceExtension);
return Status;
}
VP_STATUS
I2CBusAccessCRT(
PVOID DeviceObject,
PI2CControl I2CControl
)
{
return I2CBusAccess(DeviceObject, I2CControl, &I2CCallbacksCRT);
}
VP_STATUS
I2CBusAccessDFP(
PVOID DeviceObject,
PI2CControl I2CControl
)
{
return I2CBusAccess(DeviceObject, I2CControl, &I2CCallbacksDFP);
}
VP_STATUS
I2CBusAccess(
PVOID DeviceObject,
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks
)
{
PHW_DEVICE_EXTENSION hwDeviceExtension;
VP_STATUS Status = STATUS_UNSUCCESSFUL;
hwDeviceExtension = VideoPortGetAssociatedDeviceExtension(DeviceObject);
VideoPortAcquireDeviceLock(hwDeviceExtension);
I2CControl->Status = I2C_STATUS_NOERROR;
if (I2CControl->ClockRate > MAX_CLOCK_RATE) {
I2CControl->ClockRate = MAX_CLOCK_RATE;
}
I2CCallbacks->I2CDelay = (MAX_CLOCK_RATE / I2CControl->ClockRate) * 10;
switch(I2CControl->Command) {
case I2C_COMMAND_NULL:
I2CNull(I2CControl, I2CCallbacks, hwDeviceExtension);
break;
case I2C_COMMAND_READ:
I2CRead(I2CControl, I2CCallbacks, hwDeviceExtension);
break;
case I2C_COMMAND_WRITE:
I2CWrite(I2CControl, I2CCallbacks, hwDeviceExtension);
break;
case I2C_COMMAND_RESET:
//
// A reset is just a stop.
//
I2CStop(I2CControl, I2CCallbacks, hwDeviceExtension);
break;
case I2C_COMMAND_STATUS:
break;
default:
I2CControl->Status = I2C_STATUS_ERROR;
}
VideoPortReleaseDeviceLock(hwDeviceExtension);
return I2CControl->Status;
}
ULONG
I2CNull(
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks,
PHW_DEVICE_EXTENSION hwDeviceExtension
)
{
I2CControl->Status = I2C_STATUS_NOERROR;
if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
if (I2CControl->Flags & I2C_FLAGS_START) {
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
if (I2CControl->Flags & I2C_FLAGS_STOP) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
}
return I2CControl->Status;
}
ULONG
I2CRead(
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks,
PHW_DEVICE_EXTENSION hwDeviceExtension
)
{
BOOLEAN Result;
I2CControl->Status = I2C_STATUS_NOERROR;
if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
if (I2CControl->Flags & I2C_FLAGS_START) {
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
Result = hwDeviceExtension->I2CInterface.I2CRead(
hwDeviceExtension,
I2CCallbacks,
&I2CControl->Data,
1,
(I2CControl->Flags & I2C_FLAGS_ACK) ? FALSE : TRUE);
if (Result == TRUE) {
I2CControl->Status = I2C_STATUS_NOERROR;
} else {
I2CControl->Status = I2C_STATUS_ERROR;
}
if (I2CControl->Flags & I2C_FLAGS_STOP) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
}
return I2CControl->Status;
}
ULONG
I2CWrite(
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks,
PHW_DEVICE_EXTENSION hwDeviceExtension
)
{
BOOLEAN Result;
I2CControl->Status = I2C_STATUS_NOERROR;
if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
if (I2CControl->Flags & I2C_FLAGS_START) {
hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
}
Result = hwDeviceExtension->I2CInterface.I2CWrite(
hwDeviceExtension,
I2CCallbacks,
&I2CControl->Data,
1);
if (Result == TRUE) {
I2CControl->Status = I2C_STATUS_NOERROR;
} else {
I2CControl->Status = I2C_STATUS_ERROR;
}
if (I2CControl->Flags & I2C_FLAGS_STOP) {
hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
}
return I2CControl->Status;
}
ULONG
I2CStop(
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks,
PHW_DEVICE_EXTENSION hwDeviceExtension
)
{
BOOLEAN Result;
Result = hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
if (Result == TRUE) {
I2CControl->Status = I2C_STATUS_NOERROR;
} else {
I2CControl->Status = I2C_STATUS_ERROR;
}
return I2CControl->Status;
}
ULONG
I2CStart(
PI2CControl I2CControl,
PVIDEO_I2C_CONTROL I2CCallbacks,
PHW_DEVICE_EXTENSION hwDeviceExtension
)
{
BOOLEAN Result;
Result = hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
if (Result == TRUE) {
I2CControl->Status = I2C_STATUS_NOERROR;
} else {
I2CControl->Status = I2C_STATUS_ERROR;
}
return I2CControl->Status;
}
VOID
InterfaceReference(
IN PVOID pContext
)
{
return;
}
VOID
InterfaceDereference(
IN PVOID pContext
)
{
return;
}
VP_STATUS
Perm3QueryInterface(
PVOID HwDeviceExtension,
PQUERY_INTERFACE pQueryInterface
)
{
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
VP_STATUS Status;
ULONG HwID;
if (IsEqualGUID(pQueryInterface->InterfaceType, &GUID_I2C_INTERFACE)) {
I2CINTERFACE *Interface = (I2CINTERFACE *)pQueryInterface->Interface;
if ((pQueryInterface->Size == sizeof(I2CINTERFACE)) &&
(pQueryInterface->Version == 2))
{
//
// Get interface pointers for i2c interface help functions
//
if (hwDeviceExtension->I2CInterfaceAcquired == FALSE) {
hwDeviceExtension->I2CInterface.Size = sizeof(VIDEO_PORT_I2C_INTERFACE_2);
hwDeviceExtension->I2CInterface.Version = VIDEO_PORT_I2C_INTERFACE_VERSION_2;
Status = VideoPortQueryServices(
hwDeviceExtension,
VideoPortServicesI2C,
(PINTERFACE)&hwDeviceExtension->I2CInterface);
if (Status != NO_ERROR) {
VideoDebugPrint((1, "Perm3QueryInterface: Failed to acquire I2C services\n"));
return Status;
}
hwDeviceExtension->I2CInterfaceAcquired = TRUE;
}
if (((ULONG_PTR)pQueryInterface->InterfaceSpecificData != 0) &&
((ULONG_PTR)pQueryInterface->InterfaceSpecificData != -1)) {
//
// Get the HwID for the child requesting this interface
//
HwID = VideoPortGetAssociatedDeviceID(
pQueryInterface->InterfaceSpecificData);
} else {
if (hwDeviceExtension->Perm3Capabilities & PERM3_DFP_MON_ATTACHED) {
HwID = PERM3_DFP_MONITOR;
} else {
HwID = PERM3_DDC_MONITOR;
}
}
//
// Initialize the interface
//
Interface->_vddInterface.Size = sizeof(I2CINTERFACE);
Interface->_vddInterface.Version = 2;
Interface->_vddInterface.Context = HwDeviceExtension;
Interface->_vddInterface.InterfaceReference = InterfaceReference;
Interface->_vddInterface.InterfaceDereference = InterfaceDereference;
if (HwID == PERM3_DDC_MONITOR) {
Interface->i2cOpen = I2CBusOpenCRT;
Interface->i2cAccess = I2CBusAccessCRT;
} else if (HwID == PERM3_DFP_MONITOR) {
Interface->i2cOpen = I2CBusOpenDFP;
Interface->i2cAccess = I2CBusAccessDFP;
}
//
// Reference the interface before handing it out
//
Interface->_vddInterface.InterfaceReference(Interface->_vddInterface.Context);
Status = NO_ERROR;
} else {
VideoDebugPrint((1, "Perm3QueryInterface: Size or version incorrect\n"));
Status = ERROR_INVALID_PARAMETER;
}
} else {
VideoDebugPrint((1, "Perm3QueryInteface: Unsupported Interface\n"));
Status = ERROR_INVALID_PARAMETER;
}
VideoDebugPrint((1, "Perm3QueryInterface: Status = 0x%x\n", Status));
return Status;
}