diff -u ./serial/ulpt.c ./serial/ulpt.c --- ./serial/ulpt.c 2009-06-24 12:59:19.000000000 +0200 +++ ./serial/ulpt.c 2009-07-05 10:19:31.000000000 +0200 @@ -110,6 +110,7 @@ struct ulpt_softc { struct usb_fifo_sc sc_fifo; struct usb_fifo_sc sc_fifo_noreset; + struct usb_fifo_sc sc_fifo_raw; struct mtx sc_mtx; struct usb_callout sc_watchdog; @@ -147,6 +148,7 @@ static usb_fifo_ioctl_t ulpt_ioctl; static usb_fifo_open_t ulpt_open; static usb_fifo_open_t unlpt_open; +static usb_fifo_open_t urlpt_open; static struct usb_fifo_methods ulpt_fifo_methods = { .f_close = &ulpt_close, @@ -170,6 +172,17 @@ .basename[0] = "unlpt", }; +static struct usb_fifo_methods urlpt_fifo_methods = { + .f_close = &ulpt_close, + .f_ioctl = &ulpt_ioctl, + .f_open = &urlpt_open, + .f_start_read = &ulpt_start_read, + .f_start_write = &ulpt_start_write, + .f_stop_read = &ulpt_stop_read, + .f_stop_write = &ulpt_stop_write, + .basename[0] = "urlpt", +}; + static void ulpt_reset(struct ulpt_softc *sc) { @@ -419,6 +432,28 @@ } static int +urlpt_open(struct usb_fifo *fifo, int fflags) +{ + struct ulpt_softc *sc = usb_fifo_softc(fifo); + + /* we assume that open is a serial process */ + + if (sc->sc_fflags == 0) { + + /* reset USB paralell port */ + + ulpt_reset(sc); + + /* set raw write mode */ + + if (fflags & FWRITE) { + usb_fifo_set_write_defrag(fifo, 0); + } + } + return (unlpt_open(fifo, fflags)); +} + +static int ulpt_open(struct usb_fifo *fifo, int fflags) { struct ulpt_softc *sc = usb_fifo_softc(fifo); @@ -426,7 +461,16 @@ /* we assume that open is a serial process */ if (sc->sc_fflags == 0) { + + /* reset USB paralell port */ + ulpt_reset(sc); + + /* set defrag write mode */ + + if (fflags & FWRITE) { + usb_fifo_set_write_defrag(fifo, 1); + } } return (unlpt_open(fifo, fflags)); } @@ -633,6 +677,13 @@ if (error) { goto detach; } + error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx, + &urlpt_fifo_methods, &sc->sc_fifo_raw, + unit, 0 - 1, uaa->info.bIfaceIndex, + UID_ROOT, GID_OPERATOR, 0644); + if (error) { + goto detach; + } /* start reading of status */ mtx_lock(&sc->sc_mtx); @@ -654,6 +705,7 @@ usb_fifo_detach(&sc->sc_fifo); usb_fifo_detach(&sc->sc_fifo_noreset); + usb_fifo_detach(&sc->sc_fifo_raw); mtx_lock(&sc->sc_mtx); usb_callout_stop(&sc->sc_watchdog); diff -u ./usb_busdma.c ./usb_busdma.c --- ./usb_busdma.c 2009-06-23 04:19:59.000000000 +0200 +++ ./usb_busdma.c 2009-06-29 13:10:45.000000000 +0200 @@ -359,7 +359,8 @@ if (bus_dma_tag_create ( /* parent */ udt->tag_parent->tag, /* alignment */ align, - /* boundary */ USB_PAGE_SIZE, + /* boundary */ (align == 1) ? + USB_PAGE_SIZE : 0, /* lowaddr */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, diff -u ./usb_dev.c ./usb_dev.c --- ./usb_dev.c 2009-06-24 12:59:19.000000000 +0200 +++ ./usb_dev.c 2009-07-05 10:05:59.000000000 +0200 @@ -740,6 +740,8 @@ break; } } + /* reset have fragment flag */ + f->flag_have_fragment = 0; } /*------------------------------------------------------------------------* @@ -783,6 +785,16 @@ /* set flushing flag */ f->flag_flushing = 1; + /* get the last packet in */ + if (f->flag_have_fragment) { + struct usb_mbuf *m; + f->flag_have_fragment = 0; + USB_IF_DEQUEUE(&f->free_q, m); + if (m) { + USB_IF_ENQUEUE(&f->used_q, m); + } + } + /* start write transfer, if not already started */ (f->methods->f_start_write) (f); @@ -1303,6 +1315,7 @@ struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; + uint8_t *pdata; int fflags; int resid; int io_len; @@ -1373,33 +1386,59 @@ } tr_data = 1; - USB_MBUF_RESET(m); - - io_len = MIN(m->cur_data_len, uio->uio_resid); - - m->cur_data_len = io_len; + if (f->flag_have_fragment == 0) { + USB_MBUF_RESET(m); + io_len = m->cur_data_len; + pdata = m->cur_data_ptr; + if (io_len > uio->uio_resid) + io_len = uio->uio_resid; + m->cur_data_len = io_len; + } else { + io_len = m->max_data_len - m->cur_data_len; + pdata = m->cur_data_ptr + io_len; + if (io_len > uio->uio_resid) + io_len = uio->uio_resid; + m->cur_data_len += io_len; + } DPRINTFN(2, "transfer %d bytes to %p\n", - io_len, m->cur_data_ptr); + io_len, pdata); - err = usb_fifo_uiomove(f, - m->cur_data_ptr, io_len, uio); + err = usb_fifo_uiomove(f, pdata, io_len, uio); if (err) { + f->flag_have_fragment = 0; USB_IF_ENQUEUE(&f->free_q, m); break; } - if (f->methods->f_filter_write) { + + /* check if the buffer is ready to be transmitted */ + + if ((f->flag_write_defrag == 0) || + (m->cur_data_len == m->max_data_len)) { + f->flag_have_fragment = 0; + /* - * Sometimes it is convenient to process data at the - * expense of a userland process instead of a kernel - * process. + * Check for write filter: + * + * Sometimes it is convenient to process data + * at the expense of a userland process + * instead of a kernel process. */ - (f->methods->f_filter_write) (f, m); - } - USB_IF_ENQUEUE(&f->used_q, m); + if (f->methods->f_filter_write) { + (f->methods->f_filter_write) (f, m); + } - (f->methods->f_start_write) (f); + /* Put USB mbuf in the used queue */ + USB_IF_ENQUEUE(&f->used_q, m); + + /* Start writing data, if not already started */ + (f->methods->f_start_write) (f); + } else { + /* Wait for more data or close */ + f->flag_have_fragment = 1; + USB_IF_PREPEND(&f->free_q, m); + } } while (uio->uio_resid > 0); done: @@ -2220,6 +2259,18 @@ f->flag_short = onoff; } +void +usb_fifo_set_write_defrag(struct usb_fifo *f, uint8_t onoff) +{ + if (f == NULL) + return; + + /* defrag written data */ + f->flag_write_defrag = onoff; + /* reset defrag state */ + f->flag_have_fragment = 0; +} + void * usb_fifo_softc(struct usb_fifo *f) { diff -u ./usb_dev.h ./usb_dev.h --- ./usb_dev.h 2009-06-24 12:59:19.000000000 +0200 +++ ./usb_dev.h 2009-07-05 10:36:50.000000000 +0200 @@ -130,6 +130,8 @@ uint8_t flag_short; /* set if short_ok or force_short * transfer flags should be set */ uint8_t flag_stall; /* set if clear stall should be run */ + uint8_t flag_write_defrag; /* set to defrag written data */ + uint8_t flag_have_fragment; /* set if defragging */ uint8_t iface_index; /* set to the interface we belong to */ uint8_t fifo_index; /* set to the FIFO index in "struct * usb_device" */ @@ -144,11 +146,9 @@ int usb_fifo_wait(struct usb_fifo *fifo); void usb_fifo_signal(struct usb_fifo *fifo); uint8_t usb_fifo_opened(struct usb_fifo *fifo); -void usb_fifo_free(struct usb_fifo *f); struct usb_symlink *usb_alloc_symlink(const char *target); void usb_free_symlink(struct usb_symlink *ps); int usb_read_symlink(uint8_t *user_ptr, uint32_t startentry, uint32_t user_len); -void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t); #endif /* _USB_DEV_H_ */ diff -u ./usbdi.h ./usbdi.h --- ./usbdi.h 2009-06-28 08:48:04.000000000 +0200 +++ ./usbdi.h 2009-07-05 10:36:50.000000000 +0200 @@ -531,5 +531,8 @@ void usb_fifo_wakeup(struct usb_fifo *f); void usb_fifo_get_data_error(struct usb_fifo *fifo); void *usb_fifo_softc(struct usb_fifo *fifo); +void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t); +void usb_fifo_set_write_defrag(struct usb_fifo *, uint8_t); +void usb_fifo_free(struct usb_fifo *f); #endif /* _KERNEL */ #endif /* _USB_USBDI_H_ */