Beispiel #1
0
/* Start running. Must have called usb_open (above) first */
int sa1100_usb_start( void ) {
	
	usbd_info.state = USB_STATE_SUSPENDED;

	/* Enable UDC and mask everything */
	UDC_write(Ser0UDCCR , 0xFC);

	/* clear stall - receiver seems to start stalled? 19Jan01ww */
	/* also clear other stuff just to be thurough 22Feb01ww */
	UDC_clear(Ser0UDCCS1, UDCCS1_FST | UDCCS1_RPE | UDCCS1_RPC );
	UDC_clear(Ser0UDCCS2, UDCCS2_FST | UDCCS2_TPE | UDCCS2_TPC );

	rx_pktsize = 8;	// OJO
	tx_pktsize = 1; // OJO
	
	/* flush DMA and fire through some -EAGAINs */
	ep1_init( usbd_info.dmach_rx );
	ep2_init( usbd_info.dmach_tx );

	/* clear all top-level sources */
	Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR | UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
	
	/* EXERIMENT - a short line in the spec says toggling this
	..bit diddles the internal state machine in the udc to
	..expect a suspend */
	Ser0UDCCR  |= UDCCR_RESIM; 
	/* END EXPERIMENT 10Feb01ww */
	UDC_write( Ser0UDCCR, UDCCR_SUSIM | UDCCR_TIM);

	/* clear all top-level sources */
	Ser0UDCSR = UDCSR_RSTIR | UDCSR_RESIR | UDCSR_EIR | UDCSR_RIR | UDCSR_TIR | UDCSR_SUSIR ;
	
	return 0;
}
Beispiel #2
0
/*
 * This gets called when we receive a SET_CONFIGURATION packet to EP0.
 * We were configured.  We can now send packets to the host.
 */
void udc_ep2_config(struct sausb_dev *usb, unsigned int maxpktsize)
{
	/*
	 * We shouldn't be transmitting anything...
	 */
	BUG_ON(usb->ep[1].buflen);
	BUG_ON(usb->ep[1].pktlen);

	/*
	 * Set our configuration.
	 */
	usb->ep[1].maxpktsize = maxpktsize;
	usb->ep[1].configured = 1;

	/*
	 * Clear any pending TPC status.
	 */
	udc_set_cs2(UDCCS2_TPC, UDCCS2_TPC, 0);

	/*
	 * Enable EP2 interrupts.
	 */
	usb->udccr &= ~UDCCR_TIM;
	UDC_write(Ser0UDCCR, usb->udccr);

	usb->ep[1].udccs = 0;
}
Beispiel #3
0
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;
	}
}
Beispiel #4
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;
}
Beispiel #5
0
/* set feature stall executing, async */
static void ep2_start(struct sausb_dev *usb)
{
	ep2_curdmalen = min(ep2_remain, usb->ep[1].maxpktsize);
	if (ep2_curdmalen == 0)
		return;

	/*
	 * must do this _before_ queue buffer..
	 * stop NAKing IN tokens
	 */
	udc_set_cs2(usb->ep[1].udccs | UDCCS2_TPC, UDCCS2_TPC, 0);

	UDC_write(Ser0UDCIMP, ep2_curdmalen - 1);

	/* Remove if never seen...8Mar01ww */
	{
		int massive_attack = 20;
		while (Ser0UDCIMP != ep2_curdmalen - 1 && massive_attack--) {
			printk("usbsnd: Oh no you don't! Let me spin...");
			udelay(500);
			printk("and try again...\n");
			UDC_write(Ser0UDCIMP, ep2_curdmalen - 1);
		}
		if (massive_attack != 20) {
			if (Ser0UDCIMP != ep2_curdmalen - 1)
				printk("usbsnd: Massive attack FAILED. %d\n",
				     20 - massive_attack);
			else
				printk("usbsnd: Massive attack WORKED. %d\n",
				     20 - massive_attack);
		}
	}
	/* End remove if never seen... 8Mar01ww */

	/*
	 * fight stupid silicon bug
	 */
	Ser0UDCAR = usb->ctl->address;

	sa1100_start_dma(usb->ep[1].dmach, usb->ep[1].pktdma, ep2_curdmalen);
}
Beispiel #6
0
/*
 * We saw a reset from the attached hub, or were deconfigured.
 * This means we are no longer configured.
 */
void udc_ep2_reset(struct sausb_dev *usb)
{
	/*
	 * Disable EP2 interrupts.
	 */
	usb->udccr |= UDCCR_TIM;
	UDC_write(Ser0UDCCR, usb->udccr);

	usb->ep[1].configured = 0;
	usb->ep[1].maxpktsize = 0;

	sa1100_reset_dma(usb->ep[1].dmach);
	udc_ep2_done(usb, -EINTR);
}
Beispiel #7
0
static void hub_interrupt_complete(int flag, int size) {
	int flags;
	
	PRINTKI( "[%lu]Hub_interrupt_complete (status %d)\n",(jiffies-start_time)*10, flag);
	local_irq_save(flags);	
	if (flag == 0)
	{
		//printk( "hub_interrupt_complete: ¿queda pendiente?\n");
		hub_interrupt_queued = 0;
	}
	else
	{
		printk( "hub_interrupt_complete con error?: flag %d, size %d\n", flag, size);
	}
		
	local_irq_restore(flags);

	// Mask EP2 interrupts
	Ser0UDCCR = 0xFC;
	UDC_write(Ser0UDCCR, UDCCR_TIM);
	//UDC_write(Ser0UDCCR, UDCCR_TIM | UDCCR_REM); // Errata 29
	
	if (device_retry>0) {
		PRINTKI( "[%lu]GetHub/PortStatus: retry port %d \n", (jiffies-start_time)*10, device_retry);
	}
	
	// Keep sending Device 5 connected until PORT_RESET received
	if (machine_state==DEVICE5_WAIT_READY && device_retry>0) {
		machine_state=DEVICE4_READY;
		SET_TIMER (10);
	}
	
	// Keep sending Device 3 disconnected until PORT_STATUS received
	if (machine_state==DEVICE3_WAIT_DISCONNECT && device_retry>0) {
		machine_state=DEVICE5_READY;
		SET_TIMER (10);
	}
}
Beispiel #8
0
static void udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
{
	__u32 status = Ser0UDCSR;
	
	if (start_time==0) {
		start_time = jiffies;
	}
	
	//PRINTKD("[%lu]Status %d Mask %d\n", (jiffies-start_time)*10, status, Ser0UDCCR);

	UDC_flip(Ser0UDCSR, status); // clear all pending sources
	
	/* ReSeT Interrupt Request - UDC has been reset */
	if (status & UDCSR_RSTIR)
	{
		Ser0UDCCR = 0xFC;
		
		if (second_reset) {
			UDC_write(Ser0UDCCR, UDCCR_TIM);
			//UDC_write(Ser0UDCCR, UDCCR_TIM | UDCCR_REM); // Errata 29
		}
		else {
			Ser0UDCCR = UDCCR_TIM;
			//Ser0UDCCR = UDCCR_TIM | UDCCR_REM; // Errata 29
		}
		
		if (Ser0UDCCR & UDCCR_TIM || second_reset==1) {
			/* starting 20ms or so reset sequence now... */
			ep0_reset();  // just set state to idle
			ep1_reset();  // flush dma, clear false stall
			ep2_reset();  // flush dma, clear false stall
		}
		second_reset = 1;
		//UDC_flip(Ser0UDCSR, status); // clear all pending sources
		PRINTKI("[%lu]Reset: Mask %d\n", (jiffies-start_time)*10, Ser0UDCCR);		
		return;
	}
	
	second_reset = 0;
	
	// /* RESume Interrupt Request ojo eliminar?*/
	if ( status & UDCSR_RESIR )
	{
		core_kicker();
		Ser0UDCCR = 0xFC;
		Ser0UDCCR = UDCCR_TIM | UDCCR_RESIM;
		
		//UDC_flip(Ser0UDCSR, status); // clear all pending sources
		PRINTKD("[%lu]Resume: Mask %d\n", (jiffies-start_time)*10, Ser0UDCCR);
		
		return;
	}

	/* SUSpend Interrupt Request */
	if ( status & UDCSR_SUSIR )
	{
		Ser0UDCCR = 0xFC;
		// Does not seems to help either to be necessary
		// if (tr==2) {
			// core_kicker();
		// }
		
		UDC_write(Ser0UDCCR, UDCCR_TIM | UDCCR_SUSIM); 
		//UDC_write(Ser0UDCCR, UDCCR_TIM | UDCCR_SUSIM | UDCCR_REM); // Errata 29
		//UDC_flip(Ser0UDCSR, status); // clear all pending sources
		PRINTKI("[%lu]Suspended: Mask %d\n", (jiffies-start_time)*10, Ser0UDCCR);
		return;
	}	
	
	//UDC_flip(Ser0UDCSR, status); // clear all pending sources
		
	if (status & UDCSR_RIR)
		ep1_int_hndlr();

	if (status & UDCSR_TIR)
		ep2_int_hndlr();
	
	if (status & UDCSR_EIR)
		ep0_int_hndlr();
}