static void ep1_start(void) { PRINTKD( "[%lu]ep1_start dma_len %d remain %d pkt %d\n", (jiffies-start_time)*10, ep1_curdmalen, ep1_remain, rx_pktsize); sa1100_clear_dma(dmachn_rx); if (!ep1_curdmalen) { // ep1_curdmalen is min (rx_pktsize , ep1_remain) ep1_curdmalen = rx_pktsize; if (ep1_curdmalen > ep1_remain) ep1_curdmalen = ep1_remain; ep1_curdmapos = pci_map_single(NULL, ep1_curdmabuf, ep1_curdmalen, PCI_DMA_FROMDEVICE); } UDC_write( Ser0UDCOMP, ep1_curdmalen - 1); sa1100_start_dma(dmachn_rx, ep1_curdmapos, ep1_curdmalen); if ( naking ) { /* turn off NAK of OUT packets, if set */ UDC_flip( Ser0UDCCS1, UDCCS1_RPC ); naking = 0; } }
int ep1_init(dma_regs_t *chn) { UDC_write( Ser0UDCOMP, rx_pktsize-1 ); dmachn_rx = chn; sa1100_clear_dma(dmachn_rx); ep1_done(-EAGAIN); return 0; }
void ep1_reset(void) { if (currentPort) { rx_pktsize = 8; // OJO } else { rx_pktsize = 1; // OJO } sa1100_clear_dma(dmachn_rx); UDC_clear(Ser0UDCCS1, UDCCS1_FST); ep1_done(-EINTR); }
/* * We want to get here as soon as possible, and get the receiver setup. * We use the existing buffer. */ static void sa1100_irda_rx_dma_start(struct sa1100_irda *si) { if (!si->rxskb) { printk(KERN_ERR "sa1100_ir: rx buffer went missing\n"); return; } /* * First empty receive FIFO */ Ser2HSCR0 = si->hscr0 | HSCR0_HSSP; /* * Enable the DMA, receiver and receive interrupt. */ sa1100_clear_dma(si->rxdma); sa1100_start_dma(si->rxdma, si->rxbuf_dma, HPSIR_MAX_RXLEN); Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_RXE; }
/* * Note: rev A0-B2 chips don't like FST */ void udc_ep2_halt(struct sausb_dev *usb, int halt) { usb->ep[1].host_halt = halt; if (halt) { usb->ep[1].udccs |= UDCCS2_FST; udc_set_cs2(UDCCS2_FST, UDCCS2_FST, UDCCS2_FST); } else { sa1100_clear_dma(usb->ep[1].dmach); udc_set_cs2(UDCCS2_FST, UDCCS2_FST, UDCCS2_FST); udc_set_cs2(0, UDCCS2_FST, 0); udc_set_cs2(UDCCS2_SST, UDCCS2_SST, 0); usb->ep[1].udccs &= ~UDCCS2_FST; udc_ep2_done(usb, -EINTR); } }
int udc_ep2_send(struct sausb_dev *usb, char *buf, int len) { unsigned long flags; dma_addr_t dma; int ret; if (!buf || len == 0) { printk("%s: returning -EINVAL. buf = %x, len = %x\n",__FUNCTION__,(int)buf,len); return -EINVAL; } #if 1 /* NCB added to resolve aligment problem */ if (len > SEND_BUFFER_SIZE) { printk("%s: buffer too big %d\n",__FUNCTION__,len); return -EINVAL; } /* try to let usb tx drain */ if (usb->ep[1].buflen) { #if 0 int i; printk("%s: busy sending %d - waiting 5secs\n",__FUNCTION__,usb->ep[1].buflen); for (i=0; i<500; i++) { udelay(10000); if (!usb->ep[1].buflen) break; } #endif if (usb->ep[1].buflen) { printk("%s: busy sending %d - returning -EBUSY\n",__FUNCTION__,usb->ep[1].buflen); return -EBUSY; } } /* start by not manipulating the buffer while anything remaining to be sent */ spin_lock_irqsave(&usb->lock, flags); if (index+len>SEND_BUFFER_SIZE) { // printk("usb_send: udc_ep2_send - len is %x, reduced to 4096\n",len); index=0; } else // align index on a 32 bit boundary while (index%3) index++; /* copy buffer to aligned memory area */ memcpy(send_buffer+index,buf,len); dma = dma_map_single(usb->dev, send_buffer+index, len, DMA_TO_DEVICE); #else dma = dma_map_single(usb->dev, buf, len, DMA_TO_DEVICE); spin_lock_irqsave(&usb->lock, flags); #endif do { if (!usb->ep[1].configured) { printk("%s: -ENODEV\n",__FUNCTION__); ret = -ENODEV; break; } if (usb->ep[1].buflen) { printk("%s: -EBUSY\n",__FUNCTION__); ret = -EBUSY; break; } usb->ep[1].bufdma = dma; usb->ep[1].buflen = len; usb->ep[1].pktdma = dma; ep2_remain = len; sa1100_clear_dma(usb->ep[1].dmach); ep2_start(usb); ret = 0; } while (0); spin_unlock_irqrestore(&usb->lock, flags); #if 0 if (ret == -EBUSY) { printk("%s: busy so resetting endpoint\n",__FUNCTION__); // sa1100_clear_dma(usb->ep[1].dmach); // ep2_start(usb); udc_ep2_send_reset(usb); } else #endif if (ret) { printk("%s: returning -%d\n",__FUNCTION__,ret); dma_unmap_single(usb->dev, dma, len, DMA_TO_DEVICE); } return ret; }
void udc_ep2_int_hndlr(struct sausb_dev *usb) { u32 status = Ser0UDCCS2; // check for stupid silicon bug. if (Ser0UDCAR != usb->ctl->address) Ser0UDCAR = usb->ctl->address; udc_set_cs2(usb->ep[1].udccs | UDCCS2_SST, UDCCS2_SST, 0); if (!(status & UDCCS2_TPC)) { char *buf = (char *) usb->ep[1].bufdma; int len = usb->ep[1].buflen; printk("usb_send: Not TPC: UDCCS2 = %x\n", status); printk("%s: hmm, what to do here?\n",__FUNCTION__); // udc_ep2_send_reset(usb); printk("%s: Buffer is %x length %d\n",__FUNCTION__,(int)buf,len); if (buf && len) { printk("%s: Retransmitting\n",__FUNCTION__); udc_ep2_send(usb, buf, len); } return; } sa1100_stop_dma(usb->ep[1].dmach); if (status & (UDCCS2_TPE | UDCCS2_TUR)) { printk("usb_send: transmit error %x\n", status); usb->ep[1].fifo_errs ++; udc_ep2_done(usb, -EIO); } else { unsigned int imp; #if 1 // 22Feb01ww/Oleg imp = ep2_curdmalen; #else // this is workaround for case when setting // of Ser0UDCIMP was failed imp = Ser0UDCIMP + 1; #endif usb->ep[1].pktdma += imp; ep2_remain -= imp; usb->ep[1].bytes += imp; usb->ep[1].packets++; sa1100_clear_dma(usb->ep[1].dmach); #if 0 /* induce horrible 5ms delay */ { udelay(1000); udelay(1000); udelay(1000); udelay(1000); udelay(1000); } #endif if (ep2_remain != 0) { ep2_start(usb); } else { udc_ep2_done(usb, 0); } } }