/* 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 #include #include #include #include #include /* for strtok_r */ #include #include #include #include #include #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