FreeBSD/sys/dev/usb/controller/musb_otg.c
/* Control endpoint only data handling functions (RX/TX/SYNC) */
Control endpoint only data handling functions (RX/TX/SYNC)
Control endpoint only data handling functions ( RX / TX / SYNC )
static uint8_t
musbotg_dev_ctrl_data_rx(struct musbotg_td *td)
{
	struct usb_page_search buf_res;
	struct musbotg_softc *sc;
	uint16_t count;
	uint8_t csr;
	uint8_t got_short;
	sc = MUSBOTG_PC2SC(td->pc);
	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
	if (sc->sc_ep0_cmd) {
		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, sc->sc_ep0_cmd);
		sc->sc_ep0_cmd = 0;
	}
	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
	DPRINTFN(4, "csr=0x%02x\n", csr);
	got_short = 0;
	if (csr & (MUSB2_MASK_CSR0L_SETUPEND |
	    MUSB2_MASK_CSR0L_SENTSTALL)) {
		if (td->remainder == 0) {
			DPRINTFN(4, "faking complete\n");
			return (0);	
		}
		td->error = 1;
		return (0);		
	}
	if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
		return (1);		
	}
	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
	if (count != td->max_frame_size) {
		if (count < td->max_frame_size) {
			td->short_pkt = 1;
			got_short = 1;
		} else {
			td->error = 1;
			return (0);	
		}
	}
	if (count > td->remainder) {
		td->error = 1;
		return (0);		
	}
	while (count > 0) {
		uint32_t temp;
		usbd_get_page(td->pc, td->offset, &buf_res);
		if (buf_res.length > count) {
			buf_res.length = count;
		}
		if (USB_P2U(buf_res.buffer) & 3) {
			temp = count & ~3;
			if (temp) {
				bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
				    MUSB2_REG_EPFIFO(0), sc->sc_bounce_buf,
				    temp / 4);
			}
			temp = count & 3;
			if (temp) {
				bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
				    MUSB2_REG_EPFIFO(0),
				    (void *)(&sc->sc_bounce_buf[count / 4]), temp);
			}
			usbd_copy_in(td->pc, td->offset,
			    sc->sc_bounce_buf, count);
			td->offset += count;
			td->remainder -= count;
			break;
		}
		if (buf_res.length >= 4) {
			bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
			    MUSB2_REG_EPFIFO(0), buf_res.buffer,
			    buf_res.length / 4);
			temp = buf_res.length & ~3;
			count -= temp;
			td->offset += temp;
			td->remainder -= temp;
			continue;
		}
		bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
		    MUSB2_REG_EPFIFO(0), buf_res.buffer, buf_res.length);
		count -= buf_res.length;
		td->offset += buf_res.length;
		td->remainder -= buf_res.length;
	}
	if ((td->remainder == 0) || got_short) {
		if (td->short_pkt) {
			sc->sc_ep0_cmd = MUSB2_MASK_CSR0L_RXPKTRDY_CLR;
			return (0);
		}
	}
	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
	    MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
	return (1);			
}
static uint8_t musbotg_dev_ctrl_data_rx ( struct musbotg_td * td ) { struct usb_page_search buf_res ; struct musbotg_softc * sc ; uint16_t count ; uint8_t csr ; uint8_t got_short ; sc = MUSBOTG_PC2SC ( td -> pc ) ; MUSB2_WRITE_1 ( sc , MUSB2_REG_EPINDEX , 0 ) ; if ( sc -> sc_ep0_cmd ) { MUSB2_WRITE_1 ( sc , MUSB2_REG_TXCSRL , sc -> sc_ep0_cmd ) ; sc -> sc_ep0_cmd = 0 ; } csr = MUSB2_READ_1 ( sc , MUSB2_REG_TXCSRL ) ; DPRINTFN ( 4 , " \n " , csr ) ; got_short = 0 ; if ( csr & ( MUSB2_MASK_CSR0L_SETUPEND | MUSB2_MASK_CSR0L_SENTSTALL ) ) { if ( td -> remainder == 0 ) { DPRINTFN ( 4 , " \n " ) ; return ( 0 ) ; } td -> error = 1 ; return ( 0 ) ; } if ( ! ( csr & MUSB2_MASK_CSR0L_RXPKTRDY ) ) { return ( 1 ) ; } count = MUSB2_READ_2 ( sc , MUSB2_REG_RXCOUNT ) ; if ( count != td -> max_frame_size ) { if ( count < td -> max_frame_size ) { td -> short_pkt = 1 ; got_short = 1 ; } else { td -> error = 1 ; return ( 0 ) ; } } if ( count > td -> remainder ) { td -> error = 1 ; return ( 0 ) ; } while ( count > 0 ) { uint32_t temp ; usbd_get_page ( td -> pc , td -> offset , & buf_res ) ; if ( buf_res . length > count ) { buf_res . length = count ; } if ( USB_P2U ( buf_res . buffer ) & 3 ) { temp = count & ~ 3 ; if ( temp ) { bus_space_read_multi_4 ( sc -> sc_io_tag , sc -> sc_io_hdl , MUSB2_REG_EPFIFO ( 0 ) , sc -> sc_bounce_buf , temp / 4 ) ; } temp = count & 3 ; if ( temp ) { bus_space_read_multi_1 ( sc -> sc_io_tag , sc -> sc_io_hdl , MUSB2_REG_EPFIFO ( 0 ) , ( void * ) ( & sc -> sc_bounce_buf [ count / 4 ] ) , temp ) ; } usbd_copy_in ( td -> pc , td -> offset , sc -> sc_bounce_buf , count ) ; td -> offset += count ; td -> remainder -= count ; break ; } if ( buf_res . length >= 4 ) { bus_space_read_multi_4 ( sc -> sc_io_tag , sc -> sc_io_hdl , MUSB2_REG_EPFIFO ( 0 ) , buf_res . buffer , buf_res . length / 4 ) ; temp = buf_res . length & ~ 3 ; count -= temp ; td -> offset += temp ; td -> remainder -= temp ; continue ; } bus_space_read_multi_1 ( sc -> sc_io_tag , sc -> sc_io_hdl , MUSB2_REG_EPFIFO ( 0 ) , buf_res . buffer , buf_res . length ) ; count -= buf_res . length ; td -> offset += buf_res . length ; td -> remainder -= buf_res . length ; } if ( ( td -> remainder == 0 ) || got_short ) { if ( td -> short_pkt ) { sc -> sc_ep0_cmd = MUSB2_MASK_CSR0L_RXPKTRDY_CLR ; return ( 0 ) ; } } MUSB2_WRITE_1 ( sc , MUSB2_REG_TXCSRL , MUSB2_MASK_CSR0L_RXPKTRDY_CLR ) ; return ( 1 ) ; }
Control endpoint only data handling functions (RX/TX/SYNC)
Control endpoint only data handling functions ( RX / TX / SYNC )
/* get pointer to softc */ /* select endpoint 0 */ /* check if a command is pending */ /* read out FIFO status */ /*
			 * We are actually complete and have
			 * received the next SETUP
			 */ /* complete */ /*
	         * USB Host Aborted the transfer.
	         */ /* complete */ /* not complete */ /* get the packet byte count */ /* verify the packet byte count */ /* we have a short packet */ /* invalid USB packet */ /* we are complete */ /* verify the packet byte count */ /* invalid USB packet */ /* we are complete */ /* get correct length */ /* check for unaligned memory address */ /* receive data 4 bytes at a time */ /* receive data 1 byte at a time */ /* update offset and remainder */ /* check if we can optimise */ /* receive data 4 bytes at a time */ /* update counters */ /* receive data */ /* update counters */ /* check if we are complete */ /* we are complete */ /* else need to receive a zero length packet */ /* write command - need more data */ /* not complete */