📄 wmmx.c
字号:
channel = wmmx_usb_dma_configs[phys_ep].dma_channel; UDCCSN(phys_ep) |= UDCCSR_DME; wmmx_usb_dma_configs[phys_ep].size = endpoint->rcv_packetSize; /* Listen to the request */ DCSR(channel) = DCSR_NODESC | DCSR_EORIRQEN; DTADR(channel) = wmmx_usb_dma_configs[phys_ep].dma_phys_buffer; DSADR(channel) = PHYS_UDCDN(phys_ep); DCMD(channel) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_ENDIRQEN | DCMD_BURST32 | DCMD_WIDTH4 | endpoint->rcv_packetSize; DRCMRUDC(phys_ep) = channel | DRCMR_MAPVLD; DCSR(channel) |= DCSR_RUN; } }#endif if (!wmmx_usb_dma_configs[phys_ep].dma_enabled) { wmmx_enable_ep_interrupt(phys_ep, (UDC_INT_FIFOERROR | UDC_INT_PACKETCMP)); } } }}/* * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */void udc_disable_ep (unsigned int phys_ep){ dbg_init(1, "udc_disable_ep: disable endpoint %d", phys_ep); /* if the endpoint use PIO mode, we should disable the endpoint interrupts too. */ if (phys_ep < UDC_MAX_ENDPOINTS) { struct usb_endpoint_instance *endpoint; dbg_init(1, "endpoint descr 0x%08x", phys_ep_to_endpoints[phys_ep]); if ((endpoint = phys_ep_to_endpoints[phys_ep])) { phys_ep_to_endpoints[phys_ep] = NULL; usbd_flush_ep (endpoint); } else { return; } if (phys_ep == 0) { dbg_init(1, "ep0 - ignore"); } else if (endpoint->endpoint_address & 0x80) { /* IN */ if (wmmx_usb_dma_configs[phys_ep].dma_enabled) { if (wmmx_usb_dma_configs[phys_ep].dma_buffer) { consistent_free(wmmx_usb_dma_configs[phys_ep].dma_buffer, wmmx_usb_dma_configs[phys_ep].endpoint->tx_packetSize, wmmx_usb_dma_configs[phys_ep].dma_phys_buffer); wmmx_usb_dma_configs[phys_ep].dma_buffer = NULL; } pxa_free_dma(wmmx_usb_dma_configs[phys_ep].dma_channel); wmmx_dmach_to_configs[wmmx_usb_dma_configs[phys_ep].dma_channel] = NULL; wmmx_usb_dma_configs[phys_ep].dma_enabled = 0; } } else if (endpoint->endpoint_address) { /* OUT */ if (wmmx_usb_dma_configs[phys_ep].dma_enabled) { if (wmmx_usb_dma_configs[phys_ep].dma_buffer) { consistent_free(wmmx_usb_dma_configs[phys_ep].dma_buffer, wmmx_usb_dma_configs[phys_ep].endpoint->rcv_packetSize, wmmx_usb_dma_configs[phys_ep].dma_phys_buffer); wmmx_usb_dma_configs[phys_ep].dma_buffer = NULL; } pxa_free_dma(wmmx_usb_dma_configs[phys_ep].dma_channel); wmmx_dmach_to_configs[wmmx_usb_dma_configs[phys_ep].dma_channel] = NULL; wmmx_usb_dma_configs[phys_ep].dma_enabled = 0; } } }}/* * udc_connected - is the USB cable connected * * Return non-zeron if cable is connected. */int udc_connected (void){ return 1;}/* * udc_connect - enable pullup resistor * * Turn on the USB connection by enabling the pullup resistor. */void udc_connect (void){}/* * udc_disconnect - disable pullup resistor * * Turn off the USB connection by disabling the pullup resistor. */void udc_disconnect (void){}/* * udc_enable_interrupts - enable interrupts * * Switch on UDC interrupts. * */void udc_all_interrupts (struct usb_device_instance *device){ int i; UDCICR1 = (UDCICR1_IESU | UDCICR1_IERU | UDCICR1_IERS | UDCICR1_IECC) & ~UDCICR1_IESOF; /* always enable control endpoint */ wmmx_enable_ep_interrupt(0, /*UDC_INT_FIFOERROR |*/ UDC_INT_PACKETCMP); for (i = 1; i < UDC_MAX_ENDPOINTS; i++) { if (phys_ep_to_endpoints[i] && phys_ep_to_endpoints[i]->endpoint_address) { wmmx_enable_ep_interrupt(i, UDC_INT_FIFOERROR | UDC_INT_PACKETCMP); } } }/* * udc_suspended_interrupts - enable suspended interrupts * * Switch on only UDC resume interrupt. * */void udc_suspended_interrupts (struct usb_device_instance *device){ UDCICR1 = (UDCICR1 | UDCICR1_IERS | UDCICR1_IERU | UDCICR1_IECC | UDCICR1_IESU) & ~UDCICR1_IESOF;}/* * udc_disable_interrupts - disable interrupts. * * switch off interrupts */void udc_disable_interrupts (struct usb_device_instance *device){ /* disable sof interrupt */ /* disable suspend and resume interrupt */ /* disable endpoint interrupts */ UDCICR0 = UDCICR1 = 0x00000000;}/* * udc_ep0_packetsize - return ep0 packetsize */int udc_ep0_packetsize (void){ return EP0_PACKETSIZE;}/* * udc_enable - enable the UDC * * Switch on the UDC */void udc_enable (struct usb_device_instance *device){ udc_device = device; dbgENTER(dbgflg_usbdbi_init, 1); if (!ep0_urb) { ep0_urb = usbd_alloc_urb(device, device->function_instance_array, 0, 512); if (!ep0_urb) { printk(KERN_ERR "udc_enable: usbd_alloc_urb failed\n"); } } else { printk (KERN_ERR "udc_enable: ep0_urb already allocated\n"); } /* enable UDC clock */ CKEN |= CKEN11_USB; /* enable UDC controller */ UDCCR = UDCCR_UDE; /* * If UDCCR_EMCE is set, we should reduce the number of the * configuration automatically or just yelled. */ if ((UDCCR & UDCCR_EMCE) == UDCCR_EMCE) { printk(KERN_ERR "udc_enable: Endpoint memory configure " "error\n"); UDCCR = UDCCR_EMCE; }}/* * udc_disable - disable the UDC * * Switch off the UDC */void udc_disable (void){ dbgENTER(dbgflg_usbdbi_init, 1); /* disable UDC controller */ UDCCR &= ~(UDCCR_UDE); /* disable UDC clock */ CKEN &= ~CKEN11_USB; /* reset device pointer */ udc_device = NULL; /* ep0 urb */ if (ep0_urb) { usbd_dealloc_urb (ep0_urb); ep0_urb = 0; } else printk (KERN_ERR "udc_disable: ep0_urb already NULL\n");}/* * udc_startup_events - allow udc code to do any additional startup */void udc_startup_events (struct usb_device_instance *device){ dbgENTER(dbgflg_usbdbi_init, 1); udc_configuration_enable(device); usbd_device_event(device, DEVICE_INIT, 0); usbd_device_event(device, DEVICE_CREATE, 0); usbd_device_event(device, DEVICE_HUB_CONFIGURED, 0); usbd_device_event(device, DEVICE_RESET, 0);}/* Proc Filesystem */#ifdef WMMX_TRACE#ifdef CONFIG_USBD_PROCFS/* * wmmx_proc_read - implement proc file system read. * @file * @buf * @count * @pos * * Standard proc file system read function. */ static ssize_t wmmx_proc_read(struct file *file, char *buf, size_t count, loff_t * pos){ unsigned long page; int len = 0; int index; int i; MOD_INC_USE_COUNT; /* get a page, max 4095 bytes of data... */ if (!(page = get_free_page (GFP_KERNEL))) { MOD_DEC_USE_COUNT; return -ENOMEM; } len = 0; index = (*pos)++; if (index == 0) { len += sprintf ( (char *) page + len, " Index Ints Jifs Ticks\n"); } if (index < trace_next) { u64 jifs = 1111; u32 ticks = 2222; wmmx_trace_t *p = wmmx_traces + index; unsigned char *cp; if (index > 0) { u32 ocsr = wmmx_traces[index-1].ocsr; ticks = (p->ocsr > ocsr) ? (p->ocsr - ocsr) : (ocsr - p->ocsr); jifs = p->jiffies - wmmx_traces[index-1].jiffies; } len += sprintf((char *)page + len, "%8d %8d %8llu ", index, p->interrupts, jifs); if (ticks > 1024 * 1024) { len += sprintf((char *)page + len, "%8dM ", ticks>>20); } else { len += sprintf((char *)page + len, "%8d ", ticks); } switch (p->trace_type) { case wmmx_regs: len += sprintf((char *) page + len, "CS0[%02x] %s\n", p->trace.regs.cs0, p->trace.regs.msg); break; case wmmx_setup: cp = (unsigned char *)&p->trace.setup; len += sprintf((char *)page + len, " -- request " "[%02x %02x %02x %02x %02x %02x %02x " "%02x]\n", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); break; case wmmx_xmit: len += sprintf((char *) page + len, " -- sending [%02x]\n", p->trace.xmit.size); break; case wmmx_ccr: len += sprintf((char *) page + len, "CCR[%02x] %s\n", p->trace.ccr.ccr, p->trace.ccr.msg); break; case wmmx_iro: len += sprintf((char *) page + len, "IRO[%02x] %s\n", p->trace.iro.iro, p->trace.iro.msg); break; case wmmx_xfer: cp = (unsigned char *)&p->trace.xfer.data; len += sprintf((char *)page + len, "%s xfer of %d bytes:", (p->trace.xfer.dir == WMMX_XFER_DIR_OUT) ? "OUT" : "IN", p->trace.xfer.size); for (i = 0; i < MIN(p->trace.xfer.size, WMMX_XFER_MAX_TRACE_SIZE); i++) { len += sprintf((char *)page + len, " %02x", (p->trace.xfer.data[i]) & 0xff); } len += sprintf((char *)page + len, "\n"); break; } } if (len > count) { len = -EINVAL; } else if (len > 0 && copy_to_user (buf, (char *) page, len)) { len = -EFAULT; } free_page (page); MOD_DEC_USE_COUNT; return len;}/* * wmmx_proc_write - implement proc file system write. * @file * @buf * @count * @pos * * Proc file system write function, used to signal monitor actions complete. * (Hotplug script (or whatever) writes to the file to signal the completion * of the script.) An ugly hack. */static ssize_t wmmx_proc_write(struct file *file, const char *buf, size_t count, loff_t * pos){ return count;}static struct file_operations wmmx_proc_operations_functions = { read:wmmx_proc_read, write:wmmx_proc_write,};#endif#endif/* * udc_name - return name of USB Device Controller */char *udc_name (void){ return UDC_NAME;}/* * udc_request_udc_irq - request UDC interrupt * * Return non-zero if not successful. */int udc_request_udc_irq (){ dbgENTER(dbgflg_usbdbi_init, 1); if (request_irq(IRQ_USB, wmmx_int_hndlr, SA_INTERRUPT | SA_SAMPLE_RANDOM, UDC_NAME " USBD Bus Interface", NULL) != 0) { printk (KERN_INFO "usb_ctl: Couldn't request USB irq\n"); return -EINVAL; } return 0;}/* * udc_request_cable_irq - request Cable interrupt * * Return non-zero if not successful. */int udc_request_cable_irq(){ return 0;}/* * udc_request_udc_io - request UDC io region * * Return non-zero if not successful. */int udc_request_io (){#ifdef WMMX_TRACE#ifdef CONFIG_USBD_PROCFS if (!(wmmx_traces = vmalloc(sizeof(wmmx_trace_t) * TRACE_MAX))) { printk(KERN_ERR "WMMX_TRACE malloc failed %p %d\n", wmmx_traces, sizeof(wmmx_trace_t) * TRACE_MAX); } else { printk(KERN_ERR "WMMX_TRACE malloc ok %p\n", wmmx_traces); } WMMX_REGS(0,"init"); WMMX_REGS(0,"test"); { struct proc_dir_entry *p; if ((p = create_proc_entry("wmmx", 0, 0)) == NULL) { printk(KERN_INFO"WMMX PROC FS failed\n"); } else { printk(KERN_INFO"WMMX PROC FS Created\n"); p->proc_fops = &wmmx_proc_operations_functions; } }#endif#endif return 0;}/* * udc_release_release_io - release UDC io region */void udc_release_io (){#ifdef WMMX_TRACE#ifdef CONFIG_USBD_PROCFS unsigned long flags; dbgENTER(dbgflg_usbdbi_init, 1); save_flags_cli (flags); remove_proc_entry ("wmmx", NULL); if (wmmx_traces) { wmmx_trace_t *p = wmmx_traces; wmmx_traces = 0; vfree(p); dbg_init(1, "trace memory is released"); } restore_flags (flags);#endif#endif}/* * udc_release_udc_irq - release UDC irq */void udc_release_udc_irq (){ dbgENTER(dbgflg_usbdbi_init, 1); free_irq (IRQ_USB, NULL);}/* * udc_release_cable_irq - release Cable irq */void udc_release_cable_irq (){}/* * udc_regs - dump registers * * Dump registers with printk */void udc_regs (void){ printk ("[%d:%d] CCR[%08x] UDUICR[%08x %08x] UFN[%08x] UDCCS[%08x]\n", udc_interrupts, jifs(), UDCCR, UDCICR0, UDCICR1, UDCFNR, UDCCSR0);}void wmmx_print(void){ printk("%08x %08x\n", UDCCSN(1), UDCCSN(2));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -