#include <platform.h>
#include <bceddk.h>
#include "i2c.h"
#include "sio.h"
#ifdef DEBUG
#define ZONE_INIT DEBUGZONE(0)
#define ZONE_CLOCKS DEBUGZONE(1)
#define ZONE_GPIOS DEBUGZONE(2)
#define ZONE_IOCTL DEBUGZONE(3)
#define ZONE_FUNC DEBUGZONE(4)
#define ZONE_WARNING DEBUGZONE(14)
#define ZONE_ERROR DEBUGZONE(15)
DBGPARAM dpCurSettings = {
TEXT("Ohcd"), {
TEXT("Init"), TEXT("Clocks"), TEXT("Gpios"), TEXT("IOCTLs"),
TEXT("-"), TEXT("-"), TEXT("-"), TEXT("-"),
TEXT("-"), TEXT("-"), TEXT("-"),TEXT("-"),
TEXT("Alloc"), TEXT(""),TEXT("Warnings"), TEXT("Errors")},
0xffff};
#else
#if 0
#undef DEBUGMSG
#define DEBUGMSG(x,y) RETAILMSG(x,y)
#define ZONE_INIT (1)
#define ZONE_CLOCKS (1)
#define ZONE_GPIOS (1)
#define ZONE_IOCTL (1)
#define ZONE_FUNC (1)
#define ZONE_WARNING (1)
#define ZONE_ERROR (1)
#endif
#endif
/*
* IOCTLS used to access the driver
*/
enum {
IOCTL_I2C_READDATA = 0x80002000, /* some arbirary base */
IOCTL_I2C_WRITEDATA
};
/*
* Structure for storing device instance data.
*/
typedef struct _DEVICE_INSTANCE {
long OpenCount; /* Number of open handles */
CRITICAL_SECTION ControlMutex; /* Access control */
} DEVICE_INSTANCE, *PDEVICE_INSTANCE;
/*******************************************************************************
**************** Static Functions of I2C Read/Write ****************
******************************************************************************/
static
BOOL ReadData(
PDEVICE_INSTANCE DeviceInstance,
I2C_TRANSFER *pTransfer,
PUCHAR pData
)
{
BOOL status = TRUE;
DEBUGMSG(ZONE_FUNC,(TEXT("I2C ReadData: Addr:%02x Register:%02x\r\n"),
pTransfer->Address, pTransfer->Register));
EnterCriticalSection(&DeviceInstance->ControlMutex);
if (!SIO_Read(pTransfer->Address, pTransfer->Register,
pData, pTransfer->DataSize))
{
RETAILMSG(1, (TEXT("GPIO_I2C: ReadData failed\r\n")));
status = FALSE;
}
LeaveCriticalSection(&DeviceInstance->ControlMutex);
return status;
}
static
BOOL WriteData(
PDEVICE_INSTANCE DeviceInstance,
I2C_TRANSFER *pTransfer
)
{
BOOL status = TRUE;
EnterCriticalSection(&DeviceInstance->ControlMutex);
if (!SIO_Write(pTransfer->Address, pTransfer->Register,
&pTransfer->DataBuffer[0], pTransfer->DataSize))
{
RETAILMSG(1, (TEXT("GPIO_I2C: WriteData failed\r\n")));
status = FALSE;
}
LeaveCriticalSection(&DeviceInstance->ControlMutex);
return status;
}
/*******************************************************************************
***************************** Exported Routines *******************************
******************************************************************************/
BOOL WINAPI DllMain(
IN HANDLE Instance,
IN DWORD Reason,
IN PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER(NULL);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
default:
break;
}
return TRUE;
}
BOOL I2C_Deinit(
IN OUT ULONG DeviceContext
)
{
PDEVICE_INSTANCE DeviceInstance;
DeviceInstance = (PDEVICE_INSTANCE)DeviceContext;
DEBUGMSG(ZONE_INIT, (
TEXT("GPIO_I2C: I2C_Deinit(0x%x) entered.\r\n"),
DeviceContext));
if ((DeviceInstance->OpenCount != 0))
{
DEBUGMSG((ZONE_INIT|ZONE_ERROR),
(TEXT("GPIO_I2C: Handles still open. Shutting down anyway.\r\n")));
}
/* Close the handle to the mutex protecting the device's control shadow.
*/
DeleteCriticalSection(&DeviceInstance->ControlMutex);
/* Finally, the device instance itself can be freed.
*/
LocalFree(DeviceInstance);
DEBUGMSG(ZONE_INIT, (TEXT("GPIO_I2C: I2C_Deinit returning TRUE.\r\n")));
return TRUE;
}
ULONG
I2C_Init(
IN ULONG RegistryPath
)
{
PDEVICE_INSTANCE DeviceInstance;
DEBUGMSG(ZONE_INIT,
(TEXT("GPIO_I2C: I2C_Init(0x%x) entered.\r\n"),RegistryPath));
/*
* Allocate a structure to hold the state for this instance. This value
* is used as a handle and is returned by this routine. When I2C_Open or
* I2C_Close is called, this handle will be passed in as a parameter.
*/
DeviceInstance = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
sizeof(*DeviceInstance));
if (DeviceInstance == NULL)
{
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("GPIO_I2C: Failed to allocate device instance.\r\n")));
goto ErrorReturn;
}
/* Initialize the mutex to protect the device's Control register's shadow.
*/
InitializeCriticalSection(&DeviceInstance->ControlMutex);
return (ULONG)DeviceInstance;
ErrorReturn:
if (DeviceInstance == NULL)
{
DEBUGMSG((ZONE_INIT|ZONE_ERROR), (TEXT("GPIO_I2C: I2C_Init failed.\r\n")));
}
return (ULONG)DeviceInstance;
}
ULONG I2C_Open(
IN OUT ULONG DeviceContext,
IN ULONG AccessCode,
IN ULONG ShareMode
)
{
PDEVICE_INSTANCE DeviceInstance;
DeviceInstance = (PDEVICE_INSTANCE)DeviceContext;
DEBUGMSG(ZONE_FUNC,
(TEXT("GPIO_I2C: I2C_Open(0x%x, 0x%x, 0x%x) entered.\r\n"),
DeviceContext,
AccessCode,
ShareMode));
DeviceInstance->OpenCount++;
DEBUGMSG(ZONE_FUNC, (TEXT("GPIO_I2C: I2C_Open returning 0x%x.\r\n"),
DeviceContext));
return (ULONG)DeviceContext;
}
BOOL
I2C_Close(
IN OUT ULONG DeviceContext
)
{
PDEVICE_INSTANCE DeviceInstance;
DeviceInstance = (PDEVICE_INSTANCE)DeviceContext;
DEBUGMSG(ZONE_FUNC, (TEXT("GPIO_I2C: I2C_Close(0x%x) entered.\r\n"),
DeviceInstance));
/*
* Reset the open count that is stored in the device instance. This
* releases the device for others to call CreateFile on the stream.
*/
DeviceInstance->OpenCount--;
DEBUGMSG(ZONE_FUNC, (TEXT("GPIO_I2C: I2C_Close returning TRUE.\r\n")));
return TRUE;
}
ULONG
I2C_Read(
IN OUT ULONG DeviceContext,
IN PUCHAR ReadBuffer,
IN ULONG Count
)
{
return 0;
}
ULONG
I2C_Write(
IN OUT ULONG OpenContext,
IN PUCHAR Source,
IN ULONG Count
)
{
UNREFERENCED_PARAMETER(OpenContext);
UNREFERENCED_PARAMETER(Source);
UNREFERENCED_PARAMETER(Count);
return 0;
}
ULONG
I2C_Seek(
IN OUT ULONG OpenContext,
IN LONG Amount,
IN USHORT Type
)
{
UNREFERENCED_PARAMETER(OpenContext);
UNREFERENCED_PARAMETER(Amount);
UNREFERENCED_PARAMETER(Type);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return -1;
}
BOOL
I2C_IOControl(
IN OUT ULONG DeviceContext,
IN ULONG Code,
IN PUCHAR InputBuffer,
IN ULONG InputBufferLength,
OUT PUCHAR OutputBuffer,
IN ULONG OutputBufferLength,
OUT PULONG ActualOutput
)
{
PDEVICE_INSTANCE DeviceInstance = (PDEVICE_INSTANCE)DeviceContext;
BOOL Status = FALSE;
I2C_TRANSFER *pTransfer = (I2C_TRANSFER*)InputBuffer;
DEBUGMSG(ZONE_IOCTL,
(TEXT("GPIO_I2C: I2C_IOControl(0x%x, 0x%x, 0x%x, %u, 0x%x,")
TEXT(" %u, 0x%x) entered.\r\n"),
DeviceContext,
Code,
InputBuffer,
Inpu