/**************************************************************** * Copyright (c) 2008-2009 QUANTA COMPUTER INC., INC. All rights reserved. * * File Name: cpi.c * Abstract: Component programming interface * Description: * * Project Name: Aurora * Software Component: * * Exported Functions: * * Notes: * * History: * 2008/4/14 Cloud Created * 2009/9/1 Modified for Pikes Peak Platform * *** END OF REVISION HISTORY ***********************************/ #include #include #include #include #include #include "commDebug.h" #include #include "commCpi.h" #include #include #include "flashExpDiag.h" EXTERN INT32 plxProgramEeprom(UINT8 *buf, UINT32 size); /* Function prototype */ static int cpiProcPermission(struct inode *inode, int op, unsigned int); STATIC ssize_t cpiProcRead(struct file *file, char *buf, size_t size, loff_t *offset); STATIC ssize_t cpiProcWrite(struct file *file, const char *buf, size_t size, loff_t *offset); STATIC INT32 cpiProcOpen(struct inode *inode, struct file *file); static long cpiProcIoctl(struct file *file, unsigned int cmd, unsigned long arg); STATIC INT32 cpiProcClose(struct inode *inode, struct file *file); /* Local variable */ STATIC BOOLEAN s_cpi_opened = FALSE; STATIC CPI_PRO_CB s_pro_cb; STATIC UINT8 *s_pro_buffer = NULL; STATIC INT32 s_pro_cursor = 0; /* for mutiple phase write */ //PUBLIC pid_t g_iotestd_pid; STATIC struct inode_operations s_cpi_proc_iops = { .permission = cpiProcPermission, }; STATIC struct file_operations s_cpi_proc_fops = { .read = cpiProcRead, .write = cpiProcWrite, .open = cpiProcOpen, .compat_ioctl = cpiProcIoctl, .unlocked_ioctl = cpiProcIoctl, .release = cpiProcClose, }; /*********************************************************** Name: CpiProcPermission Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ static int cpiProcPermission(struct inode *inode, int op, unsigned int arg) { if (!s_cpi_opened) return (0); else return (-EBUSY); } /*********************************************************** Name: CpiProcOpen Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC INT32 cpiProcOpen(struct inode *inode, struct file *file) { if (!s_cpi_opened) s_cpi_opened = TRUE; else ASSERT(0); return(0); } /*********************************************************** Name: CpiProcClose Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC INT32 cpiProcClose(struct inode *inode, struct file *file) { if (s_cpi_opened) s_cpi_opened = FALSE; else ASSERT(0); return(0); } /*********************************************************** Name: CpiProcRead Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC ssize_t cpiProcRead(struct file *file, char *buf, size_t size, loff_t *offset) { printk("Component Programming Interface\n"); return (0); } /*********************************************************** Name: CpiProcWrite Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC ssize_t cpiProcWrite(struct file *file, const char *buf, size_t size, loff_t *offset) { INT32 ret = 0; INT32 address; VOID* fpgaEpcsP = NULL; if (size > CPI_PRO_BUFFER_SIZE) return (-EINVAL); if (copy_from_user(s_pro_buffer, buf, size)) return -EFAULT; /* Set up start address for programming */ address = s_pro_cb.start_addr + s_pro_cursor; switch (s_pro_cb.target) { case CPI_PCIE_EEPROM: /* XXX: expect: eeprom image <= CPI_PRO_BUFFER_SIZE */ ret = plxProgramEeprom(s_pro_buffer, size); break; case CPI_VPD_EEPROM: { #if 0 struct i2c_adapter *adap = pca9548Adapter[PCA9548_CHANNEL_7]; ret = i2cEeprom64KBitProgram(adap, EEPROM_64KB_NAME, address, s_pro_buffer, size); #endif break; } case CPI_EXP_EEPROM: //TBD break; case CPI_EXP_FLASH: ret = ExpProgramFlash(address, size, s_pro_buffer); break; case CPI_IOC_EEPROM: { #if 0 struct i2c_adapter *adap = pca9548Adapter[PCA9548_CHANNEL_4]; ret = i2cEeprom64KBitProgram(adap, SAS2008_EEPROM_ADDR, address, s_pro_buffer, size); #endif break; } case CPI_FPGA_FLASH: printk("\n"); fpgaEpcsP = (UINT8*)kmalloc(size, GFP_KERNEL); if(fpgaEpcsP == NULL) printk("[FPGA EPCS] Can not allocate buffer \n"); else{ *(UINT8*)fpgaEpcsP = 0xFF; memcpy(fpgaEpcsP + 1, s_pro_buffer, size - 1); ret = fpgaProgramEpcs(address, size, fpgaEpcsP); } break; case CPI_ETH_EEPROM: //TBD break; case CPI_PSOC_FW: //TBD break; default: return (-EINVAL); } if (ret) return (-EIO); /* maybe mutiple write */ s_pro_cursor += size; /* Should not happen */ if (s_pro_cb.size < (s_pro_cursor - s_pro_cb.start_addr)) ASSERT(0); return(size); } /*********************************************************** Name: CpiDoValidation Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC INT32 cpiDoValidation(CPI_VAL_CB *cb) { INT32 ret = 0; switch (cb->target) { case CPI_PCIE_EEPROM: //TBD break; case CPI_VPD_EEPROM: //TBD break; case CPI_EXP_EEPROM: //TBD break; case CPI_EXP_FLASH: //TBD break; case CPI_IOC_EEPROM: //TBD break; case CPI_FPGA_FLASH: //NONE break; case CPI_ETH_EEPROM: //TBD break; case CPI_PSOC_FW: //TBD break; default: return (-EINVAL); } return (ret); } /*********************************************************** Name: CpiProcIoctl Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ static long cpiProcIoctl(struct file *file, unsigned int cmd, unsigned long arg) { VOID __user *uarg = (VOID __user*)arg; switch (cmd) { case CPI_CMD_PRO: /* * Setup programming parameters * then we can do write operation */ memset(&s_pro_cb, 0, sizeof(CPI_PRO_CB)); if (copy_from_user(&s_pro_cb, uarg, sizeof(CPI_PRO_CB))) return -EFAULT; /* Reset programming cursor at beginning */ s_pro_cursor = 0; break; case CPI_CMD_VAL: { CPI_VAL_CB cb; memset(&cb, 0, sizeof(CPI_VAL_CB)); if (copy_from_user(&cb, uarg, sizeof(CPI_VAL_CB))) return -EFAULT; return (cpiDoValidation(&cb)); } break; #if 0 case CPI_CMD_IO: if (copy_from_user(&g_iotestd_pid, uarg, sizeof(pid_t))) return (-EFAULT); printk("[%s] pid: %d\n", __func__, g_iotestd_pid); break; #endif default: return (-EINVAL); } return(0); } /*********************************************************** Name: CpiProcInit Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ STATIC INT32 cpiProcInit(VOID) { struct proc_dir_entry *entry; entry = create_proc_entry("pikespeak_cpi", 0644, NULL); if (!entry) return -ENOMEM; entry->proc_iops = &s_cpi_proc_iops; entry->proc_fops = &s_cpi_proc_fops; return (0); } /*********************************************************** Name: CpiInit Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ static int __init cpiInit( void ) { /* Reset CB */ memset(&s_pro_cb, 0, sizeof(CPI_PRO_CB)); /* Alloc programming buffer */ s_pro_buffer = kmalloc(CPI_PRO_BUFFER_SIZE, GFP_KERNEL); if (s_pro_buffer == NULL) return (-ENOMEM); return (cpiProcInit()); } /*********************************************************** Name: CpiExit Synopsis: Description: Input Variables: Output Variables: Return Value: Globals: ***********************************************************/ static void __exit cpiExit( void ) { if (s_pro_buffer) kfree(s_pro_buffer); remove_proc_entry("pikespeak_cpi", NULL); } module_init( cpiInit ); module_exit( cpiExit ); MODULE_AUTHOR( "merck.hung@netapp.com" ); MODULE_DESCRIPTION( "NetApp CPI Diag Code" ); MODULE_LICENSE( "GPL" ); MODULE_VERSION( "0.1" );