Date: Tue, 14 Jul 2009 09:08:33 GMT From: Sylvestre Gallon <syl@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 166072 for review Message-ID: <200907140908.n6E98XU4057008@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166072 Change 166072 by syl@syl_pablo on 2009/07/14 09:08:11 Implement s3c24dci_timeout. Implement s3c24dci_standard_done_sub. Implement s3c24dci_standard_done. Implement s3c24dci_xfer_do_fifo. Implement s3c24dci_start_standard_chain. Affected files ... .. //depot/projects/soc2009/syl_usb/src/sys/dev/usb/controller/s3c24xxdci.c#10 edit Differences ... ==== //depot/projects/soc2009/syl_usb/src/sys/dev/usb/controller/s3c24xxdci.c#10 (text+ko) ==== @@ -161,14 +161,193 @@ } static void -s3c24dci_setup_standard_chain(struct usb_xfer *xfer) +s3c24dci_timeout(void *arg) +{ + struct usb_xfer *xfer = arg; + + DPRINTFN("xfer=%p\n", xfer); + + USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); + + /* transfer is transferred */ + s3c24dci_device_done(xfer, USB_ERR_TIMEOUT); +} + +static usb_error_t +s3c24dci_standard_done_sub(struct usb_xfer *xfer) +{ + struct s3c24dci_td *td; + uint32_t len; + uint8_t error; + + DPRINTFN(9, "\n"); + + td = xfer->td_transfer_cache; + + do { + len = td->remainder; + + if (xfer->aframes != xfer->nframes) { + /* + * Verify the length and subtract + * the remainder from "frlengths[]": + */ + if (len > xfer->frlengths[xfer->aframes]) { + td->error = 1; + } else { + xfer->frlengths[xfer->aframes] -= len; + } + } + /* Check for transfer error */ + if (td->error) { + /* the transfer is finished */ + error = 1; + td = NULL; + break; + } + /* Check for short transfer */ + if (len > 0) { + if (xfer->flags_int.short_frames_ok) { + /* follow alt next */ + if (td->alt_next) { + td = td->obj_next; + } else { + td = NULL; + } + } else { + /* the transfer is finished */ + td = NULL; + } + error = 0; + break; + } + td = td->obj_next; + + /* this USB frame is complete */ + error = 0; + break; + + } while (0); + + /* update transfer cache */ + + xfer->td_transfer_cache = td; + + return (error ? + USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION); +} + +static void +static void +s3c24dci_standard_done(struct usb_xfer *xfer) +{ + usb_error_t err = 0; + + DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", + xfer, xfer->endpoint); + + /* reset scanner */ + + xfer->td_transfer_cache = xfer->td_transfer_first; + + if (xfer->flags_int.control_xfr) { + if (xfer->flags_int.control_hdr) { + err = s3c24dci_standard_done_sub(xfer); + } + xfer->aframes = 1; + if (xfer->td_transfer_cache == NULL) { + goto done; + } + } + while (xfer->aframes != xfer->nframes) { + err = s3c24dci_standard_done_sub(xfer); + xfer->aframes++; + + if (xfer->td_transfer_cache == NULL) { + goto done; + } + } + + if (xfer->flags_int.control_xfer && + !xfer->flags_int.control_act) { + err = s3c24dci_standard_done_sub(xfer); + } +done: + s3c24dci_device_done(xfer, err); +} + +static uint8_t +s3c24dci_xfer_do_fifo(struct usb_xfer *xfer) { + struct s3c24dci_softc *sc; + struct s3c24dci_td *td; + DPRINTFN(9, "\n"); + + td = xfer->td_transfer_cache; + while (1) { + if ((td->func)(td)) { + /* operation in progress */ + break ; + } + if (((void *)td) == xfer->td_transfer_last) { + goto done; + } else if (td->remainder > 0) { + /* + * We had a short transfer. If there is no alternate + * next, stop processing ! + */ + if (!td->alt_next) { + goto done; + } + /* + * Fetch the next transfer descriptor and transfer + * some flags to the next transfer descriptor. + */ + td = td->obj_next; + xfer->td_transfer_cache = td; + } + return (1); +done: + s3c24dci_standard_done(xfer); } static void s3c24dci_start_standard_chain(struct usb_xfer *xfer) { + DPRINTFN(9, "\n"); + + /* poll one time */ + if (s3c24dci_xfer_do_fifo(xfer)) { + struct at91dci_softc *sc = S3C24_DCI_BUS2SC(xfer->xroot->bus); + uint8_t ep_no = xfer->endpointno & UE_ADDR; + uint32_t ittmp; + + /* + * Only enable the endpoint interrupt when we are actually + * waiting for data, hence we are dealing with level + * triggered interrupts ! + */ + ittmp = S3C24XX_DCI_READ_4(sc, S3C24_DCI_EP_INT_EN); + ittmp |= (1<<ep_no); + S3C24XX_DCI_WRITE_4(sc, S3C24_DCI_EP_INT_EN, ittmp); + + DPRINTFN(15, "enable interrupts on endpoint %d\n", ep_no); + + /* put transfer on interrupt queue */ + usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); + + /* start timeout, if any */ + if (xfer->timeout != 0) { + usbd_transfer_timeout_ms(xfer, + &s3c24dci_timeout, xfer->timeout); + } + } +} + +static void +s3c24dci_setup_standard_chain(struct usb_xfer *xfer) +{ }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907140908.n6E98XU4057008>