typedef void VOID; typedef void* PVOID; #define LINUX_OS_FILES /* * Benchmark tracing utility */ #include #include #include #include #include #include #include #include "register_access.h" #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif #define BUFSIZE 1024 int Quiet=1; unsigned long last_read=0; /* WLAN 1350 definition (from morpheus_vlynq_setup.h)*/ #define VLYNQ_TNETW1X50_MEM_OFFSET 0x00000000 /* Physical address of TNETW1150 memory */ #define VLYNQ_TNETW1X50_MEM_SIZE 0x00080000 /* Total size of the TNETW1150 memory */ #define VLYNQ_TNETW1X50_REG_OFFSET 0x00300000 /* PHYS_ADDR of TNETW1150 control registers */ #define VLYNQ_TNETW1X50_REG_SIZE 0x00100000 /* Size of TNETW1150 registers area, MAC+PHY */ extern unsigned long wlan_mem_addr; /* WLAN memory base */ extern unsigned long wlan_reg_addr; /* WLAN register area base */ // we still need these 2 buffers for the loopback until remapping is done unsigned long SourceDataBuffer[BUFSIZE]; unsigned long DestinationDataBuffer[BUFSIZE]; EXPORT_SYMBOL(SourceDataBuffer); EXPORT_SYMBOL(DestinationDataBuffer); #ifdef CONFIG_WLAN_VLYNQ_TEST struct semaphore ra_semaphore; int ra_pending_interrputs = 0; #endif // CONFIG_WLAN_VLYNQ_TEST typedef struct { int print_level; int nusers; } ra_control_t; static ra_control_t *ra_control; static inline int ra_control_size(void) { return sizeof(ra_control_t); } static void usage(void) { printk("Register access proc usage: \n"); printk(" r|R|w|W src_addr [value] \n"); printk(" for read use r|R \n"); printk(" for write use w|W with value\n"); printk(" src_addres is 32 hex address\n"); printk(" value is 32 hex address\n"); printk("Reading from 0x0123abcd: \n"); printk(" w 0123abcd \n"); printk("Writing 0x55aa55aa to 0x0123abcd: \n"); printk(" w 0123abcd 55aa55aa \n"); printk(" q|Q - Quiet mode (toggle). DEFUALT is Quiet! \n"); } static int ra_res_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int len=0; len = sprintf(page, "%x\n",(unsigned int)last_read); *eof = 1; if (!Quiet) printk("Read_proc %X\n", (unsigned int)last_read); return len; } static void ra_reset(int print_level) { memset(ra_control, 0, sizeof(ra_control_t)); ra_control->nusers = 1; ra_control->print_level = print_level; #ifdef DEBUG printk("%s: print_level=%d\n", __FUNCTION__, ra_control->print_level); #endif } static void ra_read_reg(const char* buffer, int print_level, unsigned long base) { unsigned long *reg, *addr; unsigned long value; sscanf(buffer, "%X", (unsigned int *)®); addr = (unsigned long *)((unsigned long)reg + base); value = *addr; if (!Quiet) printk("The value at %X is %X\n", (unsigned int)reg, (unsigned int)value); last_read = value; } static void ra_write_reg(const char* buffer, int print_level, unsigned int base) { unsigned long *reg; unsigned long value; sscanf(buffer, "%X %X", (unsigned int *)®, (unsigned int *)&value); if (!Quiet) printk("Writing %X to %X\n", (unsigned int)value, (unsigned int)reg); reg = (unsigned long *)((unsigned long)reg + base); *reg = value; } #ifdef CONFIG_WLAN_VLYNQ_TEST VOID os_cacheFlushRange(PVOID startAddr, size_t size) { consistent_sync(startAddr, size, DMA_BIDIRECTIONAL); } VOID os_cacheInvalidateRange(PVOID startAddr, size_t size) { consistent_sync(startAddr, size, DMA_FROM_DEVICE); } static int ra_check_buf_params(unsigned long length) { if (length == 0) { printk("ra_buf zero length !\n"); return 0; } if (length > BUFSIZE) { printk("ra_buf length - %d > %d !\n",(int)length, BUFSIZE); return 0; } if (length % 4) { printk("ra_buf length - %d not aligned !\n",(int)length); return 0; } return (1); } static void ra_read_buf(const char* buffer, int print_level) { unsigned long count, length, *bufp; sscanf(buffer, "%d %d", (int *)&length, (int *)&count); // printk("ra_read_buf() length = %d, count = %d\n",length,count); if (!ra_check_buf_params(length)) return; if (down_interruptible(&ra_semaphore)) printk("down_interruptible(&ra_semaphore) FAILED !\n"); bufp = (unsigned long *)&DestinationDataBuffer[length/sizeof(long) - 1]; // dmac_inv_range((int)&DestinationDataBuffer, (int)&DestinationDataBuffer[length]); os_cacheInvalidateRange(&DestinationDataBuffer, length); if (*bufp != count) printk ("ra_read_buf() read %d instead of %d at DestinationDataBuffer[%d] ! (pending_interrputs = %d)\n", (int)*bufp,(int)count,(int)length, ra_pending_interrputs ); } static void ra_write_buf(const char* buffer, int print_level) { unsigned long count, length, *bufp; sscanf(buffer, "%d %d", (int *)&length, (int *)&count); // printk("ra_write_buf() length = %d, count = %d\n",length,count); if (!ra_check_buf_params(length)) return; bufp = (unsigned long *)&SourceDataBuffer[length/sizeof(long) - 1]; *bufp = count; // Mark the data buf os_cacheFlushRange(&SourceDataBuffer, length); bufp = (unsigned long *)0xcc088a10; *bufp = length; // length in bytes into SCR_PAD2 ra_pending_interrputs += 1; bufp = (unsigned long *)0xcc083874; *bufp = 4; // TX proc } #endif // CONFIG_WLAN_VLYNQ_TEST static unsigned long ra_get_base(char target) { unsigned long base; switch (target) { case 'r': // WLAN Registers case 'R': base = wlan_reg_addr;// - VLYNQ_TNETW1X50_REG_OFFSET; break; case 'm': // WLAN Memory case 'M': base = wlan_mem_addr;// - VLYNQ_TNETW1X50_MEM_OFFSET; break; default: base = 0; break; } return base; } static inline int ra_res_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { int print_level = ra_control->print_level; unsigned long base; switch (buffer[0]) { case 'r': case 'R': base = ra_get_base(buffer[1]); ra_read_reg(&buffer[3], print_level, base); break; case 'w': case 'W': base = ra_get_base(buffer[1]); ra_write_reg(&buffer[3], print_level, base); break; case 'q': case 'Q': if (Quiet) Quiet=0; else Quiet=1; printk("Changed Quiet mode to %d\n",Quiet); break; #ifdef CONFIG_WLAN_VLYNQ_TEST case 'i': case 'I': if (down_interruptible(&ra_semaphore)) printk("down_interruptible(&ra_semaphore) FAILED !\n"); else printk("Interrupt\n"); break; case 'b': case 'B': switch (buffer[1]) { case 'r': case 'R': ra_read_buf(&buffer[3], print_level); break; case 'w': case 'W': ra_write_buf(&buffer[3], print_level); break; } break; #endif // CONFIG_WLAN_VLYNQ_TEST default: usage(); }; return count; } /* Initialization */ int ra_init(void) { struct proc_dir_entry *res; if (ra_control) { ++ra_control->nusers; return 0; } ra_control = (ra_control_t *)kmalloc(ra_control_size(), GFP_KERNEL); if (!ra_control) return -ENOMEM; ra_reset(0); res = create_proc_entry("reg_access", 0, NULL); if (res) { res->read_proc = ra_res_read_proc; res->write_proc = ra_res_write_proc; res->data = NULL; } #ifdef CONFIG_WLAN_VLYNQ_TEST sema_init(&ra_semaphore, 0); #endif return 0; } /* De-initialization */ void ra_destroy(void) { if (--ra_control->nusers) return; remove_proc_entry("reg_access", NULL); kfree( ra_control ); }