PERFORCE change 166072 for review
Sylvestre Gallon
syl at FreeBSD.org
Tue Jul 14 09:08:35 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=166072
Change 166072 by syl at 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)
+{
}
More information about the p4-projects
mailing list