opl_cpuif.c
浏览该文件的文档。00001 00015 #include <linux/init.h> 00016 #include <linux/kernel.h> 00017 #include <linux/module.h> 00018 #include <linux/sched.h> 00019 #include <linux/wait.h> 00020 #include <asm/uaccess.h> 00021 #include <asm/io.h> 00022 #include <linux/slab.h> 00023 #include <linux/types.h> 00024 #include <linux/errno.h> 00025 00026 00027 #include <ipmux_interrupt.h> 00028 #include <opl_cpuif.h> 00032 /*--------------------------Macro definition------------------------- */ 00033 #define OPL_HOST_MAJOR 130 00034 #define OPL_HOST_NAME "opl_cpuif" 00035 00036 #define IPMUX_DMA_NUMS 4 00037 #define OPL_DMA_VAL_MAX 2048 00038 00039 00045 /*--------------------------type definition------------------------- */ 00046 00047 00048 00049 00055 /*-----------------global varible/function declaration--------------- */ 00056 extern void ipmux_irq_enable(unsigned int irq); 00057 extern void ipmux_irq_disable(unsigned int irq); 00058 00064 /*-------------------local function declaration---------------------- */ 00065 00066 00067 00068 00069 00076 /*--------------local variable declaration and definition------------- */ 00077 static int opl_host_open(struct inode *inode, struct file *filp); 00078 static ssize_t opl_host_read(struct file *filp, char *buffer, size_t length, loff_t *offset); 00079 static ssize_t opl_host_write(struct file *filp, const char *buffer, size_t length, loff_t *offset); 00080 static int opl_host_release(struct inode *inode, struct file *filp); 00081 static int opl_host_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,u32 arg); 00082 00083 static void host_dma0_isr(int irq,void *dev_id,struct pt_regs *regs); 00084 00085 static u32 tx_phys_addr[IPMUX_DMA_NUMS]={0}; 00086 static u32 rx_phys_addr[IPMUX_DMA_NUMS]={0}; 00087 00088 static char *dma0_rx_buf=NULL; 00089 static char *dma0_tx_buf=NULL; 00090 00091 static u32 order = 0; 00092 static u32 opl_host_is_open = 0; 00093 static u32 opl_host_open_count = 0; 00094 static u32 opl_host_dma0_irq_event = 0; 00095 static wait_queue_head_t opl_host_dma0_waitq; 00096 struct file_operations opl_host_fops = { 00097 .open = opl_host_open, 00098 .read = opl_host_read, 00099 .write = opl_host_write, 00100 .release = opl_host_release, 00101 .ioctl = opl_host_ioctl, 00102 }; 00103 00104 00111 /*------------------global variable and function exported-------------- */ 00112 00113 00121 /*----------------------local function definition--------------------- */ 00122 00134 static void host_dma0_isr(int irq,void *dev_id,struct pt_regs *regs) 00135 { 00136 if(test_and_set_bit(0,&opl_host_dma0_irq_event)){ 00137 /* TBD: add some debug message here */ 00138 } 00139 wake_up_interruptible(&opl_host_dma0_waitq); 00140 } 00141 00142 00143 static int opl_host_open(struct inode *inode,struct file *filp) 00144 { 00145 if(test_and_set_bit(0,&opl_host_is_open)){ 00146 printk(KERN_DEBUG "the device is opened\n"); 00147 } 00148 opl_host_open_count ++; 00149 MOD_INC_USE_COUNT; 00150 return 0; 00151 } 00152 00153 static int opl_host_release(struct inode *inode,struct file *filp) 00154 { 00155 opl_host_open_count --; 00156 if(!opl_host_open_count) 00157 clear_bit(0,&opl_host_is_open); 00158 00159 MOD_DEC_USE_COUNT; 00160 return 0; 00161 } 00162 00163 static ssize_t opl_host_read(struct file *filp, char *buffer, size_t length, loff_t *offset) 00164 { 00165 return 0; 00166 } 00167 00168 static ssize_t opl_host_write(struct file *filp,const char *buf,size_t length,loff_t *offset) 00169 { 00170 return 0; 00171 } 00172 00194 static int opl_host_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,u32 arg) 00195 { 00196 int status = 0; 00197 if(!test_bit(0,&opl_host_is_open)){ 00198 return -ENODEV; 00199 } 00200 switch(cmd){ 00201 case GET_IPMUX_DMA_TX_PHYS_ADDR: 00202 { 00203 int dmas= 0; 00204 dma_request_phys_addr_t *req = (dma_request_phys_addr_t *)arg; 00205 if(copy_from_user(&dmas,&req->dmas,4)){ 00206 } 00207 if(tx_phys_addr[dmas]){ 00208 if(copy_to_user(&req->phys_addr,&tx_phys_addr[dmas],4)){ 00209 } 00210 }else{ 00211 /* for others dma,not for dma0. */ 00212 } 00213 } 00214 break; 00215 case GET_IPMUX_DMA_RX_PHYS_ADDR: 00216 { 00217 int dmas= 0; 00218 dma_request_phys_addr_t *req = (dma_request_phys_addr_t *)arg; 00219 if(copy_from_user(&dmas,&req->dmas,4)){ 00220 } 00221 if(rx_phys_addr[dmas]){ 00222 if(copy_to_user(&req->phys_addr,&rx_phys_addr[dmas],4)){ 00223 } 00224 }else{ 00225 /* for others dma,not for dma0. */ 00226 } 00227 } 00228 break; 00229 case SET_IPMUX_DMA_TX_BUF_DATA: 00230 { 00231 dma_request_data_t req; 00232 if(copy_from_user(&req,(char *)arg,sizeof(dma_request_data_t))){ 00233 } 00234 int dmas = req.dmas; 00235 int bd = req.bd; 00236 int len = req.len; 00237 if(copy_from_user((char *)(tx_phys_addr[dmas]+bd*OPL_DMA_VAL_MAX),req.buf,len)){ 00238 } 00239 } 00240 break; 00241 case GET_IPMUX_DMA_RX_BUF_DATA: 00242 { 00243 dma_request_data_t req; 00244 if(copy_from_user(&req,(char *)arg,sizeof(dma_request_data_t))){ 00245 } 00246 int dmas = req.dmas; 00247 int bd = req.bd; 00248 int len = req.len; 00249 if(dmas<2){ 00250 if(copy_to_user(((dma_request_data_t *)arg)->buf, 00251 (char *)(rx_phys_addr[dmas]+bd*OPL_DMA_VAL_MAX),len)){ 00252 } 00253 } 00254 } 00255 break; 00256 case ENABLE_IPMUX_HOST_DMA0_INTERRUPT: 00257 { 00258 ipmux_irq_enable(OPL_HOSTDMA0_IRQ); 00259 } 00260 break; 00261 case DISABLE_IPMUX_HOST_DMA0_INTERRUPT: 00262 { 00263 ipmux_irq_disable(OPL_HOSTDMA0_IRQ); 00264 } 00265 break; 00266 case WAIT_FOR_IPMUX_HOST_DMA0_INTERRUPT: 00267 { 00268 wait_event_interruptible(opl_host_dma0_waitq,opl_host_dma0_irq_event); 00269 if(!test_and_clear_bit(0,&opl_host_dma0_irq_event)){ 00270 printk(KERN_ALERT "clear opl_host_dma0_irq_event failed \n"); 00271 return -1; 00272 } 00273 } 00274 break; 00275 default: 00276 break; 00277 } 00278 return status; 00279 } 00280 00289 static int __init opl_host_dma_init(void) 00290 { 00291 int ret = 0; 00292 int count = 0; 00293 int size = 2*64*OPL_DMA_VAL_MAX; 00294 00295 ret = register_chrdev(OPL_HOST_MAJOR,OPL_HOST_NAME,&opl_host_fops); 00296 if(ret < 0){ 00297 /* add debug Message TBD */ 00298 return -1; 00299 } 00300 00301 for (count = PAGE_SIZE, order = 0; count < size; order++, count <<= 1) 00302 ; 00303 dma0_rx_buf =(char*) __get_free_pages(GFP_KERNEL| GFP_DMA, order); 00304 if(!dma0_rx_buf){ 00305 goto fail1; 00306 } 00307 memset(dma0_rx_buf,0,size); 00308 dma0_tx_buf = &dma0_rx_buf[64*OPL_DMA_VAL_MAX]; 00309 rx_phys_addr[0] = (u32)dma0_rx_buf|0xa0000000; /* for mips uncacheable memory. */ 00310 tx_phys_addr[0] = (u32)dma0_tx_buf|0xa0000000; 00311 00312 init_waitqueue_head(&opl_host_dma0_waitq); 00313 ret = request_irq(OPL_HOSTDMA0_IRQ,host_dma0_isr,0,"IPMux dma0",NULL); 00314 if(ret){ 00315 /* add error message */ 00316 goto fail2; 00317 } 00318 return 0; 00319 fail1: 00320 ret = unregister_chrdev(OPL_HOST_MAJOR,OPL_HOST_NAME); 00321 fail2: 00322 free_pages((u32)dma0_rx_buf,order); 00323 return -1; 00324 } 00325 00333 static void __exit opl_host_dma_exit(void) 00334 { 00335 int ret = 0; 00336 00337 free_irq(OPL_HOSTDMA0_IRQ,NULL); 00338 free_pages((u32)dma0_rx_buf,order); 00339 ret = unregister_chrdev(OPL_HOST_MAJOR,OPL_HOST_NAME); 00340 if(ret<0){ 00341 /* add debug Message TBD */ 00342 } 00343 } 00344 00345 module_init(opl_host_dma_init); 00346 module_exit(opl_host_dma_exit); 00347 MODULE_LICENSE("GPL2"); 00348 MODULE_AUTHOR("opulan Inc"); 00349 MODULE_DESCRIPTION("opulan IPMUX-e switch chip driver module"); 00350
Generated at Mon Jul 30 16:43:48 2007 for IPMUX1IPMUX2IPMUX3 by 1.3.9.1