📄 usb_pdc.c
字号:
} /* End of pdc_open_pipe() *//* * Close an already opened pipe * @pipe_handle: pipe handle */void pdc_close_pipe(pdc_pipe_handle_t pipe_handle){ __u8 ep; struct pdc_pipe *pipe; struct pdc_dev *pdc=usb_devices; func_debug(("pdc_close_pipe(pipe_handle=%x)\n",pipe_handle)) if(pipe_handle < PDC_MAX_PIPES) { pipe = pdc->ep_pipes + pipe_handle; /* If the pipe is opened then cleanup the stuff */ if(pipe->ep_state == PDC_PIPE_OPEN) { pipe->pipe_desc = NULL; pipe->ep_state = PDC_PIPE_CONFIG; } /* * Get the endpoint and if it is control ep then close * the control IN pipe also */ ep = pdc_pipe_to_epreg(pipe_handle); if(ep == 0) { pdc_close_pipe(pipe_handle + 1); } }} /* End of pdc_close_pipe() */int pdc_submit_control_urb(struct pdc_dev *pdc, struct pdc_urb *urb_req){ struct pdc_pipe *pipe; struct pdc_urb *urb; unsigned long length; pdc_pipe_handle_t handle = urb_req->pipe; func_debug(("pdc_submit_control_urb(urb=%p)\n",urb_req)) if(urb_req->operation == PDC_OPR_WRITE) handle += 1; /* Control IN pipe */ pipe = pdc->ep_pipes + handle; urb = pipe->urb; /* Insert the URB in to the pipe URB queue (FIFO) */ if(!urb) { pipe->urb = urb_req; } else { while(urb) { if(urb->next != NULL) urb = urb->next; else urb->next = urb_req; } } /* set the output parameters */ urb_req->actual_length = 0; urb_req->next = NULL; if(urb_req->operation == PDC_OPR_WRITE) { if(pipe->urb == urb_req) { length = urb_req->transfer_buffer_length; if(urb_req->transfer_buffer_length > pipe->ep_desc->max_pkt_size) { length = pipe->ep_desc->max_pkt_size; } writeendpoint(handle,urb_req->transfer_buffer,length); urb_req->actual_length += length; } if(urb_req->actual_length == urb_req->transfer_buffer_length) { urb_req->status = PDC_URB_COMPLETE; pipe->urb = urb_req->next; if(urb_req->complete) urb_req->complete(urb); } } else if(urb_req->operation == PDC_OPR_READ) { /* TODO */ } return 0;}/* * Submit an urb for data transfer * @urb: urb request block */int pdc_submit_urb(struct pdc_urb *urb_req){ struct pdc_pipe *pipe; struct pdc_urb *urb; unsigned long flags; struct pdc_dev *pdc=usb_devices; func_debug(("pdc_submit_urb(urb=%p)\n",urb_req)) if(urb_req->pipe > PDC_MAX_PIPES) return -EINVAL; if(urb_req->pipe < 2) return pdc_submit_control_urb(pdc, urb_req); pipe = pdc->ep_pipes + urb_req->pipe; spin_lock_irqsave(&pdc_rdwr_lock, flags); urb = pipe->urb; /* Insert the URB in to the pipe URB queue (FIFO) */ if(!urb) { pipe->urb = urb_req; } else { while(urb) { if(urb->next != NULL) urb = urb->next; else urb->next = urb_req; } } /* set the output parameters */ urb_req->actual_length = 0; urb_req->next = NULL; if(urb_req->operation == PDC_OPR_READ) { /* * handle the read request, if there are no URB's, * call the rx_data function */ if(pipe->urb == urb_req) { rx_data(pdc, urb_req->pipe); } } else if(urb_req->operation == PDC_OPR_WRITE) { /* * Handle the write request. * If the Pipe is not stalled and the transmission is idle * start the transmission */ pipe->ep_status = (pdc_read16(CMD_CHECKEPSTATUS+(urb_req->pipe)) & STATUS_EPSTAL) ? PDC_PIPE_STALL : PDC_PIPE_UNSTALL ; if(pipe->txrx_idle && pipe->ep_status != PDC_PIPE_STALL) { tx_data(pdc, urb_req->pipe, 1); /* Kick the transfer */ } } spin_unlock_irqrestore(&pdc_rdwr_lock, flags); return 0;} /* End of pdc_submit_urb *//* * Cancel an urb for data transfer * @urb: urb request block */int pdc_cancel_urb(struct pdc_urb *urb_req){ struct pdc_pipe *pipe; struct pdc_urb *urb, *prev_urb; unsigned long flags; struct pdc_dev *pdc=usb_devices; func_debug(("pdc_cancel_urb(%p)\n",urb_req)) /* Check the pipe value */ if(urb_req->pipe > PDC_MAX_PIPES) return -EINVAL; pipe = pdc->ep_pipes + urb_req->pipe; if((urb_req->pipe == 0) && (urb_req->operation == PDC_OPR_WRITE)) { /* Special case of control IN pipe */ pipe++; } spin_lock_irqsave(&pdc_rdwr_lock, flags); prev_urb = NULL; urb = pipe->urb; /* * search for the URB , The pipe could be either IN or OUT so there is * only one URB list */ while((urb!=NULL) && (urb_req != urb)) { prev_urb = urb; urb = urb->next; } /* * found URB, then Un link it from the list */ if(urb) { urb->status = PDC_URB_COMPLETE; if(prev_urb) prev_urb->next = urb->next; else pipe->urb = urb->next; } spin_unlock_irqrestore(&pdc_rdwr_lock, flags); return 0;} /* End of pdc_cancel_urb *//* * Pipe operations * @pipe_opr: */int pdc_pipe_operation(struct pdc_pipe_opr *pipe_opr){ struct pdc_pipe *pipe; __u16 status; struct pdc_dev *pdc=usb_devices; pdc_pipe_handle_t handle = pipe_opr->handle; func_debug(("pdc_pipe_control(pipe_opr=%p)\n",pipe_opr)) if(handle < PDC_MAX_PIPES) { pipe = pdc->ep_pipes + handle; switch(pipe_opr->opr) { case PDC_PIPE_STALL: pdc_command(CMD_STALLEP+handle); if(handle == EP0OUT) pdc_command(CMD_STALLEP+handle+1); /* Stall control in also */ break; case PDC_PIPE_UNSTALL: pdc_command(CMD_UNSTALLEP+handle); if(handle == EP0OUT) pdc_command(CMD_UNSTALLEP+handle+1); /* untall control in also */ if(handle > EP0IN) { if(pipe->ep_desc->ep_dir & PDC_EP_DIR_IN) tx_data(pdc, handle, 2); else rx_data(pdc, handle); } break; case PDC_GET_PIPE_STATUS: status = pdc_read16(CMD_READEPSTATUS+handle); pipe_opr->pipe_status = (status&STATUS_EPSTAL) ? PDC_PIPE_STALL :PDC_PIPE_UNSTALL; break; } return 0; } return -1;} /* End of pdc_pipe_operation() *//*--------------------------------------------------------------* * Device Controller intialization functions *--------------------------------------------------------------*//* Initialisation of the Peripheral Controller */void pdc_init(struct isp1362_dev *dev){ func_debug(("pdc_init(dev=%p)\n",dev)) /* set the ISP1362 Device controller Hardware Configuration */ isp1362_set_hw_config(dev); /* Set DMA mode (no dma) */ pdc_write16(CMD_WRITEDMACONFIG,0); /*bledia Disable all interrupts */ pdc_write32(CMD_WRITEIRQENABLE,0); /* Set default address */ pdc_write16(CMD_WRITEADDRESS,0); return;} /* End of pdc_init *//* Actually connect to the bus */void pdc_connect(void){ /* Set device address & enable */ pdc_write16(CMD_WRITEADDRESS,ADDRESS_DEVEN|0); /* Enable interrupts */ pdc_write32(CMD_WRITEIRQENABLE,IE_EP0OUT|IE_EP0IN|IE_RST|IE_SUSP); /* Connect to the bus */ pdc_write16(CMD_WRITEMODE,MODE_SOFTCT|MODE_INTENA); return;} /* End of pdc_connect *//*---------------------------------------------------------------------* * ISP1362 HOSAL interface functions * *---------------------------------------------------------------------*/struct isp1362_driver pdc_driver = { name: "usb-pdc", index: ISP1362_DC, probe: pdc_probe, remove: pdc_remove,};/* Device initialisation */int pdc_probe (struct isp1362_dev *dev) { struct pdc_dev *pdc=usb_devices; int result, i; struct pdc_pipe *pipe; func_debug(("pdc_probe(dev=%p)\n",dev)) /* Grab the IO resources */ result = isp1362_check_io_region(dev); if(result < 0) { detail_debug(("%s IO resources are not free\n","isp1362-pdc")) return result; } isp1362_request_io_region(dev); pdc->dev = dev; isp1362_dc_dev = dev; for(i=0; i< PDC_MAX_PIPES;i++) { pipe = pdc->ep_pipes + i; pipe->urb = NULL; pipe->txrx_idle = 1; pipe->ep_state = PDC_PIPE_UNCONFIG; pipe->ep_desc = NULL; } /* Configure the default end points */ /* Configure the control OUT pipe */ pipe = pdc->ep_pipes; pipe->ep_desc = &pdc_ctrl_ep_desc[0]; pipe->ep_desc->ep_num = 0; pipe->ep_desc->ep_dir = PDC_EP_DIR_OUT; pipe->ep_desc->attributes = PDC_EP_CONTROL; pipe->ep_desc->max_pkt_size = 64; pipe->ep_state = PDC_PIPE_CONFIG; /* configure the control IN pipe */ pipe = pdc->ep_pipes + 1; pipe->ep_desc = &pdc_ctrl_ep_desc[1]; pipe->ep_desc->ep_num = 0; pipe->ep_desc->ep_dir = PDC_EP_DIR_IN; pipe->ep_desc->attributes = PDC_EP_CONTROL; pipe->ep_desc->max_pkt_size = 64; pipe->ep_state = PDC_PIPE_CONFIG; pdc_bus_init(pdc); /* Do chip setup */ pdc_init(dev); /* Claim USB IRQ */ result=isp1362_request_irq(pdc_isr,dev,pdc); /* Got it ok? */ if (result < 0) { detail_debug((KERN_ERR "usb-pdc:Can't get USB device IRQ %d.\n", dev->irq)) return result; } detail_debug(("usb-pdc:device IRQ is initialised, Irq is %04x\n",dev->irq)) /* If there are pending IRQs, process them as we can only detect edges */#ifndef CONFIG_USB_HCDC_OTG /* All ready! */ pdc_connect();#endif /* CONFIG_USB_HCDC_OTG */ dev->driver_data = pdc; detail_debug(("pdc:Philips USB device driver in INIT.\n")) return 0;} /* End of pdc_probe */void pdc_remove (struct isp1362_dev *dev) { struct pdc_dev *pdc=(struct pdc_dev*)dev->driver_data; func_debug(("pdc_remove(dev=%p)\n",dev)) pdc_bus_deinit(); /* Go off bus */ pdc_write16(CMD_WRITEADDRESS,0); /* Turn off IRQs */ pdc_write32(CMD_WRITEIRQENABLE,0); /* Global IRQ disable & turn off softconnect */ pdc_write16(CMD_WRITEMODE,0); /* Free IRQ */ isp1362_free_irq(dev,pdc); isp1362_release_io_region(dev); /* release IO space */ pdc->dev = NULL; isp1362_dc_dev = NULL; pdc->ep_pipes = pdc_eps;} /* End of pdc_remove *//* * This is module init function * This function registers the PDC driver to ISP1362 HOSAL driver * which in turn calls the probe function when the dev is found */static int __init pdc_module_init (void) { struct pdc_dev *pdc = usb_devices; func_debug(("pdc_module_init(void)\n")) pdc->dev = NULL; pdc->ep_pipes = pdc_eps; isp1362_dc_dev = NULL; return isp1362_register_driver(&pdc_driver);} /* End of pdc_module_init *//* * This is module cleanup function * Unregister from isp1362 HOSAL layer which in turn calls * Close function */static void __exit pdc_module_cleanup (void) { func_debug(("pdc_module_cleanup (void)\n")) return isp1362_unregister_driver(&pdc_driver);} /* End of pdc_module_cleanup */module_init (pdc_module_init);module_exit (pdc_module_cleanup);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_AUTHOR(DRIVER_AUTHOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -