📄 wncandevio.c
字号:
/* wncanDevIO.c - implementation of WIND NET CAN Device I/O Interface */
/* Copyright 2002-2003 Wind River Systems, Inc. */
/*
modification history
--------------------
01d,11may05,lsg Fix in macro checks for malloc definition
01c,21apr04,bjn Added WNCAN_REG_SET and WNCAN_REG_GET.
01b,21feb03,rgp finished
01a,19dec02,emcw created
*/
/*
DESCRIPTION
This file contains the functions that implement the DevIO interface defined
in the wncanDevIO.h header file.
*/
/* log message debugging */
#define DEVIO_DEBUG 0
/* includes */
#include <vxWorks.h>
#include <stdlib.h>
#include <errnoLib.h>
#include <string.h>
#include <stdio.h>
#include <CAN/wnCAN.h>
#include <CAN/wncanDevIO.h>
#include <intLib.h>
#ifndef _WRS_VXWORKS_5_X
#include <memLib.h>
#include <memPartLib.h>
#endif
#if DEVIO_DEBUG
#include <logLib.h>
#include <private/selectLibP.h>
#endif
/* global variables */
/* local variables */
LOCAL int wncDevIODrvNum = 0; /* driver number assigned to this driver */
LOCAL int wncDevDrvInstance = 0; /* # times wncDevIODevCreate() called */
/* local prototypes */
LOCAL int wncUtilCalcRingBufSize(int numCanMsgs);
LOCAL STATUS wncUtilIoctlFioCmds(WNCAN_DEVIO_FDINFO*,int,int);
LOCAL STATUS wncUtilIoctlDeviceFioCmds(WNCAN_DEVIO_FDINFO*,int,int);
LOCAL STATUS wncUtilIoctlChannelCmds(WNCAN_DEVIO_FDINFO*,int,int);
LOCAL STATUS wncUtilIoctlCtlrCmds(WNCAN_DEVIO_FDINFO*,int,int);
LOCAL STATUS wncUtilIoctlDeviceCmds(WNCAN_DEVIO_FDINFO*,int,int);
LOCAL void wncDevIOIsrHandler(struct WNCAN_Device*,WNCAN_IntType,UCHAR);
/* memory allocation for 5.5 and AE are different */
#ifdef _WRS_KERNEL
#define WNCDEV_MALLOC(s) malloc(s)
#define WNCDEV_FREE(s) free(s)
#endif
#ifndef _WRS_KERNEL
#ifdef _WRS_VXWORKS_5_X
#define WNCDEV_MALLOC(s) malloc(s)
#define WNCDEV_FREE(s) free(s)
#else
#define WNCDEV_MALLOC(s) KHEAP_ALIGNED_ALLOC(s, 4)
#define WNCDEV_FREE(s) KHEAP_FREE(s)
#endif
#endif
/* define helper macros to access the device's info struct
** which we store within the WNC's device structure
**/
#define WNCDEV_PUT_DEVICEINFO(pDev, pInfo) \
(pDev)->userData = (void*)pInfo
#define WNCDEV_GET_DEVICEINFO(pDev) \
((WNCAN_DEVIO_FDINFO*)((pDev)->userData))
#define WNCDRV_PUT_DEVICEINFO(pDrv, pInfo) \
WNCDEV_PUT_DEVICEINFO(pDrv->wncDevice, pInfo)
#define WNCDRV_GET_DEVICEINFO(pDrv) \
WNCDEV_GET_DEVICEINFO(pDrv->wncDevice)
/************************************************************************
*
* wncDevIODrvInstall - install the DevIO interface driver
*
* This routine installs the DevIO interface driver into the VxWorks I/O system.
*
* This routine should be called exactly once, before any reads, writes, or calls
* to wncDevIODevCreate(). Normally, it is called by usrRoot() in usrConfig.c.
*
* RETURNS: OK or ERROR if the driver cannot be installed
*
* ERRNO: N/A
*
*/
STATUS wncDevIODrvInstall(void)
{
/* Check whether driver is already installed */
if (wncDevIODrvNum > 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODrvInstall() OK: DevIO driver already installed\n",
0,0,0,0,0,0);
#endif
return OK;
}
/*
VxWorks startup code takes care of creation, and VxWorks shutdown
code takes care of destruction. Don't need creat() and delete()
functions here.
*/
#if DEVIO_DEBUG
wncDevIODrvNum = iosDrvInstall (wncDevIOCreate, wncDevIODelete, wncDevIOOpen,
wncDevIOClose, wncDevIOReadBuf, wncDevIOWriteBuf,
wncDevIOIoctl);
#else
wncDevIODrvNum = iosDrvInstall ((FUNCPTR) NULL, (FUNCPTR) NULL, wncDevIOOpen,
wncDevIOClose, wncDevIOReadBuf, wncDevIOWriteBuf,
wncDevIOIoctl);
#endif
return (wncDevIODrvNum == ERROR ? ERROR : OK);
}
/************************************************************************
*
* wncDevIODrvRemove - remove the DevIO interface driver
*
* This routine removes the DevIO interface driver from the VxWorks I/O system.
*
* RETURNS: OK or ERROR
*
* ERRNO: N/A
*
*/
STATUS wncDevIODrvRemove(void)
{
STATUS status;
/* Check whether driver is already removed */
if (wncDevIODrvNum == 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODrvRemove() OK: DevIO driver already removed\n",
0,0,0,0,0,0);
#endif
return OK;
}
/* Check whether other instances of driver need to be removed */
if (wncDevDrvInstance > 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODrvRemove() ERROR: Still have DevIO driver instances in use\n",
0,0,0,0,0,0);
#endif
return ERROR;
}
/* Delete driver entry from VxWorks I/O system */
status = iosDrvRemove (wncDevIODrvNum, TRUE);
if (status == OK)
wncDevIODrvNum = 0;
return (status);
}
/************************************************************************
*
* wncDevIODevCreate - device creation routine
*
* This routine creates an instance of the DevIO driver for the specified
* device name and adds it to the VxWorks I/O System
*
* RETURNS: OK or ERROR
*
* ERRNO: S_ioLib_NO_DRIVER
* S_can_invalid_parameter
* S_can_out_of_memory
*/
STATUS wncDevIODevCreate
(
char *name, /* device name */
int boardtype, /* WNC board type */
int boardindex, /* board index */
int ctlrindex, /* controller number */
WNCAN_DEVIO_DRVINFO **pwncDrv /* pointer to driver descriptor */
)
{
STATUS status = OK;
char ctlrName[WNCAN_LG_BUF_SIZE];
char *pCtlrName = ctlrName;
/* Check for errors */
if (wncDevIODrvNum <= 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevCreate() ERROR: Invalid wncDevIODrvNum\n", 0,0,0,0,0,0);
#endif
errnoSet (S_ioLib_NO_DRIVER);
return ERROR;
}
if (name == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevCreate() ERROR: device name not specified\n", 0,0,0,0,0,0);
#endif
errnoSet (S_can_invalid_parameter);
return ERROR;
}
/* convert to device name "board/controller" */
{
int namelen = strlen(name)+2; /* add trailing '/' and nul */
int idx = ctlrindex;
/* account for controller number (one for each digit)
** (i.e. namelen += (log10(ctlrindex)+1) )
*/
for(namelen +=1; idx>=10; idx /= 10, namelen++) ;
if (namelen > WNCAN_LG_BUF_SIZE)
{
pCtlrName = (char*)WNCDEV_MALLOC(namelen+1);
if (pCtlrName == NULL)
{
errnoSet (S_can_out_of_memory);
status = ERROR;
}
}
}
if (status == OK)
{
WNCAN_DEVIO_DRVINFO *wncDrv;
/* create the device name */
sprintf(pCtlrName, "%s/%d", name, ctlrindex);
/* Initialize DevIO struct */
wncDrv = (WNCAN_DEVIO_DRVINFO *) WNCDEV_MALLOC(sizeof(WNCAN_DEVIO_DRVINFO));
if (wncDrv == NULL)
{
errnoSet (S_can_out_of_memory);
status = ERROR;
}
else
{
wncDrv->boardType = boardtype;
wncDrv->boardIdx = boardindex;
wncDrv->ctlrIdx = ctlrindex;
wncDrv->numOpenChans = 0;
wncDrv->isDeviceOpen = FALSE;
wncDrv->wncDevice = NULL;
wncDrv->ctrlSetConfig = NULL;
wncDrv->ctrlGetConfig = NULL;
/* create device mutex */
wncDrv->mutex = semBCreate(SEM_Q_PRIORITY, SEM_FULL);
if (wncDrv->mutex == NULL)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevCreate() ERROR: failed to create semaphore\n",
0,0,0,0,0,0);
#endif
status = ERROR;
}
else
{
/* Add device to VxWorks I/O System and associate with DevIO driver */
status = iosDevAdd (&(wncDrv->devHdr), pCtlrName, wncDevIODrvNum);
}
if (status == OK)
{
wncDevDrvInstance++;
if (pwncDrv) /* pass back to use the dev pointer */
*pwncDrv = wncDrv;
}
else
{ /* error, clean up allocated memory */
WNCDEV_FREE((char*)wncDrv);
}
}
}
/* clean-up locally allocated memory, if needed */
if (pCtlrName != ctlrName)
WNCDEV_FREE((char*)pCtlrName);
return status;
}
/************************************************************************
*
* wncDevIODevDestroy - device destroy routine
*
* This routine destroys an instance of the DevIO driver for the specified
* driver descriptor and removes it from the VxWorks I/O System. The user
* must ensure that any open channels and the CAN device must be closed before
* calling this routine.
*
* RETURNS: OK or ERROR
*
* ERRNO: S_ioLib_NO_DRIVER, S_ioLib_DEVICE_ERROR, S_iosLib_DEVICE_NOT_FOUND
*
*/
STATUS wncDevIODevDestroy
(
WNCAN_DEVIO_DRVINFO* wncDrv /* pointer to driver descriptor */
)
{
/* Check for installed DevIO driver */
if (wncDevIODrvNum <= 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevDestroy() ERROR: Invalid wncDevIODrvNum\n", 0,0,0,0,0,0);
#endif
errnoSet (S_ioLib_NO_DRIVER);
return ERROR;
}
/* Check if at least one instance of the driver is installed */
if (wncDevDrvInstance == 0)
{
errnoSet (S_iosLib_DEVICE_NOT_FOUND);
return ERROR;
}
/* Ensure that all CAN channels are closed */
if (wncDrv->numOpenChans > 0)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevDestroy() ERROR: CAN device still has open channels\n",
0,0,0,0,0,0);
#endif
errnoSet (S_ioLib_DEVICE_ERROR);
return ERROR;
}
/* Ensure that the CAN device is closed */
if (wncDrv->isDeviceOpen)
{
#if DEVIO_DEBUG
logMsg("wncDevIODevDestroy() ERROR: CAN device still open\n",
0,0,0,0,0,0);
#endif
errnoSet (S_ioLib_DEVICE_ERROR);
return ERROR;
}
/* Delete DevIO driver from I/O System */
iosDevDelete (&wncDrv->devHdr);
/* Free DevIO driver struct resources */
wncDrv->boardType = 0;
wncDrv->boardIdx = 0;
wncDrv->ctlrIdx = 0;
semDelete(wncDrv->mutex);
wncDrv->wncDevice = NULL;
WNCDEV_FREE((char*)wncDrv);
wncDrv = NULL;
wncDevDrvInstance--;
return OK;
}
#if DEVIO_DEBUG
/************************************************************************
*
* wncDevIOCreate - device create routine
*
* This routine is only for debugging purposes to test the VxWorks I/O System
*
* RETURNS: OK or ERROR
*
* ERRNO: N/A
*
*/
int wncDevIOCreate
(
WNCAN_DEVIO_DRVINFO* wncDev, /* pointer to device descriptor */
char* name, /* device or channel name */
int mode /* not used */
)
{
/* Debugging only */
logMsg("wncDevIOCreate() called\n", 0,0,0,0,0,0);
return OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -