/******************************************************************************* NAME $RCSfile: commIpcEthernetExport.c,v $ SUMMARY IPC APIs for inter-controller communication VERSION $Revision: 1.12 $ UPDATE DATE $Date: 2010/01/28 08:10:49 $ PROGRAMMER $Author: jim $ Copyright 2009 LSI Corporation. All Rights Reserved. DESCRIPTION: REFERENCE: *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "commIpcEthernet.h" static EIPC_CB eIpcCb; EXPORT_SYMBOL(eIpcCb); /* EIPC notify callback function */ static EIPC_NOTIFY ipcEthernetNotifyFunc[IPC_APP_MAX]; EXPORT_SYMBOL(ipcEthernetNotifyFunc); /******************************************************************************* * PROCEDURE * * NAME: ipcEthernetRegister * SUMMARY: Register notify function for specific IPC app * * SCOPE: Public * * DESCRIPTION: * * RETURNS: * * NOTES: * */ void ipcEthernetRegister(int app, EIPC_NOTIFY notifyFunc) { switch (app) { case IPC_APP_ECHO: case IPC_APP_GET_TEMP: case IPC_APP_START_PLX_IPC: case IPC_APP_STOP_PLX_IPC: case IPC_APP_REQUEST_POWER_CYCLE: case IPC_APP_IO_TEST_RUN: case IPC_APP_IO_TEST_STOP: case IPC_APP_GET_DYNAMO_STAT: case IPC_APP_GET_QE8_CNT: case IPC_APP_FIXTURE_SAS_INIT: case IPC_APP_FIXTURE_SAS_READY: case IPC_APP_ALT_CTRL_READY_REQ: case IPC_APP_ALT_CTRL_READY_REPLY: case IPC_APP_FIXTURE_FALCON_PHY_DISABLE_INIT: case IPC_APP_FIXTURE_FALCON_PHY_DISABLE_READY: case IPC_APP_FIXTURE_SAS_INIT_FORCE: //DVT3 case IPC_APP_UUT_SAS_INIT: //PVT case IPC_APP_UUT_SAS_READY: //PVT #include "IPCforStress_S.inc" case IPC_APP_HW_VALIDATION: ipcEthernetNotifyFunc[app] = notifyFunc; break; default: printk("[EIPC] register unknown IPC APP(%d)\n", app); break; } } EXPORT_SYMBOL(ipcEthernetRegister); /******************************************************************************* * PROCEDURE * * NAME: ipcEthernetDeregister * SUMMARY: De-register notify function for specific IPC app * * SCOPE: Public * * DESCRIPTION: * * RETURNS: * * NOTES: * */ void ipcEthernetDeregister(int app) { switch (app) { case IPC_APP_ECHO: case IPC_APP_GET_TEMP: case IPC_APP_START_PLX_IPC: case IPC_APP_STOP_PLX_IPC: case IPC_APP_REQUEST_POWER_CYCLE: case IPC_APP_IO_TEST_RUN: case IPC_APP_IO_TEST_STOP: case IPC_APP_GET_DYNAMO_STAT: case IPC_APP_GET_QE8_CNT: case IPC_APP_FIXTURE_SAS_INIT: case IPC_APP_FIXTURE_SAS_READY: case IPC_APP_ALT_CTRL_READY_REQ: case IPC_APP_ALT_CTRL_READY_REPLY: case IPC_APP_FIXTURE_FALCON_PHY_DISABLE_INIT: case IPC_APP_FIXTURE_FALCON_PHY_DISABLE_READY: case IPC_APP_FIXTURE_SAS_INIT_FORCE: //DVT3 case IPC_APP_UUT_SAS_INIT: //PVT case IPC_APP_UUT_SAS_READY: //PVT #include "IPCforStress_S.inc" case IPC_APP_HW_VALIDATION: ipcEthernetNotifyFunc[app] = NULL; break; default: printk("[EIPC] deregister unknown IPC APP(%d)\n", app); break; } } EXPORT_SYMBOL(ipcEthernetDeregister); uint8_t ipcChksum(IPC_MSG *msg) { char sum; int i; if( !msg ) return 0; sum = msg->hdr.app; sum += msg->hdr.flag; sum += msg->hdr.cookie; if (msg->hdr.len) { char *data = msg->body; for (i=0; i < msg->hdr.len; i++, data++) { sum += *data; } } return (sum); } /******************************************************************************* * PROCEDURE * * NAME: ipcEthernetSend * SUMMARY: Sending message to peer controller throuth ethernet * * SCOPE: Public * * DESCRIPTION: * * RETURNS: * * NOTES: * Callers should set the following element in EIPC_MSG: * msg->hdr.app: app type * msg->hdr.len: body size * msg->hdr.flag: reqeust or response */ int ipcEthernetSend(EIPC_MSG *msg) { EIPC_MSG *freeMsg; if( !msg ) return -EINVAL; spin_lock(&eIpcCb.txLock); if (list_empty(&eIpcCb.freeTxQueue)) { printk("[EIPC] out of free tx resource\n"); spin_unlock(&eIpcCb.txLock); return (-ENOMEM); } freeMsg = list_entry(eIpcCb.freeTxQueue.next, EIPC_MSG, list); //DPRINTK("%s(%d) get free tx msg @%p\n", __func__, __LINE__, freeMsg); list_del(&freeMsg->list); spin_unlock(&eIpcCb.txLock); memset(freeMsg, 0, sizeof(EIPC_MSG)); /* copy header */ memcpy(freeMsg, msg, IPC_HEADER_SIZE); /* copy body if any */ if (msg->hdr.len) memcpy(freeMsg->body, msg->body, msg->hdr.len); freeMsg->hdr.type = IPC_TYPE_ETHERNET; freeMsg->hdr.err_chk = ipcChksum((IPC_MSG*) freeMsg); /* put on working queue */ spin_lock(&eIpcCb.txLock); list_add_tail(&freeMsg->list, &eIpcCb.txQueue); wake_up_process(eIpcCb.eTask); spin_unlock(&eIpcCb.txLock); return (0); } EXPORT_SYMBOL(ipcEthernetSend); static int __init commIpcInit( void ) { memset( ipcEthernetNotifyFunc, 0, IPC_APP_MAX ); return 0; } static void __exit commIpcExit( void ) { } module_init( commIpcInit ); module_exit( commIpcExit ); MODULE_AUTHOR( "merck.hung@netapp.com" ); MODULE_DESCRIPTION( "Common IPC Code" ); MODULE_LICENSE( "GPL" );