/* #include */ #include #include #include #include /* printk() */ #include /* kmalloc() */ #include /* everything... */ #include /* error codes */ #include /* size_t */ #include #include /* O_ACCMODE */ /* #include */ #include /* #include */ #include "ssd.h" #include "ssd_testdrv.h" #include #include #include MODULE_AUTHOR("Yanir Lubetkin"); MODULE_LICENSE("GPL"); //MODULE_PARM(test_busycount, "i"); //MODULE_PARM_DESC(test_busycount, "how many times to busy loop between actions"); int test_busycount = 3000; struct ssd_testdrv_dev ssd_testdrv_device; static const char *ifx_dev_name="driver/ifx_testdrv2_api"; static int ifx_switch_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data); static int ifx_switch_write_procmem(struct file *file, const char *buffer, unsigned long count, void *data); unsigned char *buf; unsigned char*ptr[10]; unsigned char *buf1; unsigned char*ptr1[10]; unsigned char*ptr2[10]; unsigned char *buf2; int io_size; int io_direction;/* = read, 1 = write */ void noop_routine(void* BusGuardHandle, int status){} typedef enum { ISR = 0, TEST_CONTEXT }bus_txn_context_t; bus_txn_context_t g_bus_txn_context=TEST_CONTEXT; #if 1/* nitialization code and load vals */ /*Yanir: tnet init code */ /************************************** Routine: board_setup_psc Description: Enable/Disable a PSC domain **************************************/ #define PLL1_PLLM __REG(0x01c40910) #define PLL2_PLLM __REG(0x01c40D10) #define PTCMD __REG(0x01C41120) #define PDSTAT __REG(0x01C41200) #define PDCTL1 __REG(0x01C41304) #define EPCPR __REG(0x01C41070) #define PTSTAT __REG(0x01C41128) #define MDSTAT IO_ADDRESS(0x01C41800) #define MDCTL IO_ADDRESS(0x01C41A00) /***************************************************************************** * definitions used by the TNETW initialization code - should be seperated ******************************************************************************/ #define WLAN_RESET_BIT 5 #define IN_RESET 1 #define OUT_OF_RESET 0 /* DAVINCI GPIO */ #define DAVINCI_GPIO IO_ADDRESS(DAVINCI_GPIO_BASE) #define DAVINCI_GPIO_BINTEN (unsigned int *)(DAVINCI_GPIO + 0x08) #define DAVINCI_GPIO_DIR_REG (unsigned int *)(DAVINCI_GPIO + 0x10) #define DAVINCI_GPIO_OUT_DATA (unsigned int *)(DAVINCI_GPIO + 0x14) #define DAVINCI_GPIO_BINTEN (unsigned int *)(DAVINCI_GPIO + 0x08) #define DAVINCI_GPIO_SET_RIS_TRIG (unsigned int *)(DAVINCI_GPIO + 0x24) #define DAVINCI_GPIO_CLR_RIS_TRIG (unsigned int *)(DAVINCI_GPIO + 0x28) #define DAVINCI_GPIO_SET_FAL_TRIG (unsigned int *)(DAVINCI_GPIO + 0x2c) #define DAVINCI_GPIO_CLR_FAL_TRIG (unsigned int *)(DAVINCI_GPIO + 0x30) #define DAVINCI_GPIO_INSTAT (unsigned int *)(DAVINCI_GPIO + 0x34) /********************************************************************/ /* TNETW initialization code (not pure SDIO - should be moved? */ /********************************************************************/ /* /\*i2c-expander.h is defined in kernel MV baseline 1 */ /* i2c-client.h defnition changed in kernel MV baseline 2*; include file name was modified between 2 kernel releases*\/ */ /* #if defined(TI_KERNEL_BASELINE2) */ /* #include */ /* #else */ /* #include */ /* #endif */ //MODULE_PARM(wlan_reset, "s"); //MODULE_PARM_DESC(wlan_reset, "Wlan reset polarity (high/low)"); static char *wlan_reset = "high"; static unsigned char wlan_reset_val = 0; /* DaVinci peripherals power control */ void board_setup_psc(unsigned int domain, unsigned int id, char enable) { printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); /* volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id); */ /* volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id); */ /* if (enable) { */ /* *mdctl |= 0x00000003; /\* Enable Module *\/ */ /* } else { */ /* *mdctl &= 0xFFFFFFF2; /\* Disable Module *\/ */ /* } */ /* if ((PDSTAT & 0x00000001) == 0) { */ /* PDCTL1 |= 0x1; */ /* PTCMD = (1 << domain); */ /* while ((((EPCPR >> domain) & 1) == 0)) ; */ /* PDCTL1 |= 0x100; */ /* while (!(((PTSTAT >> domain) & 1) == 0)) ; */ /* } else { */ /* PTCMD = (1 << domain); */ /* while (!(((PTSTAT >> domain) & 1) == 0)) ; */ /* } */ /* if (enable) */ /* { */ /* while (!((*mdstat & 0x0000001F) == 0x3)) ; */ /* } */ /* else */ /* { */ /* while (!((*mdstat & 0x0000001F) == 0x2)) ; */ /* } */ } /* Reset TNETW using the I2C controller */ #define RST_GPIO 13 int ifx_sdio_set_ext_reset(int gpio, int active); int DaVinci_TNETW_Reset(int SetFlag) { u8 val; volatile unsigned int temp; printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); if (SetFlag==IN_RESET) { printk("--Put the TNET in Reset--\n"); val = wlan_reset_val; } else { printk("--Take the TNET out of Reset--\n"); val = 1 - wlan_reset_val; } /* Send the value to the I2C controller */ /* davinci_i2c_expander_op(0x3a, WLAN_RESET, val); */ ifx_sdio_set_ext_reset(RST_GPIO, SetFlag); /* Delay to make sure line has stabled */ for (temp=0; temp<=10;temp++) udelay(1000); return 0; } /* Configure the DaVinci EVM. Turn on the MMCSD and the WLAN */ /* #define PINMUX0 (unsigned int *)(IO_ADDRESS(0x01c40000)) */ void Davinci_Wlan_Hardware_Init( void ) { printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); /* unsigned int temp; */ /* /\* We are getting the wlan reset polarity from the command line *\/ */ /* printk("info: polarity is %s\n",wlan_reset); */ /* if (strcmp(wlan_reset, "low") == 0) */ /* { */ /* printk("Wlan reset polarity is low (Beta board)\n"); */ /* wlan_reset_val = 0; */ /* } */ /* else */ /* { */ /* wlan_reset_val = 1; */ /* } */ /* /\* Activate the MMCSD module *\/ */ /* board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_MMC_SD, 1); */ /* board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); */ /* #if 0 */ /* printk("changing GPIO direction form: %x \n",*DAVINCI_GPIO_DIR_REG); */ /* *DAVINCI_GPIO_DIR_REG &= ~(0x003c0000); /\* GPIO 19,20,21 to output mode. GPIO18 Input mode*\/ */ /* printk("To : %x\n",*DAVINCI_GPIO_DIR_REG); */ /* printk("changing GPIO output level from: %x \n",*DAVINCI_GPIO_OUT_DATA); */ /* *DAVINCI_GPIO_OUT_DATA &= ~(0x003c0000); /\* Zero on GPIO 19,20,21 *\/ */ /* *DAVINCI_GPIO_OUT_DATA |= 0x00280000; /\* GPIO19=1, GPIO20=0, GPIO21=1*\/ */ /* printk("To : %x\n",*DAVINCI_GPIO_OUT_DATA); */ /* #endif */ /* #if 1 */ /* /\* Set falling edge detection on GPIO bank 1 *\/ */ /* *DAVINCI_GPIO_SET_FAL_TRIG |= (1 << 18); */ /* /\* Enable bank 1 interrupts *\/ */ /* *DAVINCI_GPIO_BINTEN |= 0x3; */ /* /\* Delay to make sure GPIOs are stable *\/ */ /* for (temp=0; temp<=20000;temp++); */ /* #endif */ /* /\* Configure PinMux0 to use the vlynq pins and GPIOs 10-21 *\/ */ /* /\* printk("Muxing the VLYNQ pins using PinMux0...\n"); *\/ */ /* /\* Mask bits 0-15 in PinMux0 register *\/ */ /* *PINMUX0 &= ~0x0000f01f; */ /* /\* Program the PinMux0 register *\/ */ /* *PINMUX0 |= 0x0000000b;/\*d00b*\/ */ /* printk("Mux: PinMux0=%x\n",*PINMUX0); */ /* /\* Delay to make sure GPIOs are stable *\/ */ /* for (temp=0; temp<=20000;temp++); */ /* davinci_i2c_expander_op(0x3a, VLYNQ_ON, 0); */ /* Send a reset pulse to the WLAN chip */ /* Danube_Wlan_Hardware_Init(); */ DaVinci_TNETW_Reset(IN_RESET); // mdelay(5); DaVinci_TNETW_Reset(OUT_OF_RESET); // mdelay(5); } /*Yanir: this is the code that sets the partition scheme on the tnet. */ #define SDIO_FUNC1_OFFSET 0x1FFC0 /* anir: address of the partition table */ struct parts{ unsigned long size1; unsigned long off1; unsigned long size2; unsigned long off2; }g_parts; inline int load_vals(int clientID, unsigned long v1,unsigned long v2,unsigned long v3,unsigned long v4) { int status; char byteData[4]; g_parts.size1 = v1; g_parts.off1 = v2; g_parts.size2 = v3; g_parts.off2 = v4; printk("entering %s(%lx,%lx,%lx,%lx)\n",__FUNCTION__, v1, v2, v3, v4); status = ssd_functionSelect(clientID, 1); /* rom eyal's code it seems that partition transaction can only be performed using COMMAND52 */ byteData[0] = g_parts.size1 & 0xff; byteData[1] = (g_parts.size1>>8) & 0xff; byteData[2] = (g_parts.size1>>16) & 0xff; byteData[3] = (g_parts.size1>>24) & 0xff; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET,byteData[0]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+1,byteData[1]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+2,byteData[2]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+3,byteData[3]); if(status)return status; byteData[0] = g_parts.off1 & 0xff; byteData[1] = (g_parts.off1>>8) & 0xff; byteData[2] = (g_parts.off1>>16) & 0xff; byteData[3] = (g_parts.off1>>24) & 0xff; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+4,byteData[0]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+5,byteData[1]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+6,byteData[2]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+7,byteData[3]); if(status)return status; byteData[0] = g_parts.size2 & 0xff; byteData[1] = (g_parts.size2 >> 8) & 0xff; byteData[2] = (g_parts.size2>>16) & 0xff; byteData[3] = (g_parts.size2>>24) & 0xff; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+8,byteData[0]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+9,byteData[1]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+10,byteData[2]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+11,byteData[3]); if(status)return status; byteData[0] = g_parts.off2 & 0xff; byteData[1] = (g_parts.off2>>8) & 0xff; byteData[2] = (g_parts.off2>>16) & 0xff; byteData[3] = (g_parts.off2>>24) & 0xff; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+12,byteData[0]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+13,byteData[1]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+14,byteData[2]); if(status)return status; status = ssd_SDIO_writeByte(clientID,SDIO_FUNC1_OFFSET+15,byteData[3]); if(status)return status; status = ssd_functionSelect(clientID, 1); /* ead the partition from the device: */ printk("exiting %s\n",__FUNCTION__); return status; } /*Yanir: tnet init code end */ #endif/* */ void sdiotest_completion_routine(void* BusTxnHandle, int status) { /* ake us up if we wait for a completion. */ struct ssd_testdrv_dev* dev = (struct ssd_testdrv_dev*)BusTxnHandle; // printk("debug : %s",__FUNCTION__); if(dev != &ssd_testdrv_device){ printk("Yanir: sdiotest_completion_routine()!!!!!!!!!! context lost!!!!!!!!!!! 0x%p != 0x%p\n",dev,&ssd_testdrv_device); printk("orig status is: %d - changing to -1\n",status); ssd_testdrv_device.async_completion_status = -1; dev->io_in_progress = 0; }else{ ssd_testdrv_device.async_completion_status = status; dev->io_in_progress = 0; } } void sdiotest_completion_routine_isr(void* BusTxnHandle, int status) { volatile int ret = 0; /* ake us up if we wait for a completion. */ struct ssd_testdrv_dev* dev = (struct ssd_testdrv_dev*)BusTxnHandle; // printk("debug : %s",__FUNCTION__); /* printk("entering sdiotest_completion_routine2()\n"); */ if(dev != &ssd_testdrv_device){ printk("Yanir: sdiotest_completion_routine()!!!!!!!!!! context lost!!!!!!!!!!! 0x%p != 0x%p\n",dev,&ssd_testdrv_device); printk("orig status is: %d - changing to -1\n",status); ssd_testdrv_device.async_completion_status = -1; dev->io_in_progress = 0; // wake_up_interruptible(&(dev->wq)); }else{ /* printk("number of io operations to complete...%d\n",dev->io_in_progress); */ ssd_testdrv_device.async_completion_status = status; dev->io_in_progress--; if(dev->io_in_progress){ /* for(ret=0;ret<100000;){i=ret+1;ret=i;} */ if(io_direction) /* rite */ { ret = ssd_SDIO_writeAsync(ssd_testdrv_device.client_id,0x00000008, ptr[( dev->io_in_progress)%10], io_size); if(ret){ printk("ssd_SDIO_writeAsync() returned an error value of %d\n",ret); dev->io_in_progress = 0; } } else { ret = ssd_SDIO_readAsync(ssd_testdrv_device.client_id,0x00000008, ptr[( dev->io_in_progress)%10], io_size); if(ret){ printk("ssd_SDIO_writeAsync() returned an error value of %d\n",ret); dev->io_in_progress = 0; // wake_up_interruptible(&(dev->wq)); } } }else{ // wake_up_interruptible(&(dev->wq)); } } } void sdiotest_completion_base_routine(void* BusTxnHandle, int status) { // printk("debug : %s",__FUNCTION__); if (g_bus_txn_context==TEST_CONTEXT) sdiotest_completion_routine(BusTxnHandle, status); if (g_bus_txn_context==ISR) sdiotest_completion_routine_isr(BusTxnHandle, status); } void init_buffers(void) { int i, z; buf = kmalloc(5120, __GFP_DMA); buf1 = kmalloc(5120, __GFP_DMA); buf2 = kmalloc(5120, __GFP_DMA); if ((buf == 0) || (buf1 == 0)|| (buf2 == 0)) { printk("%s:%s:%d TODO: No memory buf=%p, buf1=%p\n", __FILE__, __FUNCTION__, __LINE__, buf, buf1); } for(i=0;i<10;i++){ ptr[i] = buf+i*512; ptr2[i] = buf2+i*512; for (z=0; z<512; z+=4) { *((unsigned long*)(&(ptr[i][z]))) = (i*0x1000)+z + ((((i+1)%10) * 0x1000 + (z + 1)) << 16); *((unsigned long*)(&(ptr2[i][z]))) = 0x5a5aa5a5; } ptr1[i] = buf1+i*512; memset(ptr1[i],0,512); } memset(&ssd_testdrv_device, 0,sizeof (struct ssd_testdrv_dev)); } int init_ssd(void) { int ret, j; printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); init_waitqueue_head(&(ssd_testdrv_device.wq)); ssd_testdrv_device.ssd_params.DevId = 2; ssd_testdrv_device.ssd_params.OrigCmdCode = 0; ssd_testdrv_device.ssd_params.NewCmdCode = 0; ssd_testdrv_device.ssd_params.BusWidth = 4; ssd_testdrv_device.ssd_params.FunctionSelectMode = 0; ssd_testdrv_device.ssd_params.blockSize = 4; ssd_testdrv_device.ssd_params.BusTxnCB = sdiotest_completion_base_routine; ssd_testdrv_device.ssd_params.BusTxnHandle = &ssd_testdrv_device; printk("registering context: 0x%p\n",ssd_testdrv_device.ssd_params.BusTxnHandle); ssd_testdrv_device.ssd_params.BusGuardCB = noop_routine; ssd_testdrv_device.ssd_params.BusGuardHandle = NULL; ssd_testdrv_device.ssd_params.BusGuardParams = NULL; ssd_testdrv_device.ssd_params.Timeout = 0xff; ssd_testdrv_device.ssd_params.MaxClockRate = 25; printk("entering hardware init phase\n"); Davinci_Wlan_Hardware_Init(); /* anir: removed from the SDIO driver to the clients. */ printk("finished hardware_init process\nentering open phase\n"); printk(" running open\n"); ssd_testdrv_device.client_id = ssd_SDIO_open(&(ssd_testdrv_device.ssd_params)); if(ssd_testdrv_device.client_id <0) return -ENODEV; printk(" running enumerate\n"); for(j=0;j<80000;j++); ret = ssd_SDIO_enumerate(ssd_testdrv_device.client_id); if(ret<0){ ssd_SDIO_close(ssd_testdrv_device.client_id); return -ENODEV; } printk("finished enumeration process\n"); printk(" running load_vals\n"); ret = load_vals(ssd_testdrv_device.client_id,0x16800, 0x0, 0x8800, 0x300000); if(ret){ ssd_SDIO_close(ssd_testdrv_device.client_id); return -ENODEV; } return 0; } void is_alive_test(void) { ssd_SDIO_readSync(ssd_testdrv_device.client_id,0x16800 + 0x5674, ptr1[0], 4); printk("Read device ID via ReadSync: 0x%x (jiffies=%d)\n", *((unsigned int*)ptr1[0]), jiffies); *((unsigned int*)ptr[0]) = 0; ssd_SDIO_readByte(ssd_testdrv_device.client_id,0x16800 + 0x5674, &(ptr1[0][0])); ssd_SDIO_readByte(ssd_testdrv_device.client_id,0x16800 + 0x5675, &(ptr1[0][1])); ssd_SDIO_readByte(ssd_testdrv_device.client_id,0x16800 + 0x5676, &(ptr1[0][2])); ssd_SDIO_readByte(ssd_testdrv_device.client_id,0x16800 + 0x5677, &(ptr1[0][3])); printk("Read device ID via ReadByte: 0x%x (jiffies=%d)\n", *((unsigned int*)ptr1[0]), jiffies); } int sync_write_test(int number_of_transactions, int block_len) { int i; int ret = 0; for(i=0;i=basetime? endtime-basetime : 0xffffffff-basetime+endtime; exectime = jiffies_to_msecs(exectime); printk(": %d*%d bytes took %lu [msecs] ", number_of_transactions, block_len, exectime); if (exectime!=0) printk("=> %d [Mbps] (%d [kbs])\n", (int)((number_of_transactions*8*block_len)/(exectime*1000)), (int)((number_of_transactions*8*block_len)/exectime)); else printk("\n"); return ret; } #define DO_ON_ERROR(RETURN_VALUE, STRING) \ if (RETURN_VALUE!=0) \ { \ printk(STRING); \ return ret; \ } int do_test_use_case1(void) { int ret; ret = perform_test("Starting sync read test", sync_read_test, 10000, 512); DO_ON_ERROR(ret, "sync read test failed\n"); ret = perform_test("Starting sync write test", sync_write_test, 10000, 512); DO_ON_ERROR(ret, "sync write test failed\n"); ret = perform_test("Starting sync wr/rd compare test", sync_compare_test, 10000, 512); DO_ON_ERROR(ret, "sync wr/rd compare test failed\n"); g_bus_txn_context=TEST_CONTEXT; ret = perform_test("Starting async read test", async_read_test, 10000, 512); DO_ON_ERROR(ret, "async read test failed\n"); ret = perform_test("Starting async write test", async_write_test, 10000, 512); DO_ON_ERROR(ret, "async write test failed\n"); ret = perform_test("Starting async wr/rd comapre test", async_compare_test, 10000, 512); DO_ON_ERROR(ret, "async wr/rd compare test failed\n"); g_bus_txn_context=ISR; ret = perform_test("Starting async read test (ISR)", async_read_test, 10000, 512); DO_ON_ERROR(ret, "async read test (ISR) failed\n"); ret = perform_test("Starting async write test (ISR)", async_write_test, 10000, 512); DO_ON_ERROR(ret, "async write test (ISR) failed\n"); ret = perform_test("Starting async wr/rd compare test", async_compare_test, 10000, 512); DO_ON_ERROR(ret, "async wr/rd compare test (ISR) failed\n"); return ret; } int do_test_use_case2(void) { int ret, i; g_bus_txn_context=TEST_CONTEXT; for (i=0; i<2; ++i) { ret = perform_test("Starting sync read test", sync_read_test, 2, 64); DO_ON_ERROR(ret, "sync read test failed\n"); ret = perform_test("Starting sync write test", sync_write_test, 2, 64); DO_ON_ERROR(ret, "sync write test failed\n"); ret = perform_test("Starting async read test", async_read_test, 2, 64); DO_ON_ERROR(ret, "async read test failed\n"); ret = perform_test("Starting async write test", async_write_test, 2, 64); DO_ON_ERROR(ret, "async write test failed\n"); } return ret; } int do_test_use_case_ifx_1(void) { int ret; ret = perform_test("Starting sync read test", sync_read_test, 10000, 64); DO_ON_ERROR(ret, "sync read test failed\n"); ret = perform_test("Starting sync write test", sync_write_test, 10000, 64); DO_ON_ERROR(ret, "sync write test failed\n"); ret = perform_test("Starting sync wr/rd compare test", sync_compare_test, 10000, 64); DO_ON_ERROR(ret, "sync wr/rd compare test failed\n"); return ret; } int do_test_use_case_ifx_2(int flag, int number, int block_size) { int ret; if (flag & 1) { ret = perform_test("Starting sync read test", sync_read_test, number, block_size); DO_ON_ERROR(ret, "sync read test failed\n"); } if (flag & 2) { ret = perform_test("Starting sync write test", sync_write_test, number, block_size); DO_ON_ERROR(ret, "sync write test failed\n"); } if (flag & 4) { ret = perform_test("Starting sync wr/rd compare test", sync_compare_test, number, block_size); DO_ON_ERROR(ret, "sync wr/rd compare test failed\n"); } return ret; } int do_test_async_ifx_3(int flag, int number, int block_size) { int ret; if (flag & 1) { ret = perform_test("Starting async read test", async_read_test, number, block_size); DO_ON_ERROR(ret, "async read test failed\n"); } if (flag & 2) { ret = perform_test("Starting async write test", async_write_test, number, block_size); DO_ON_ERROR(ret, "async write test failed\n"); } if (flag & 4) { ret = perform_test("Starting async wr/rd compare test", async_compare_test, number, block_size); DO_ON_ERROR(ret, "async wr/rd compare test failed\n"); } return ret; } /* int do_test_ifx(int flag, int number, int block_size) { int ret,i,j; for(i=0;i<10;i++) { ptr2[i] = buf2+i*512; for (j=0; j<512; j+=4) { if (flag == 0 ) *((unsigned long*)(&(ptr2[i][j]))) = 0x0; else if (flag == 1) *((unsigned long*)(&(ptr2[i][j]))) = 0x11111111; else if (flag == 2) *((unsigned long*)(&(ptr2[i][j]))) = 0x22222222; else if (flag == 3) *((unsigned long*)(&(ptr2[i][j]))) = 0x33333333; else if (flag == 4) *((unsigned long*)(&(ptr2[i][j]))) = 0x44444444; else if (flag == 5) *((unsigned long*)(&(ptr2[i][j]))) = 0x55555555; else if (flag == 6) *((unsigned long*)(&(ptr2[i][j]))) = 0x66666666; else if (flag == 7) *((unsigned long*)(&(ptr2[i][j]))) = 0x77777777; else if (flag == 8) *((unsigned long*)(&(ptr2[i][j]))) = 0x88888888; else if (flag == 9) *((unsigned long*)(&(ptr2[i][j]))) = 0x99999999; else if (flag == 0xa) *((unsigned long*)(&(ptr2[i][j]))) = 0x5a5a5a5a; else if (flag == 0xb) *((unsigned long*)(&(ptr2[i][j]))) = 0xa5a5a5a5; else *((unsigned long*)(&(ptr2[i][j]))) = 0xffffffff; } } ret = perform_test("Starting sync wr/rd compare test", sync_compare_test_fix, number, block_size); DO_ON_ERROR(ret, "sync wr/rd compare test failed\n"); return ret; } */ unsigned long dump_buf(unsigned char* buf, int length, int dir); int testdrv2_init(void) { int ret; struct proc_dir_entry *ifx_switch_proc; printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); /* printk("ssd.o .text=%p\n", dump_buf); */ printk("testdrv.o .text=%p\n", noop_routine); init_buffers(); ifx_switch_proc = create_proc_entry(ifx_dev_name, 0, 0); if (!ifx_switch_proc) { printk(KERN_ERR "could not create /proc/%s!\n", ifx_dev_name); return -ENOENT; } ifx_switch_proc->read_proc = ifx_switch_read_procmem; ifx_switch_proc->write_proc = ifx_switch_write_procmem; ret = init_ssd(); /* DO_ON_ERROR(ret, "Inis ssd failed\n"); */ if (ret != 0) printk("Init ssd failed\n"); else is_alive_test(); /* #undef DO_IFX_TEST */ /* #define DO_IFX_TEST */ #ifdef DO_IFX_TEST { #define ADDR_OFFSET_WRITE 8 #define ADDR_OFFSET_READ 0x6c unsigned long val, addr; int iteration; int buffer[16] = { 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68/* , 72 */}; /* printk("Do Burst Write\n"); */ /* for (addr = 0; addr < sizeof(buffer)/sizeof(buffer[0]); addr++) */ /* buffer[addr] = (addr * 4) + ADDR_OFFSET_WRITE; */ /* ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, ADDR_OFFSET_WRITE, &buffer[0] /\* ptr[i%10] *\/, sizeof(buffer) /\* block_len *\/); */ /* if (ret) */ /* { */ /* printk("\n\nERROR in write burst, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); */ /* return ret; */ /* } */ /* printk("Burst Write done\n"); */ for (iteration = 1; iteration < 10; iteration++) { addr = 8; val = iteration+1; ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); val = iteration; ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); if (ret) { printk("ERROR in write single, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); return ret; } ret = ssd_SDIO_readSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); if (ret) { printk("ERROR in read single, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); return ret; } if (val != iteration) { printk("ERROR in write/read single, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); ret = ssd_SDIO_readSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); printk("ERROR in write/read single, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); } } for (iteration = 1; iteration < 2; iteration++) { printk("\n******************** Starting iteration %d (jiffies = %d)\n", iteration, jiffies); #if 1 for (addr = 8; addr < 256+8; addr+=4) { val = addr; ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); if (ret) { printk("\n\nERROR in write loop, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); return ret; } } printk("Do Burst Write 64\n"); for (addr = 0; addr < sizeof(buffer)/sizeof(buffer[0]); addr++) buffer[addr] = (addr * 4) + ADDR_OFFSET_WRITE; ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, ADDR_OFFSET_WRITE, &buffer[0] /* ptr[i%10] */, sizeof(buffer) /* block_len */); if (ret) { printk("\n\nERROR in write burst, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); return ret; } printk("Burst Write done 64\n"); for (addr = 8; addr < 256+8; addr+=4) { val = addr; ret = ssd_SDIO_readSync(ssd_testdrv_device.client_id, addr /* 0x00000008 */, &val /* ptr[i%10] */, 4 /* block_len */); if (ret || (val != addr)) { printk("\n\nERROR in read loop, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); /* return ret; */ } } #endif printk("Do Burst Read\n"); ret = ssd_SDIO_readSync(ssd_testdrv_device.client_id, ADDR_OFFSET_READ , buffer /* ptr[i%10] */, sizeof(buffer) /* block_len */); if (ret) { printk("\n\nERROR in read burst, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); return ret; } #if 1 for (addr = 0; addr < sizeof(buffer)/sizeof(buffer[0]); addr ++) if (buffer[addr] != ((addr*4) + ADDR_OFFSET_READ)) { printk("\n\nERROR in read burst compare, iteration=%d, addr=%d, val=%d\n", iteration, addr, buffer[addr]); } #endif printk("Burst Read done\n"); /* printk("Do Burst Write 68\n"); */ /* for (addr = 0; addr < sizeof(buffer)/sizeof(buffer[0]); addr++) */ /* buffer[addr] = (addr * 4) + ADDR_OFFSET_WRITE; */ /* ret = ssd_SDIO_writeSync(ssd_testdrv_device.client_id, ADDR_OFFSET_WRITE, &buffer[0] /\* ptr[i%10] *\/, sizeof(buffer)+4 /\* block_len *\/); */ /* if (ret) */ /* { */ /* printk("\n\nERROR in write burst, iteration=%d, addr=%d, val=%d, ret=%d\n", iteration, addr, val, ret); */ /* return ret; */ /* } */ /* printk("Burst Write done 68\n"); */ } } #endif /*DO_IFX_TEST */ /* printk("************** starting use case IFX 1 *********************\n"); */ /* printk("**** run IFX 1 *****\n"); */ /* do_test_use_case_ifx_1(); */ /* printk("************** starting use case 1 *************************\n"); */ /* printk("**** run 1 *****\n"); */ /* do_test_use_case1(); */ /* printk("**** run 2 *****\n"); */ /* do_test_use_case1(); */ /* printk("**** run 3 *****\n"); */ /* do_test_use_case1(); */ /* printk("**** run 4 *****\n"); */ /* do_test_use_case1(); */ //printk("************** starting use case 2 *************************\n"); //do_test_use_case2(); printk("\nFinished test\n"); return 0; /* ret; */ /* succeed */ } void testdrv2_cleanup(void) { kfree(buf); kfree(buf1); ssd_SDIO_close(ssd_testdrv_device.client_id); ssd_testdrv_device.client_id = -1; remove_proc_entry(ifx_dev_name, 0); } /* int init_module(void) */ /* { */ /* printk("%s:%s:%d TODO: Inititalization for Danube\n", __FILE__, __FUNCTION__, __LINE__); */ /* return 0; */ /* } */ /* copied from incaip bsp */ //#include #include //#include //#include //#include extern int ifx_sdio_controller_set_ops (int type, uint32_t data); int get_frequency(void) { } int set_frequency(long frequency) { return ifx_sdio_controller_set_ops(SD_SET_FREQENCY, frequency); } int ifx_show_buffers(int src_dest, int nr) { int i, j; unsigned char **p; // p = (src_dest == 0) ? ptr : ptr1; if (src_dest == 0) p=ptr; else if(src_dest == 1) p=ptr1; else p=ptr2; for (i = 0; i < 10; i++) { if ((i == nr) || (nr == -1)) { // printk("Ptr%s %d", (src_dest == 0) ? "" : "1", i); if (src_dest == 0 ) printk("Ptr %d", i); else if(src_dest == 1 ) printk("Ptr1 %d", i); else printk("Ptr2 %d", i); for (j = 0; j < 512; j+=4) { if ((j % 64) == 0) printk("\n%04x: ", j); printk("%08x ", *(unsigned int *)&p[i][j]); } printk("\n"); } } } int sync_read_word(int addr) { unsigned char val1, val2, val3, val4; int val; ssd_SDIO_readByte(ssd_testdrv_device.client_id, addr, &val1); ssd_SDIO_readByte(ssd_testdrv_device.client_id, addr+1, &val2); ssd_SDIO_readByte(ssd_testdrv_device.client_id, addr+2, &val3); ssd_SDIO_readByte(ssd_testdrv_device.client_id, addr+3, &val4); val = (val4 << 24) | (val3 << 16) | (val2 << 8) | val1; return val; } int sync_write_word(int addr, int val) { ssd_SDIO_writeByte(ssd_testdrv_device.client_id, addr, val & 0xff); ssd_SDIO_writeByte(ssd_testdrv_device.client_id, addr+1, (val >> 8) & 0xff); ssd_SDIO_writeByte(ssd_testdrv_device.client_id, addr+2, (val >> 16) & 0xff); ssd_SDIO_writeByte(ssd_testdrv_device.client_id, addr+3, (val >> 24) & 0xff); return val; } static struct switch_api_command { const char *name; const void *function; const char *param; /* i=int, l=long, s=string */ } commands[] = { { "ssd_SDIO_writeSync", ssd_SDIO_writeSync, "iisi"}, { "do_test_use_case_ifx_1", do_test_use_case_ifx_1, ""}, { "do_test_use_case_ifx_2", do_test_use_case_ifx_2, "iii"}, { "sync_read_test", sync_read_test, "ii" }, { "sync_write_test", sync_write_test, "ii" }, { "ifx_show_buffers", ifx_show_buffers, "ii" }, { "get_frequency", get_frequency, "" }, { "set_frequency", set_frequency, "i" }, { "sync_read_word", sync_read_word, "i" }, { "sync_write_word", sync_write_word, "ii" }, { "init_ssd", init_ssd, "" }, { "is_alive_test", is_alive_test, "" }, { "cli_dump_data_and_time", cli_dump_data_and_time, "ii" }, // { "do_test_ifx", do_test_ifx, "iii"}, { "do_test_async_ifx_3", do_test_async_ifx_3, "iii"}, { "do_test_use_case1", do_test_use_case1, "" }, }; static const char *get_string(const char **buffer, int *len) { const char *s1 = *buffer; const char *s2; int quoted = 0; while (*s1 == ' ') { s1++; } if ((*s1 == '\0') || (*s1 == '\n')) /* end of string */ { *len = 0; return NULL; } if (*s1 == '"') { quoted = 1; s1++; } s2 = s1; while ((*s2) && (*s2 != '\n')) { if (((*s2 == ' ') && (!quoted)) || ((*s2 == '"') && ( quoted)) || ((*s2 == ',') && (!quoted))) { break; } s2++; } *len = (s2 - s1); if (quoted && (*s2 == '"')) s2++; if (*s2 == ',') s2++; /* remove comma between arguments */ *buffer = s2; /* save start of next token */ /* { */ /* int i; */ /* printk("get_string: \""); */ /* for (i = 0; i < *len; i++) printk("%c", s1[i]); */ /* printk("\"\n"); */ /* } */ return s1; } static long atoi(const char *buffer, int len) { long val = 0; int hex = 0; if ((len > 2) && (buffer[0]=='0') && (buffer[1]=='x')) { hex = 1; len -= 2; buffer += 2; } while (*buffer && len) { if ((*buffer >= '0') && (*buffer <= '9')) { val = val * ((hex) ? 16 : 10) + (*buffer - '0'); } else if ((hex && (*buffer >= 'A') && (*buffer <= 'F')) || (hex && (*buffer >= 'a') && (*buffer <= 'f'))) { val = val * 16 + ((*buffer & ~0x20) - 'A' + 10); } else { printk("atoi: invalid character: '%c'\n", *buffer); return 0; } len--; buffer++; } return val; } static int ifx_switch_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data) { int len = 0, c; len += sprintf(buf+len,"Available commands:\n"); for (c = 0; c < (sizeof(commands)/sizeof(commands[0])); c++) { len += sprintf(buf+len, "\t%s\t%s\n", commands[c].name, commands[c].param); } *eof = 1; // No more data available return len; } static int ifx_switch_write_procmem(struct file *file, const char *buffer, unsigned long count, void *data) { const char *buf = buffer; const char *cmd; const char *parg_string; const char *arg; int slen, c; long cmd_arg[10]={}; /* max. 10 command arguments (integer/long/string) */ char cmd_arg_strings[100]; /* max 100 characters as string parameters */ int cmd_arg_str_offset = 0; int argc = 0; int ret = 0; cmd = get_string(&buf, &slen); if ((cmd == NULL) || (slen == 0)) { printk("No/invalid command specified (%s)\n", buffer); return -EINVAL; } for (c = 0; c < (sizeof(commands)/sizeof(commands[0])); c++) { if (strncmp(cmd, commands[c].name, slen) == 0) { /* yeah, we found our command */ /* printk("Command found: name=\"%s\", fct=%p, param=\"%s\"\n", */ /* commands[c].name, commands[c].function, commands[c].param); */ break; } } if (c >= (sizeof(commands)/sizeof(commands[0]))) { int i; printk("Command not found ("); for (i = 0; i < slen; i++) printk("%c", cmd[i]); printk(")\n"); return -EINVAL; } parg_string = commands[c].param; while ((*parg_string) && (argc < (sizeof(cmd_arg)/sizeof(cmd_arg[0])))) { arg = get_string(&buf, &slen); if ((arg == NULL) || (slen == 0)) { printk("Too few parameters for command \"%s\", required are \"%s\"\n", commands[c].name, commands[c].param); printk("arg=%p, slen=%d\n", arg, slen); return -EINVAL; } switch (*parg_string) { case 'i': case 'l': cmd_arg[argc++] = atoi(arg, slen); break; case 's': memcpy(&cmd_arg_strings[cmd_arg_str_offset], arg, slen); cmd_arg_strings[cmd_arg_str_offset + slen] = '\0'; cmd_arg[argc++] = (long)&cmd_arg_strings[cmd_arg_str_offset]; cmd_arg_str_offset += slen+1; break; default: printk("Invalid format string in module, please fix and re-compile\n"); return -EINVAL; } parg_string++; } arg = get_string(&buf, &slen); if ((arg != NULL) && (slen != 0)) { printk("Too many parameters for command \"%s\", required are \"%s\"\n", commands[c].name, commands[c].param); return -EINVAL; } /* This instructions casts the void pointer commands.function to a function that returns int and has 10 long parameters. Though the function actually called has a different argument list it works if the parameter are set up accordingly (e.g. int/long or string pointer) */ ret = ((int (*)(long,long,long,long,long,long,long,long,long,long))(commands[c].function)) (cmd_arg[0], cmd_arg[1], cmd_arg[2], cmd_arg[3], cmd_arg[4], cmd_arg[5], cmd_arg[6], cmd_arg[7], cmd_arg[8], cmd_arg[9]); printk("return value is: %d (0x%08x)\n", ret, ret); return count; } /* end copy from incaip bsp */ EXPORT_SYMBOL(do_test_use_case1); module_init(testdrv2_init); module_exit(testdrv2_cleanup);