347 lines
7.0 KiB
C
347 lines
7.0 KiB
C
/* msmcan.c - implementation of Board Interface for MSM CAN PC104 */
|
|
|
|
/* Copyright 2001, 2013 Wind River Systems, Inc. */
|
|
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01b,09sep13,xms fix CHECKED_RETURN error. (WIND00414265)
|
|
01a,03sep04,??? set default baud rate to 125 Kbps
|
|
14dec01,dnb written
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
DESCRIPTION
|
|
This file contains the functions that provide a board-level interface
|
|
to the MSM CAN PC104 card.
|
|
|
|
*/
|
|
|
|
/* includes */
|
|
#include <vxWorks.h>
|
|
#include <errnoLib.h>
|
|
#include <intLib.h>
|
|
#include <iv.h>
|
|
#include <sysLib.h>
|
|
#include <string.h> /* for strtok_r */
|
|
|
|
#include <CAN/wnCAN.h>
|
|
#include <CAN/canController.h>
|
|
#include <CAN/canBoard.h>
|
|
#include <CAN/i82527.h>
|
|
#include <CAN/private/msmcan.h>
|
|
|
|
#if (CPU != SH7750)
|
|
static const char deviceName[] ="MSMCAN PC104";
|
|
|
|
struct MSMCAN_PC104_DeviceEntry *msmcan_pc104_DeviceArray;
|
|
UINT max_msmcan_pc104_boards;
|
|
|
|
/* external reference */
|
|
STATUS CAN_DEVICE_establishLinks(WNCAN_DEVICE *pDev, WNCAN_BoardType brdType,
|
|
WNCAN_ControllerType ctrlType);
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_isr - board-level isr
|
|
*
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
static void msmcan_pc104_isr
|
|
(
|
|
ULONG param
|
|
)
|
|
{
|
|
|
|
struct MSMCAN_PC104_DeviceEntry *pDE;
|
|
|
|
pDE = (struct MSMCAN_PC104_DeviceEntry *)param;
|
|
|
|
if(pDE->allocated)
|
|
{
|
|
i82527ISR((ULONG)&pDE->canDevice);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_enableIrq - enable irq on board
|
|
*
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
static void msmcan_pc104_enableIrq
|
|
(
|
|
struct WNCAN_Device *pDev
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_disableIrq - disable irq on board
|
|
*
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
static void msmcan_pc104_disableIrq
|
|
(
|
|
struct WNCAN_Device *pDev
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_200_new - install driver for pc104 board
|
|
*
|
|
*
|
|
* RETURNS: OK or ERROR
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
STATUS msmcan_pc104_new
|
|
(
|
|
ULONG ioAddress,
|
|
UINT irq
|
|
)
|
|
{
|
|
UINT i;
|
|
UINT brdNdx=0xff;
|
|
int oldLevel;
|
|
STATUS retCode;
|
|
VOIDFUNCPTR* irqVec = 0;
|
|
|
|
struct WNCAN_Device *pDev;
|
|
struct MSMCAN_PC104_DeviceEntry *pDeviceEntry;
|
|
|
|
retCode = ERROR; /* pessimistic */
|
|
pDeviceEntry = 0;
|
|
|
|
/* find a free device data structure */
|
|
for(i = 0 ; i < max_msmcan_pc104_boards; i++)
|
|
{
|
|
if(msmcan_pc104_DeviceArray[i].inUse == 0)
|
|
{
|
|
msmcan_pc104_DeviceArray[i].inUse = 1;
|
|
pDeviceEntry = &msmcan_pc104_DeviceArray[i];
|
|
brdNdx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!pDeviceEntry)
|
|
{
|
|
errnoSet(S_can_out_of_memory);
|
|
goto exit;
|
|
}
|
|
|
|
/* setup data structures */
|
|
pDev = &pDeviceEntry->canDevice;
|
|
pDev->pCtrl = &pDeviceEntry->canController;
|
|
pDev->pBrd = &pDeviceEntry->canBoard;
|
|
|
|
pDev->deviceName = deviceName;
|
|
pDev->pBrd->irq = irq;
|
|
pDev->pBrd->ioAddress = ioAddress;
|
|
pDev->pBrd->xtalFreq = _16MHZ;
|
|
|
|
/* set default baud rate to 125 Kbits/sec */
|
|
pDev->pCtrl->brp = 3;
|
|
pDev->pCtrl->sjw = 0;
|
|
pDev->pCtrl->tseg1 = 0xc;
|
|
pDev->pCtrl->tseg2 = 0x1;
|
|
pDev->pCtrl->samples = 0;
|
|
|
|
pDev->pCtrl->chnType = g_i82527chnType;
|
|
pDev->pCtrl->chnMode = &pDeviceEntry->i82527chnMode[0];
|
|
pDev->pCtrl->numChn = I82527_MAX_MSG_OBJ;
|
|
pDev->pCtrl->csData = &pDeviceEntry->can82527;
|
|
|
|
if(CAN_DEVICE_establishLinks(pDev, WNCAN_MSMCAN, WNCAN_I82527) == ERROR)
|
|
{
|
|
pDev = 0;
|
|
goto exit;
|
|
}
|
|
|
|
pDev->deviceId = brdNdx; /* index into deviceEntry array */
|
|
|
|
/* connect to isr */
|
|
oldLevel = intLock();
|
|
|
|
#if CPU_FAMILY == I80X86
|
|
irqVec = INUM_TO_IVEC(irq+0x20);
|
|
#elif CPU_FAMILY == PPC
|
|
irqVec = INUM_TO_IVEC(irq+0x40);
|
|
#else
|
|
#warning irqVec not defined
|
|
#endif
|
|
|
|
/* don't need return from function call */
|
|
|
|
(void) intConnect(irqVec,msmcan_pc104_isr, (ULONG)pDeviceEntry);
|
|
|
|
/* activate interrupt at board and cpu level */
|
|
#if (CPU_FAMILY == I80X86)
|
|
sysIntEnablePIC(pDev->pBrd->irq);
|
|
#elif CPU_FAMILY == PPC
|
|
intEnable(pDev->pBrd->irq+0x40);
|
|
#else
|
|
#warning interrupts cannot be enabled
|
|
#endif
|
|
|
|
intUnlock(oldLevel);
|
|
|
|
pDeviceEntry->ioAddress = ioAddress;
|
|
pDeviceEntry->irq = irq;
|
|
|
|
retCode = OK;
|
|
exit:
|
|
return retCode;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_canInByte
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
* ERRNO:
|
|
*
|
|
*/
|
|
static UCHAR msmcan_pc104_canInByte
|
|
(
|
|
struct WNCAN_Device *pDev,
|
|
unsigned int offset
|
|
)
|
|
{
|
|
sysOutByte(pDev->pBrd->ioAddress + 1,offset);
|
|
return sysInByte(pDev->pBrd->ioAddress);
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_canOutByte
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
* ERRNO:
|
|
*
|
|
*/
|
|
static void msmcan_pc104_canOutByte
|
|
(
|
|
struct WNCAN_Device *pDev,
|
|
unsigned int offset,
|
|
UCHAR value
|
|
)
|
|
{
|
|
sysOutByte(pDev->pBrd->ioAddress + 1,offset);
|
|
sysOutByte(pDev->pBrd->ioAddress, value);
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_establishLinks - set up function pointers
|
|
*
|
|
*
|
|
* RETURNS: OK always
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
|
|
STATUS msmcan_pc104_establishLinks(struct WNCAN_Device *pDev)
|
|
{
|
|
pDev->pBrd->onEnterISR = 0;
|
|
pDev->pBrd->onLeaveISR = 0;
|
|
pDev->pBrd->enableIrq = msmcan_pc104_enableIrq;
|
|
pDev->pBrd->disableIrq = msmcan_pc104_disableIrq;
|
|
|
|
pDev->pBrd->canInByte = msmcan_pc104_canInByte;
|
|
pDev->pBrd->canOutByte = msmcan_pc104_canOutByte;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_open - open a CAN device
|
|
*
|
|
* RETURNS: pointer to a WNCAN_Device structure or 0 if error
|
|
*
|
|
* ERRNO: S_can_illegal_board_no
|
|
* S_can_illegal_ctrl_no
|
|
* S_can_busy
|
|
*
|
|
*/
|
|
struct WNCAN_Device *msmcan_pc104_open(UINT brdNdx, UINT ctrlNdx)
|
|
{
|
|
|
|
struct WNCAN_Device *pRet = 0; /* pessimistic */
|
|
|
|
if((brdNdx >= max_msmcan_pc104_boards) ||
|
|
(msmcan_pc104_DeviceArray[brdNdx].inUse == 0))
|
|
{
|
|
errnoSet(S_can_illegal_board_no);
|
|
}
|
|
else if(msmcan_pc104_DeviceArray[brdNdx].allocated == 1)
|
|
{
|
|
errnoSet(S_can_busy);
|
|
}
|
|
else if(ctrlNdx >= MSMCAN_PC104_MAX_CONTROLLERS)
|
|
{
|
|
errnoSet(S_can_illegal_ctrl_no);
|
|
}
|
|
else
|
|
{
|
|
msmcan_pc104_DeviceArray[brdNdx].allocated = 1;
|
|
pRet = &msmcan_pc104_DeviceArray[brdNdx].canDevice;
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
/************************************************************************
|
|
*
|
|
* msmcan_pc104_close - close the specified CAN device
|
|
*
|
|
* RETURNS: N/A
|
|
*
|
|
* ERRNO: N/A
|
|
*
|
|
*/
|
|
void msmcan_pc104_close(struct WNCAN_Device *pDev)
|
|
{
|
|
UINT brdNdx;
|
|
|
|
if (pDev != 0)
|
|
{
|
|
brdNdx = pDev->deviceId;
|
|
msmcan_pc104_DeviceArray[brdNdx].allocated = 0;
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|