From owner-p4-projects@FreeBSD.ORG Sun Sep 23 11:59:48 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5402D16A41B; Sun, 23 Sep 2007 11:59:48 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1934816A41A for ; Sun, 23 Sep 2007 11:59:48 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 012FA13C45D for ; Sun, 23 Sep 2007 11:59:48 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l8NBxmGM064314 for ; Sun, 23 Sep 2007 11:59:48 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l8NBxmcJ064311 for perforce@freebsd.org; Sun, 23 Sep 2007 11:59:48 GMT (envelope-from hselasky@FreeBSD.org) Date: Sun, 23 Sep 2007 11:59:48 GMT Message-Id: <200709231159.l8NBxmcJ064311@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 126719 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Sep 2007 11:59:48 -0000 http://perforce.freebsd.org/chv.cgi?CH=126719 Change 126719 by hselasky@hselasky_laptop001 on 2007/09/23 11:59:42 FYI; The comments follow the P4 diff from top to bottom. - change return type of "ugen_allocate_blocks()" - "ugen_allocate_blocks()" is now called unlocked - rename "__usbd_transfer_setup()" to "ugen_transfer_setup()" - "ugen_transfer_setup()" now also allocate buffer memory by calling "ugen_allocate_blocks()". - new function "ugen_usb_uiomove()" that transfers memory directly between an USB transfer and UIO - rename "__uiomove()" into "ugen_uiomove()". - updated several "flags |= XXX" to "flags.xxx = 1". - the maximum frame size must be read from the USB transfer - all USB BULK/ISOC/INTR IN-transfers must setup "xfer->frlengths[]" before calling "usbd_start_hardware()". Else the actual length of the previous transfer will be used for transfer length of the next USB transfer. - updated several "flags & XXX" to "flags_int.xxx". - USB callbacks should return in case of "xfer->error == USBD_CANCELLED". - "usbreq_set_interface()" has been renamed "usbd_set_alt_interface_index()" to clearly show that this function does more than just an USB control request. - passing a mutex to "usbd_do_request_flags()" and all "usbreq_xxx()" functions is now mandatory. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/ugen.c#21 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/ugen.c#21 (text+ko) ==== @@ -66,8 +66,6 @@ #define UGEN_HW_FRAMES 50 /* number of milliseconds per transfer */ -#define ADD_BYTES(ptr,size) ((void *)(((u_int8_t *)(ptr)) + (size))) - struct ugen_frame_ring { u_int16_t input_index; u_int16_t output_index; @@ -295,7 +293,7 @@ } else { - *ptr = ADD_BYTES + *ptr = USBD_ADD_BYTES (ufr->buf, ufr->frame_size*ufr->input_index); @@ -318,7 +316,7 @@ } else { - *ptr = ADD_BYTES + *ptr = USBD_ADD_BYTES (ufr->buf, ufr->frame_size*ufr->output_index); @@ -327,21 +325,22 @@ return; } -static int +static usbd_status ugen_allocate_blocks(struct ugen_softc *sc, struct ugen_endpoint *sce, - u_int16_t context_bit, struct ugen_frame_ring *ufr, u_int16_t frames, u_int16_t frame_size) { void *ptr; + mtx_lock(&(sc->sc_mtx)); bzero(ufr, sizeof(*ufr)); + mtx_unlock(&(sc->sc_mtx)); if(frames == 0) { - return 0; + return USBD_INVAL; } /* one frame will always be unused @@ -350,37 +349,21 @@ */ frames++; - sce->state |= context_bit; - - mtx_unlock(&sc->sc_mtx); - ptr = malloc(frames*(frame_size + sizeof(u_int16_t)), M_USBDEV, M_WAITOK); - mtx_lock(&sc->sc_mtx); - - sce->state &= ~context_bit; - - if(sce->state & UGEN_CLOSING) - { - wakeup(sce); - if(ptr) - { - free(ptr, M_USBDEV); - ptr = NULL; - } - } - if(ptr == NULL) { - return 0; + return USBD_NOMEM; } + mtx_lock(&(sc->sc_mtx)); ufr->end_index = frames; ufr->frame_size = frame_size; - ufr->frlengths = ADD_BYTES(ptr, frames*frame_size); - ufr->buf = ADD_BYTES(ptr, 0); - return 1; + ufr->frlengths = USBD_ADD_BYTES(ptr, frames*frame_size); + ufr->buf = USBD_ADD_BYTES(ptr, 0); + mtx_unlock(&(sc->sc_mtx)); + return 0; } static void @@ -402,12 +385,19 @@ u_int8_t iface_index, struct usbd_xfer **pxfer, const struct usbd_config *setup, - u_int8_t n_setup) + u_int8_t n_setup, + uint16_t n_in_frames, + uint16_t n_out_frames) { struct usbd_xfer * temp[n_setup]; usbd_status error; + if ((n_out_frames > 0) && (n_in_frames > 0)) { + /* should not happen */ + return USBD_INVAL; + } + sce->state |= context_bit; mtx_unlock(&sc->sc_mtx); @@ -419,7 +409,22 @@ error = usbd_transfer_setup(udev, iface_index, &temp[0], setup, n_setup, sce, &(sc->sc_mtx)); + if (error == 0) { + if (n_in_frames > 0) { + error = ugen_allocate_blocks + (sc, sce, &(sce->in_queue), n_in_frames, + temp[0]->max_frame_size); + } else if (n_out_frames > 0) { + error = ugen_allocate_blocks + (sc, sce, &(sce->out_queue), n_out_frames, + temp[0]->max_frame_size); + } + if (error) { + usbd_transfer_unsetup(temp, n_setup); + } + } + mtx_lock(&sc->sc_mtx); if(sce->state & UGEN_CLOSING) @@ -445,7 +450,7 @@ } static int -__uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce, +ugen_uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce, u_int16_t context_bit, void *cp, int n, struct uio *uio) { @@ -474,6 +479,31 @@ } static int +ugen_usb_uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce, + struct usbd_page_cache *pc, struct uio *uio, + uint32_t pc_offset, uint32_t len, uint16_t context_bit) +{ + int error; + + sce->state |= context_bit; + + mtx_unlock(&sc->sc_mtx); + + error = usbd_uiomove(pc, uio, pc_offset, len); + + mtx_lock(&sc->sc_mtx); + + sce->state &= ~context_bit; + + if(sce->state & UGEN_CLOSING) + { + wakeup(sce); + error = EINTR; + } + return error; +} + +static int ugenopen(struct cdev *dev, int flag, int mode, struct thread *p) { struct ugen_softc *sc = DEV2SC(dev); @@ -592,7 +622,6 @@ static int ugen_open_pipe_write(struct ugen_softc *sc, struct ugen_endpoint *sce) { - u_int16_t isize; usbd_status err; mtx_assert(&sc->sc_mtx, MA_OWNED); @@ -612,7 +641,6 @@ usbd_config[1].direction = UE_DIR_ANY; usbd_config[1].timeout = 1000; /* 1 second */ usbd_config[1].interval = 50; /* 50 milliseconds */ - usbd_config[1].flags = 0; usbd_config[1].bufsize = sizeof(usb_device_request_t); usbd_config[1].callback = &ugen_write_clear_stall_callback; @@ -622,18 +650,18 @@ usbd_config[0].callback = &ugen_default_write_callback; usbd_config[0].interval = USBD_DEFAULT_INTERVAL; usbd_config[0].timeout = sce->in_timeout; + usbd_config[0].flags.proxy_buffer = 1; switch(ed->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: case UE_BULK: - usbd_config[0].flags = 0; usbd_config[0].bufsize = UGEN_BULK_BUFFER_SIZE; if(__usbd_transfer_setup (sc, sce, UGEN_WR_CFG, sc->sc_udev, sce->pipe_out->iface_index, - &sce->xfer_out[0], &usbd_config[0], 2)) + &sce->xfer_out[0], &usbd_config[0], 2, 0, 0)) { return (EIO); } @@ -643,11 +671,6 @@ break; case UE_ISOCHRONOUS: - isize = usbd_get_max_frame_size(ed); - - /* the maximum frame size is validated - * by "usbd_fill_iface_data()" - */ if(usbd_get_speed(sc->sc_udev) == USB_SPEED_HIGH) { @@ -658,15 +681,8 @@ sce->out_frames = UGEN_HW_FRAMES; } - if(ugen_allocate_blocks - (sc, sce, UGEN_WR_CFG, - &sce->out_queue, sce->out_frames * 10, isize) == 0) - { - return ENOMEM; - } - - usbd_config[0].flags = USBD_SHORT_XFER_OK; - usbd_config[0].bufsize = isize * sce->out_frames; + usbd_config[0].flags.short_xfer_ok = 1; + usbd_config[0].bufsize = 0; /* use default */ usbd_config[0].frames = sce->out_frames; usbd_config[0].callback = &ugenisoc_write_callback; usbd_config[0].timeout = 0; @@ -677,11 +693,11 @@ err = __usbd_transfer_setup (sc, sce, UGEN_WR_CFG, sc->sc_udev, sce->pipe_out->iface_index, - sce->xfer_out, usbd_config, 2); + sce->xfer_out, usbd_config, 2, + 0, 10 * sce->out_frames); if(err) { - ugen_free_blocks(&sce->out_queue); return (EIO); } break; @@ -702,7 +718,6 @@ static int ugen_open_pipe_read(struct ugen_softc *sc, struct ugen_endpoint *sce) { - int isize; usbd_status err; mtx_assert(&sc->sc_mtx, MA_OWNED); @@ -722,7 +737,6 @@ usbd_config[1].direction = UE_DIR_ANY; usbd_config[1].timeout = 1000; /* 1 second */ usbd_config[1].interval = 50; /* 50 milliseconds */ - usbd_config[1].flags = 0; usbd_config[1].bufsize = sizeof(usb_device_request_t); usbd_config[1].callback = &ugen_read_clear_stall_callback; @@ -730,30 +744,22 @@ usbd_config[0].endpoint = ed->bEndpointAddress & UE_ADDR; usbd_config[0].direction = UE_DIR_IN; usbd_config[0].timeout = sce->in_timeout; + usbd_config[0].flags.proxy_buffer = 1; switch(ed->bmAttributes & UE_XFERTYPE) { case UE_INTERRUPT: - isize = usbd_get_max_frame_size(ed); - usbd_config[0].flags = USBD_SHORT_XFER_OK; + usbd_config[0].flags.short_xfer_ok = 1; usbd_config[0].callback = &ugen_interrupt_callback; - usbd_config[0].bufsize = isize; + usbd_config[0].bufsize = 0; /* use "wMaxPacketSize" */ usbd_config[0].interval = USBD_DEFAULT_INTERVAL; usbd_config[0].timeout = 0; - if(ugen_allocate_blocks - (sc, sce, UGEN_RD_CFG, - &sce->in_queue, 1, isize) == 0) - { - return ENOMEM; - } - if(__usbd_transfer_setup (sc, sce, UGEN_RD_CFG, sc->sc_udev, sce->pipe_in->iface_index, - &sce->xfer_in[0], &usbd_config[0], 2)) + &sce->xfer_in[0], &usbd_config[0], 2, 1, 0)) { - ugen_free_blocks(&sce->in_queue); return (EIO); } @@ -765,15 +771,16 @@ break; case UE_BULK: - usbd_config[0].flags = ((sce->state & UGEN_SHORT_OK) ? - USBD_SHORT_XFER_OK : 0); + if (sce->state & UGEN_SHORT_OK) { + usbd_config[0].flags.short_xfer_ok = 1; + } usbd_config[0].callback = &ugen_default_read_callback; usbd_config[0].bufsize = UGEN_BULK_BUFFER_SIZE; if(__usbd_transfer_setup (sc, sce, UGEN_RD_CFG, sc->sc_udev, sce->pipe_in->iface_index, - &sce->xfer_in[0], &usbd_config[0], 2)) + &sce->xfer_in[0], &usbd_config[0], 2, 0, 0)) { return (EIO); } @@ -784,8 +791,6 @@ case UE_ISOCHRONOUS: - isize = usbd_get_max_frame_size(ed); - /* the maximum frame size is validated * by "usbd_fill_iface_data()" */ @@ -799,15 +804,8 @@ sce->in_frames = UGEN_HW_FRAMES; } - if(ugen_allocate_blocks - (sc, sce, UGEN_RD_CFG, - &sce->in_queue, sce->in_frames * 10, isize) == 0) - { - return ENOMEM; - } - - usbd_config[0].flags = USBD_SHORT_XFER_OK; - usbd_config[0].bufsize = isize * sce->in_frames; + usbd_config[0].flags.short_xfer_ok = 1; + usbd_config[0].bufsize = 0; /* use default */ usbd_config[0].frames = sce->in_frames; usbd_config[0].callback = &ugenisoc_read_callback; usbd_config[0].timeout = 0; @@ -819,11 +817,11 @@ err = __usbd_transfer_setup (sc, sce, UGEN_RD_CFG, sc->sc_udev, sce->pipe_in->iface_index, - sce->xfer_in, usbd_config, 2); + sce->xfer_in, usbd_config, 2, + sce->in_frames * 10, 0); if(err) { - ugen_free_blocks(&sce->in_queue); return (EIO); } @@ -891,7 +889,7 @@ } sce->in_timeout = USBD_NO_TIMEOUT; - sce->out_frame_size = -1; /* set maximum value */ + sce->out_frame_size = 0-1; /* set maximum value */ sce->io_buffer_size = UGEN_BULK_BUFFER_SIZE; /* set default value */ if((pipe->edesc->bEndpointAddress & @@ -1058,7 +1056,7 @@ PRINTFN(10, ("transferring %d bytes\n", len)); /* copy data to user memory */ - error = __uiomove(sc, sce, UGEN_RD_UIO, ptr, len, uio); + error = ugen_uiomove(sc, sce, UGEN_RD_UIO, ptr, len, uio); if(error) break; @@ -1090,13 +1088,13 @@ xfer = sce->xfer_in[0]; /* update length */ - xfer->length = n; + xfer->frlengths[0] = n; /* start transfer */ usbd_transfer_start(xfer); - while ((xfer->flags & USBD_DEV_TRANSFERRING) || - (sce->xfer_in[1]->flags & USBD_DEV_TRANSFERRING)) { + while ((xfer->flags_int.transferring) || + (sce->xfer_in[1]->flags_int.transferring)) { /* wait for data */ @@ -1133,9 +1131,10 @@ } PRINTFN(1, ("got %d of %d bytes\n", xfer->actlen, n)); - error = __uiomove - (sc, sce, UGEN_RD_UIO, - xfer->buffer, xfer->actlen, uio); + + error = ugen_usb_uiomove + (sc, sce, xfer->frbuffers + 0, uio, 0, + xfer->actlen, UGEN_RD_UIO); if(error || (xfer->actlen < n)) { @@ -1207,8 +1206,10 @@ #endif xfer = sce->xfer_out[0]; - error = __uiomove - (sc, sce, UGEN_WR_UIO, xfer->buffer, n, uio); + error = ugen_usb_uiomove + (sc, sce, xfer->frbuffers + 0, uio, + 0, n, UGEN_WR_UIO); + if(error) { break; @@ -1217,13 +1218,13 @@ PRINTFN(1, ("transferred %d bytes\n", n)); /* update length */ - xfer->length = n; + xfer->frlengths[0] = n; /* start transfer */ usbd_transfer_start(xfer); - while ((xfer->flags & USBD_DEV_TRANSFERRING) || - (sce->xfer_out[1]->flags & USBD_DEV_TRANSFERRING)) { + while ((xfer->flags_int.transferring) || + (sce->xfer_out[1]->flags_int.transferring)) { /* wait for data */ @@ -1316,7 +1317,7 @@ *plen = uio->uio_resid; } - error = __uiomove(sc, sce, UGEN_WR_UIO, ptr, *plen, uio); + error = ugen_uiomove(sc, sce, UGEN_WR_UIO, ptr, *plen, uio); if(error) break; @@ -1432,7 +1433,7 @@ } else { - bcopy(xfer->buffer, ptr, xfer->actlen); + usbd_copy_out(&(xfer->buf_data), 0, ptr, xfer->actlen); if(xfer->actlen > *plen) { @@ -1469,6 +1470,7 @@ if (sce->read_stall) { usbd_transfer_start(sce->xfer_in[1]); } else { + xfer->frlengths[0] = xfer->max_data_length; usbd_start_hardware(xfer); } return; @@ -1506,13 +1508,12 @@ ugenisoc_read_callback(struct usbd_xfer *xfer) { struct ugen_endpoint *sce = xfer->priv_sc; - u_int16_t *plen1; + u_int32_t *plen1; u_int16_t *plen2; - void *ptr1; void *ptr2; - u_int16_t isize; + uint32_t offset; u_int16_t n; USBD_CHECK_STATUS(xfer); @@ -1522,10 +1523,9 @@ PRINTFN(5,("actlen=%d\n", xfer->actlen)); plen1 = xfer->frlengths; - ptr1 = xfer->buffer; - isize = usbd_get_max_frame_size(sce->pipe_in->edesc); n = sce->in_frames; + offset = 0; while(n--) { if(*plen1 != 0) @@ -1542,14 +1542,15 @@ *plen1 = *plen2; } - bcopy(ptr1, ptr2, *plen1); + usbd_copy_out(xfer->frbuffers + 0, offset, + ptr2, *plen1); *plen2 = *plen1; ugen_inc_input_index(&sce->in_queue); } - ptr1 = ADD_BYTES(ptr1, isize); + offset += xfer->max_frame_size; plen1++; } @@ -1562,11 +1563,10 @@ tr_setup: tr_error: - isize = usbd_get_max_frame_size(sce->pipe_in->edesc); for(n = 0; n < sce->in_frames; n++) { /* setup size for next transfer */ - xfer->frlengths[n] = isize; + xfer->frlengths[n] = xfer->max_frame_size; } usbd_start_hardware(xfer); return; @@ -1576,24 +1576,26 @@ ugenisoc_write_callback(struct usbd_xfer *xfer) { struct ugen_endpoint *sce = xfer->priv_sc; - u_int16_t *plen1; - u_int16_t len2; - - void *ptr1; + uint32_t *plen1; void *ptr2; - u_int16_t isize; + uint32_t offset; + uint16_t len2; u_int16_t n; USBD_CHECK_STATUS(xfer); + tr_error: + if (xfer->error == USBD_CANCELLED) { + return; + } + tr_transferred: tr_setup: plen1 = xfer->frlengths; - ptr1 = xfer->buffer; - isize = usbd_get_max_frame_size(sce->pipe_out->edesc); + offset = 0; n = sce->out_frames; while(n--) { @@ -1604,18 +1606,17 @@ break; } - if(len2 > isize) - { - len2 = isize; + if (len2 > xfer->max_frame_size) { + len2 = xfer->max_frame_size; } - bcopy(ptr2, ptr1, len2); + usbd_copy_in(xfer->frbuffers + 0, offset, ptr2, len2); *plen1 = len2; ugen_inc_output_index(&sce->out_queue); - ptr1 = ADD_BYTES(ptr1, len2); + offset += len2; plen1++; } @@ -1631,9 +1632,7 @@ } selwakeuppri(&sce->selinfo, PZERO); - if(n) - { - tr_error: + if (n > 0) { usbd_start_hardware(xfer); } return; @@ -1671,7 +1670,7 @@ ugen_destroy_devnodes(sc, 1); /* change setting */ - if(usbreq_set_interface(sc->sc_udev, ifaceidx, altno)) + if(usbd_set_alt_interface_index(sc->sc_udev, ifaceidx, altno)) { return EIO; } @@ -1706,8 +1705,7 @@ } else { - if(usbreq_get_config_desc(udev, index, &cdescr)) - { + if (usbreq_get_config_desc(udev, NULL, &cdescr, index)) { return (0); } len = UGETW(cdescr.wTotalLength); @@ -1721,8 +1719,8 @@ { return 0; } - if(usbreq_get_config_desc_full(udev, index, cdesc, len)) - { + + if (usbreq_get_config_desc_full(udev, NULL, cdesc, len, index)) { free(cdesc, M_TEMP); return (0); } @@ -1749,6 +1747,7 @@ void *data = 0; int error = 0; int len; + uint16_t actlen; u_int8_t conf; u_int8_t alt; @@ -1803,9 +1802,9 @@ goto done; case USB_GET_FRAME_SIZE: - if(sce->pipe_in) + if(sce->xfer_in[0]) { - *(int *)addr = usbd_get_max_frame_size(sce->pipe_in->edesc); + *(int *)addr = sce->xfer_in[0]->max_frame_size; } else { @@ -1871,7 +1870,7 @@ break; #endif case USB_GET_CONFIG: - error = usbreq_get_config(sc->sc_udev, &conf); + error = usbreq_get_config(sc->sc_udev, NULL, &conf); if(error) { error = EIO; @@ -2020,10 +2019,10 @@ break; case USB_GET_STRING_DESC: #define si ((struct usb_string_desc *)addr) - if(usbreq_get_string_desc - (sc->sc_udev, si->usd_string_index, - si->usd_language_id, &si->usd_desc, NULL)) - { + if (usbreq_get_string_desc + (sc->sc_udev, NULL, &si->usd_desc, + sizeof(si->usd_desc), si->usd_language_id, + si->usd_string_index)) { error = EINVAL; break; } @@ -2080,11 +2079,14 @@ } } - if(usbd_do_request_flags - (sc->sc_udev, &ur->ucr_request, data, - (ur->ucr_flags & USBD_SHORT_XFER_OK), &ur->ucr_actlen, - USBD_DEFAULT_TIMEOUT)) - { + error = usbd_do_request_flags + (sc->sc_udev, NULL, &ur->ucr_request, data, + (ur->ucr_flags & USBD_SHORT_XFER_OK), &actlen, + USBD_DEFAULT_TIMEOUT); + + ur->ucr_actlen = actlen; + + if (error) { error = EIO; break; } @@ -2101,8 +2103,7 @@ break; case USB_GET_DEVICEINFO: - usbd_fill_deviceinfo(sc->sc_udev, - (struct usb_device_info *)addr, 1); + usbd_fill_deviceinfo(sc->sc_udev, (void *)addr); break; default: error = EINVAL;