Date: Mon, 5 Jun 2006 15:36:57 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 98570 for review Message-ID: <200606051536.k55Favuf098827@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=98570 Change 98570 by hselasky@hselasky_mini_itx on 2006/06/05 15:36:05 Converted "ulpt" into using the new "USB cdev". Affected files ... .. //depot/projects/usb/src/sys/dev/usb/ulpt.c#6 edit .. //depot/projects/usb/src/sys/dev/usb/usb_cdev.c#2 edit .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#8 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/ulpt.c#6 (text+ko) ==== @@ -60,7 +60,7 @@ #include <dev/usb/usb_subr.h> #include <dev/usb/usb_quirks.h> -__FBSDID("$FreeBSD: src/sys/dev/usb/ulpt.c,v 1.68 2005/11/12 17:39:31 iedowse Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/usb/ulpt.c $"); #ifdef USB_DEBUG #define DPRINTF(n,fmt,...) \ @@ -75,12 +75,10 @@ #define DPRINTF(...) #endif -#define DEV2SC(dev) (dev)->si_drv1 - #define ULPT_BSIZE (1<<17) /* bytes */ #define ULPT_IFQ_MAXLEN 2 /* units */ #define ULPT_WATCHDOG_INTERVAL 5 /* times per second */ -#define ULPT_N_TRANSFER 4 /* units */ +#define ULPT_N_TRANSFER 6 /* units */ #define UR_GET_DEVICE_ID 0x00 #define UR_GET_PORT_STATUS 0x01 @@ -93,54 +91,27 @@ #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) struct ulpt_softc { - device_t sc_dev; - struct usbd_device * sc_udev; - struct cdev * sc_cdev_1; - struct cdev * sc_cdev_2; - struct usbd_xfer * sc_xfer[ULPT_N_TRANSFER]; + struct usb_cdev sc_cdev; struct __callout sc_watchdog; struct mtx sc_mtx; - struct usbd_ifqueue sc_rdq_free; - struct usbd_ifqueue sc_rdq_used; - struct usbd_ifqueue sc_wrq_free; - struct usbd_ifqueue sc_wrq_used; - void * sc_mem_ptr_1; /* should be freed at detach */ - void * sc_mem_ptr_2; /* should be freed at detach */ + device_t sc_dev; + struct usbd_xfer * sc_xfer[ULPT_N_TRANSFER]; - u_int32_t sc_flags; -#define ULPT_FLAG_DEV_OPEN 0x00000001 /* device is open */ -#define ULPT_FLAG_NO_READ 0x00000002 /* device has no read endpoint */ -#define ULPT_FLAG_RST_SLP 0x00000004 /* device is sleeping */ -#define ULPT_FLAG_RST_WUP 0x00000008 /* device is waiting for wakeup */ -#define ULPT_FLAG_WR_UIO 0x00000010 /* device is doing I/O */ -#define ULPT_FLAG_RD_UIO 0x00000020 /* device is doing I/O */ -#define ULPT_FLAG_WR_SLP 0x00000040 /* device is sleeping */ -#define ULPT_FLAG_RD_SLP 0x00000080 /* device is sleeping */ -#define ULPT_FLAG_WR_WUP 0x00000100 /* device is waiting for wakeup */ -#define ULPT_FLAG_RD_WUP 0x00000200 /* device is waiting for wakeup */ -#define ULPT_FLAG_CLOSING 0x00000400 /* device is closing */ -#define ULPT_FLAG_GONE 0x00000800 /* device is gone */ -#define ULPT_FLAG_WAIT_USB 0x00001000 /* device is waiting for USB callbacks */ -#define ULPT_FLAG_WAIT_CO 0x00002000 /* device is waiting for callouts */ -#define ULPT_FLAG_DUMP_READ 0x00004000 /* device is not opened for read */ -#define ULPT_FLAG_WR_FLUSH 0x00008000 /* device is flushing write data */ -#define ULPT_FLAG_NO_FLUSH 0x00010000 /* device should not flush write data */ -#define ULPT_FLAG_PIPE_ERR 0x00020000 /* device has signalled an error */ + u_int8_t sc_flags; +#define ULPT_FLAG_NO_READ 0x01 /* device has no read endpoint */ +#define ULPT_FLAG_DUMP_READ 0x02 /* device is not opened for read */ +#define ULPT_FLAG_WAIT_USB 0x04 /* device is waiting for USB callbacks */ +#define ULPT_FLAG_WAIT_CO 0x08 /* device is waiting for callouts */ +#define ULPT_FLAG_READ_STALL 0x10 /* read transfer stalled */ +#define ULPT_FLAG_WRITE_STALL 0x20 /* write transfer stalled */ +#define ULPT_FLAG_RESETTING 0x40 /* device is resetting */ u_int8_t sc_iface_no; u_int8_t sc_last_status; - u_int8_t sc_wakeup_detach; /* dummy */ - u_int8_t sc_wakeup_reset; /* dummy */ - u_int8_t sc_wakeup_read; /* dummy */ - u_int8_t sc_wakeup_write; /* dummy */ - u_int8_t sc_wakeup_flush; /* dummy */ - u_int8_t sc_wakeup_sync_1; /* dummy */ }; -extern cdevsw_t ulpt_cdevsw; - static void ulpt_watchdog(void *__sc) { @@ -154,9 +125,12 @@ usbd_transfer_start(sc->sc_xfer[2]); - if ((sc->sc_flags & (ULPT_FLAG_NO_READ|ULPT_FLAG_DUMP_READ)) && - (sc->sc_flags & (ULPT_FLAG_DEV_OPEN)) && - (!(sc->sc_flags & (ULPT_FLAG_CLOSING)))) { + if ((sc->sc_flags & (ULPT_FLAG_NO_READ| + ULPT_FLAG_DUMP_READ)) && + (!(sc->sc_flags & ULPT_FLAG_RESETTING)) && + (sc->sc_cdev.sc_flags & (USB_CDEV_FLAG_OPEN_READ| + USB_CDEV_FLAG_OPEN_WRITE)) && + (!(sc->sc_cdev.sc_flags & USB_CDEV_FLAG_CLOSING_READ))) { /* start reading of data, if not already started */ @@ -176,56 +150,55 @@ ulpt_write_callback(struct usbd_xfer *xfer) { struct ulpt_softc *sc = xfer->priv_sc; - struct usbd_mbuf *m; + u_int32_t actlen; USBD_CHECK_STATUS(xfer); tr_transferred: tr_setup: - USBD_IF_DEQUEUE(&sc->sc_wrq_used, m); + if (sc->sc_flags & ULPT_FLAG_WRITE_STALL) { + return; + } + if (usb_cdev_get_data(&(sc->sc_cdev), xfer->buffer, + ULPT_BSIZE, &actlen, 0)) { - if (m) { + xfer->length = actlen; + usbd_start_hardware(xfer); + } + return; - if (m->cur_data_len > ULPT_BSIZE) { - /* extra length check */ - m->cur_data_len = ULPT_BSIZE; - } + tr_error: + if (xfer->error != USBD_CANCELLED) { + /* try to clear stall first */ + sc->sc_flags |= ULPT_FLAG_WRITE_STALL; + usbd_transfer_start(sc->sc_xfer[4]); + } + return; +} - bcopy(m->cur_data_ptr, xfer->buffer, m->cur_data_len); - xfer->length = m->cur_data_len; +static void +ulpt_write_clear_stall_callback(struct usbd_xfer *xfer) +{ + struct ulpt_softc *sc = xfer->priv_sc; - USBD_IF_ENQUEUE(&sc->sc_wrq_free, m); + USBD_CHECK_STATUS(xfer); - usbd_start_hardware(xfer); + tr_setup: + /* start clear stall */ + usbd_clear_stall_tr_setup(xfer, sc->sc_xfer[0]); + return; - if (sc->sc_flags & ULPT_FLAG_WR_WUP) { - sc->sc_flags &= ~ULPT_FLAG_WR_WUP; - wakeup(&(sc->sc_wakeup_write)); - } + tr_transferred: + usbd_clear_stall_tr_transferred(xfer, sc->sc_xfer[0]); - } else { - if (sc->sc_flags & ULPT_FLAG_WR_FLUSH) { - sc->sc_flags &= ~ULPT_FLAG_WR_FLUSH; - wakeup(&(sc->sc_wakeup_flush)); - } - } + sc->sc_flags &= ~ULPT_FLAG_WRITE_STALL; + usbd_transfer_start(sc->sc_xfer[0]); return; tr_error: - DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error)); - - sc->sc_flags |= ULPT_FLAG_PIPE_ERR; - - if (sc->sc_flags & ULPT_FLAG_WR_WUP) { - sc->sc_flags &= ~ULPT_FLAG_WR_WUP; - wakeup(&(sc->sc_wakeup_write)); - } - - if (sc->sc_flags & ULPT_FLAG_WR_FLUSH) { - sc->sc_flags &= ~ULPT_FLAG_WR_FLUSH; - wakeup(&(sc->sc_wakeup_flush)); - } - + /* bomb out */ + sc->sc_flags &= ~ULPT_FLAG_WRITE_STALL; + usb_cdev_get_data_error(&(sc->sc_cdev)); return; } @@ -242,45 +215,52 @@ return; } - USBD_IF_DEQUEUE(&sc->sc_rdq_free, m); + usb_cdev_put_data(&(sc->sc_cdev), xfer->buffer, xfer->actlen, 1); + + tr_setup: + if (sc->sc_flags & ULPT_FLAG_READ_STALL) { + return; + } + + USBD_IF_POLL(&sc->sc_cdev.sc_rdq_free, m); if (m) { - USBD_MBUF_RESET(m); + usbd_start_hardware(xfer); + } + return; - if (xfer->actlen > ULPT_BSIZE) { - /* extra length check */ - xfer->actlen = ULPT_BSIZE; - } + tr_error: + if (xfer->error != USBD_CANCELLED) { + /* try to clear stall first */ + sc->sc_flags |= ULPT_FLAG_READ_STALL; + usbd_transfer_start(sc->sc_xfer[5]); + } + return; +} - bcopy(xfer->buffer, m->cur_data_ptr, xfer->actlen); - m->cur_data_len = xfer->actlen; +static void +ulpt_read_clear_stall_callback(struct usbd_xfer *xfer) +{ + struct ulpt_softc *sc = xfer->priv_sc; - USBD_IF_ENQUEUE(&sc->sc_rdq_used, m); - - if (sc->sc_flags & ULPT_FLAG_RD_WUP) { - sc->sc_flags &= ~ULPT_FLAG_RD_WUP; - wakeup(&(sc->sc_wakeup_read)); - } - } + USBD_CHECK_STATUS(xfer); tr_setup: - USBD_IF_POLL(&sc->sc_rdq_free, m); + /* start clear stall */ + usbd_clear_stall_tr_setup(xfer, sc->sc_xfer[1]); + return; - if (m) { - usbd_start_hardware(xfer); - } + tr_transferred: + usbd_clear_stall_tr_transferred(xfer, sc->sc_xfer[1]); + sc->sc_flags &= ~ULPT_FLAG_READ_STALL; + usbd_transfer_start(sc->sc_xfer[1]); return; tr_error: - DPRINTF(0, "error=%s\n", usbd_errstr(xfer->error)); - - sc->sc_flags |= ULPT_FLAG_PIPE_ERR; - - if (sc->sc_flags & ULPT_FLAG_RD_WUP) { - sc->sc_flags &= ~ULPT_FLAG_RD_WUP; - wakeup(&(sc->sc_wakeup_read)); - } + /* bomb out */ + sc->sc_flags &= ~ULPT_FLAG_READ_STALL; + usb_cdev_put_data_error(&(sc->sc_cdev)); return; } @@ -335,6 +315,10 @@ USBD_CHECK_STATUS(xfer); tr_error: + if (xfer->error == USBD_CANCELLED) { + return; + } + if (req->bmRequestType == UT_WRITE_CLASS_OTHER) { /* * There was a mistake in the USB printer 1.0 spec that @@ -354,11 +338,7 @@ } tr_transferred: - if (sc->sc_flags & ULPT_FLAG_RST_WUP) { - sc->sc_flags &= ~ULPT_FLAG_RST_WUP; - - wakeup(&(sc->sc_wakeup_reset)); - } + usb_cdev_wakeup(&(sc->sc_cdev)); return; tr_setup: @@ -409,14 +389,109 @@ .callback = &ulpt_reset_callback, .timeout = 1000, /* 1 second */ }, + + [4] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .callback = &ulpt_write_clear_stall_callback, + .timeout = 1000, /* 1 second */ + }, + + [5] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .callback = &ulpt_read_clear_stall_callback, + .timeout = 1000, /* 1 second */ + }, }; +static void +ulpt_start_read(struct usb_cdev *cdev) +{ + struct ulpt_softc *sc = cdev->sc_priv_ptr; + usbd_transfer_start(sc->sc_xfer[1]); + return; +} + +static void +ulpt_stop_read(struct usb_cdev *cdev) +{ + struct ulpt_softc *sc = cdev->sc_priv_ptr; + usbd_transfer_stop(sc->sc_xfer[5]); + usbd_transfer_stop(sc->sc_xfer[1]); + return; +} + +static void +ulpt_start_write(struct usb_cdev *cdev) +{ + struct ulpt_softc *sc = cdev->sc_priv_ptr; + usbd_transfer_start(sc->sc_xfer[0]); + return; +} + +static void +ulpt_stop_write(struct usb_cdev *cdev) +{ + struct ulpt_softc *sc = cdev->sc_priv_ptr; + usbd_transfer_stop(sc->sc_xfer[4]); + usbd_transfer_stop(sc->sc_xfer[0]); + return; +} + +static int32_t +ulpt_open(struct usb_cdev *cdev, int32_t fflags, + int32_t devtype, struct thread *td) +{ + u_int8_t prime = ((cdev->sc_last_cdev == cdev->sc_cdev[0]) && + (cdev->sc_first_open)); + struct ulpt_softc *sc = cdev->sc_priv_ptr; + int32_t error = 0; + + if (prime) { + DPRINTF(0, "opening prime device (reset)\n"); + + sc->sc_flags |= ULPT_FLAG_RESETTING; + + usbd_transfer_start(sc->sc_xfer[3]); + + error = usb_cdev_sleep(&(sc->sc_cdev), fflags); + + usbd_transfer_stop(sc->sc_xfer[3]); + + sc->sc_flags &= ~ULPT_FLAG_RESETTING; + + if (error) { + goto done; + } + } + + if (cdev->sc_flags & USB_CDEV_FLAG_OPEN_READ) { + sc->sc_flags &= ~ULPT_FLAG_DUMP_READ; + } else { + sc->sc_flags |= ULPT_FLAG_DUMP_READ; + } + done: + return error; +} + +static int32_t +ulpt_ioctl(struct usb_cdev *cdev, u_long cmd, caddr_t data, + int32_t fflags, struct thread *td) +{ + return ENODEV; +} + + /* prototypes */ static device_probe_t ulpt_probe; static device_attach_t ulpt_attach; static device_detach_t ulpt_detach; -static d_close_t ulpt_close; static int ulpt_probe(device_t dev) @@ -450,7 +525,7 @@ mtx_lock(&(sc->sc_mtx)); - if (sc->sc_flags & ULPT_FLAG_WAIT_USB) { + if (sc->sc_flags & ULPT_FLAG_WAIT_USB) { sc->sc_flags &= ~ULPT_FLAG_WAIT_USB; wakeup(&(sc->sc_wakeup_detach)); } @@ -467,22 +542,19 @@ struct ulpt_softc *sc = device_get_softc(dev); struct usbd_interface *iface_ptr = uaa->iface; usb_interface_descriptor_t *id; + const char * p_buf[3]; int32_t iface_index = uaa->iface_index; int32_t iface_alt_index = 0; int32_t unit = device_get_unit(dev); - usbd_status err; + int32_t error; + char buf_1[16]; + char buf_2[16]; DPRINTF(10, "sc=%p\n", sc); sc->sc_dev = dev; - sc->sc_udev = uaa->device; - sc->sc_rdq_free.ifq_maxlen = ULPT_IFQ_MAXLEN; - sc->sc_rdq_used.ifq_maxlen = ULPT_IFQ_MAXLEN; - sc->sc_wrq_free.ifq_maxlen = ULPT_IFQ_MAXLEN; - sc->sc_wrq_used.ifq_maxlen = ULPT_IFQ_MAXLEN; - - usbd_set_desc(dev, sc->sc_udev); + usbd_set_desc(dev, uaa->device); mtx_init(&(sc->sc_mtx), "ulpt lock", NULL, MTX_DEF|MTX_RECURSE); @@ -494,30 +566,16 @@ sc->sc_flags |= ULPT_FLAG_WAIT_CO; #endif - sc->sc_mem_ptr_1 = - usbd_alloc_mbufs(M_DEVBUF, &(sc->sc_rdq_free), ULPT_BSIZE, ULPT_IFQ_MAXLEN); - - if (sc->sc_mem_ptr_1 == NULL) { - goto detach; - } - - sc->sc_mem_ptr_2 = - usbd_alloc_mbufs(M_DEVBUF, &(sc->sc_wrq_free), ULPT_BSIZE, ULPT_IFQ_MAXLEN); - - if (sc->sc_mem_ptr_2 == NULL) { - goto detach; - } - /* search through all the descriptors looking for bidir mode */ while(iface_alt_index < 32) { - err = usbd_fill_iface_data - (sc->sc_udev, iface_index, iface_alt_index); + error = usbd_fill_iface_data + (uaa->device, iface_index, iface_alt_index); - if (err) { + if (error) { DPRINTF(0, "end of alternate settings, " - "error=%s\n", usbd_errstr(err)); + "error=%s\n", usbd_errstr(error)); goto detach; } @@ -540,29 +598,29 @@ if (iface_alt_index) { - err = usbreq_set_interface - (sc->sc_udev, iface_index, iface_alt_index); + error = usbreq_set_interface + (uaa->device, iface_index, iface_alt_index); - if (err) { + if (error) { DPRINTF(0, "could not set alternate " - "config, error=%s\n", usbd_errstr(err)); + "config, error=%s\n", usbd_errstr(error)); goto detach; } } sc->sc_iface_no = id->bInterfaceNumber; - err = usbd_transfer_setup(sc->sc_udev, iface_index, sc->sc_xfer, - ulpt_config, ULPT_N_TRANSFER, sc, &(sc->sc_mtx), - &ulpt_detach_complete); - if (err) { - DPRINTF(0, "error=%s\n", usbd_errstr(err)) ; + error = usbd_transfer_setup(uaa->device, iface_index, + sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, + sc, &(sc->sc_mtx), &(ulpt_detach_complete)); + if (error) { + DPRINTF(0, "error=%s\n", usbd_errstr(error)) ; goto detach; } sc->sc_flags |= ULPT_FLAG_WAIT_USB; - if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BROKEN_BIDIR) { + if (usbd_get_quirks(uaa->device)->uq_flags & UQ_BROKEN_BIDIR) { /* this device doesn't handle reading properly. */ sc->sc_flags |= ULPT_FLAG_NO_READ; } @@ -587,9 +645,9 @@ USETW(req.wValue, cd->bConfigurationValue); USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); USETW(req.wLength, sizeof devinfo - 1); - err = usbd_do_request_flags(dev, &req, devinfo, USBD_SHORT_XFER_OK, + error = usbd_do_request_flags(dev, &req, devinfo, USBD_SHORT_XFER_OK, &alen, USBD_DEFAULT_TIMEOUT); - if (err) { + if (error) { device_printf(sc->sc_dev, "cannot get device id\n"); } else if (alen <= 2) { device_printf(sc->sc_dev, "empty device id, no " @@ -607,20 +665,33 @@ } #endif - sc->sc_cdev_1 = make_dev - (&ulpt_cdevsw, (2*unit)|0, UID_ROOT, GID_OPERATOR, - 0644, "ulpt%d", unit); + snprintf(buf_1, sizeof(buf_1), "ulpt%d", unit); + snprintf(buf_2, sizeof(buf_2), "unlpt%d", unit); - sc->sc_cdev_2 = make_dev - (&ulpt_cdevsw, (2*unit)|1, UID_ROOT, GID_OPERATOR, - 0644, "unlpt%d", unit); + p_buf[0] = buf_1; + p_buf[1] = buf_2; + p_buf[2] = NULL; - if (sc->sc_cdev_1) { - DEV2SC(sc->sc_cdev_1) = sc; - } + sc->sc_cdev.sc_start_read = &ulpt_start_read; + sc->sc_cdev.sc_start_write = &ulpt_start_write; + sc->sc_cdev.sc_stop_read = &ulpt_stop_read; + sc->sc_cdev.sc_stop_write = &ulpt_stop_write; + sc->sc_cdev.sc_open = &ulpt_open; + sc->sc_cdev.sc_ioctl = &ulpt_ioctl; + sc->sc_cdev.sc_flags |= (USB_CDEV_FLAG_FWD_SHORT| + USB_CDEV_FLAG_WAKEUP_RD_IMMED| + USB_CDEV_FLAG_WAKEUP_WR_IMMED); - if (sc->sc_cdev_2) { - DEV2SC(sc->sc_cdev_2) = sc; + /* make the buffers one byte larger than maximum so + * that one can detect too large read/writes and + * short transfers: + */ + error = usb_cdev_attach(&(sc->sc_cdev), sc, &(sc->sc_mtx), p_buf, + UID_ROOT, GID_OPERATOR, 0644, + ULPT_BSIZE, ULPT_IFQ_MAXLEN, + ULPT_BSIZE, ULPT_IFQ_MAXLEN); + if (error) { + goto detach; } /* start watchdog (returns unlocked) */ @@ -644,51 +715,21 @@ DPRINTF(0, "sc=%p\n", sc); - mtx_lock(&(sc->sc_mtx)); - sc->sc_flags |= ULPT_FLAG_GONE; - mtx_unlock(&(sc->sc_mtx)); - - if (sc->sc_cdev_1) { - - ulpt_close(sc->sc_cdev_1, 0, 0, 0); - - DEV2SC(sc->sc_cdev_1) = NULL; - - destroy_dev(sc->sc_cdev_1); - } - - if (sc->sc_cdev_2) { + usb_cdev_detach(&(sc->sc_cdev)); - ulpt_close(sc->sc_cdev_2, 0, 0, 0); - - DEV2SC(sc->sc_cdev_2) = NULL; - - destroy_dev(sc->sc_cdev_2); - } - mtx_lock(&(sc->sc_mtx)); - __callout_stop(&(sc->sc_watchdog)); - mtx_unlock(&(sc->sc_mtx)); usbd_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER); - if (sc->sc_mem_ptr_1) { - free(sc->sc_mem_ptr_1, M_DEVBUF); - } - - if (sc->sc_mem_ptr_2) { - free(sc->sc_mem_ptr_2, M_DEVBUF); - } - /* wait for callbacks to be aborted */ mtx_lock(&(sc->sc_mtx)); while (sc->sc_flags & (ULPT_FLAG_WAIT_USB|ULPT_FLAG_WAIT_CO)) { error = msleep(&(sc->sc_wakeup_detach), &(sc->sc_mtx), - PRIBIO, "ulpt_sync_2", 0); + PRIBIO, "ulpt_sync", 0); } mtx_unlock(&(sc->sc_mtx)); @@ -697,389 +738,6 @@ return 0; } -static int -ulpt_uiomove(struct ulpt_softc *sc, u_int32_t context_bit, void *cp, int n, - struct uio *uio) -{ - int error; - - sc->sc_flags |= context_bit; - - mtx_unlock(&(sc->sc_mtx)); - - /* "uiomove()" can sleep so one - * needs to make a wrapper, exiting - * the mutex and checking things - */ - error = uiomove(cp, n, uio); - - mtx_lock(&(sc->sc_mtx)); - - sc->sc_flags &= ~context_bit; - - if (sc->sc_flags & ULPT_FLAG_CLOSING) { - wakeup(&(sc->sc_wakeup_sync_1)); - error = EINTR; - } - - if (sc->sc_flags & ULPT_FLAG_PIPE_ERR) { - error = EINTR; - } - - if (error) { - sc->sc_flags |= ULPT_FLAG_NO_FLUSH; - } - - return error; -} - -static int -ulpt_msleep(struct ulpt_softc *sc, u_int32_t context_bit, void *ident) -{ - int error; - - sc->sc_flags |= context_bit; - - error = msleep(ident, &(sc->sc_mtx), PRIBIO|PCATCH, "ulpt_sleep", 0); - - sc->sc_flags &= ~context_bit; - - if (sc->sc_flags & ULPT_FLAG_CLOSING) { - wakeup(&(sc->sc_wakeup_sync_1)); - error = EINTR; - } - - if (sc->sc_flags & ULPT_FLAG_PIPE_ERR) { - error = EINTR; - } - - if (error) { - sc->sc_flags |= ULPT_FLAG_NO_FLUSH; - } - return error; -} - -static int -ulpt_reset(struct ulpt_softc *sc) -{ - DPRINTF(1, "\n"); - - /* start reset, if not already started */ - - usbd_transfer_start(sc->sc_xfer[3]); - - return ulpt_msleep(sc, ULPT_FLAG_RST_SLP|ULPT_FLAG_RST_WUP, - &(sc->sc_wakeup_reset)); -} - -static int -ulpt_open(struct cdev *dev, int flag, int mode, struct thread *td) -{ - u_int8_t no_prime = (minor(dev) & 1); - struct ulpt_softc *sc = DEV2SC(dev); - struct usbd_mbuf *m; - int error = 0; - - DPRINTF(1, "\n"); - - if (sc == NULL) { - return EIO; - } - - mtx_lock(&(sc->sc_mtx)); - - if (sc->sc_flags & - (ULPT_FLAG_DEV_OPEN|ULPT_FLAG_GONE| - ULPT_FLAG_RST_SLP|ULPT_FLAG_RST_WUP)) { - error = EBUSY; - goto done; - } - - if (no_prime == 0) { - error = ulpt_reset(sc); - if (error) { - goto done; - } - } - - /* reset read queue */ - - while(1) { - USBD_IF_DEQUEUE(&(sc->sc_rdq_used), m); - - if (m) { - USBD_IF_ENQUEUE(&(sc->sc_rdq_free), m); - } else { - break; - } - } - - /* reset write queue */ - - while(1) { - USBD_IF_DEQUEUE(&(sc->sc_wrq_used), m); - - if (m) { - USBD_IF_ENQUEUE(&(sc->sc_wrq_free), m); - } else { - break; - } - } - - if (flag & FREAD) { - sc->sc_flags &= ~ULPT_FLAG_DUMP_READ; - } else { - sc->sc_flags |= ULPT_FLAG_DUMP_READ; - } - - sc->sc_flags |= ULPT_FLAG_DEV_OPEN; - - done: - mtx_unlock(&(sc->sc_mtx)); - - DPRINTF(0, "done, error=%d\n", error); - return error; -} - -static int -ulpt_close(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct ulpt_softc *sc = DEV2SC(dev); - int error; - - DPRINTF(1, "\n"); - - if (sc == NULL) { - return EIO; - } - - mtx_lock(&(sc->sc_mtx)); - - if (sc->sc_flags & (ULPT_FLAG_WR_FLUSH|ULPT_FLAG_CLOSING)) { - goto done; - } - - if (sc->sc_flags & ULPT_FLAG_DEV_OPEN) { - - /* - * wait for data to - * be written to pipe: - */ - - if (!(sc->sc_flags & (ULPT_FLAG_GONE|ULPT_FLAG_NO_FLUSH| - ULPT_FLAG_PIPE_ERR))) { - - sc->sc_flags |= ULPT_FLAG_WR_FLUSH; - - /* start write transfer, if not already started */ - - usbd_transfer_start(sc->sc_xfer[0]); - - while (sc->sc_flags & ULPT_FLAG_WR_FLUSH) { - - error = msleep(&(sc->sc_wakeup_flush), &(sc->sc_mtx), - PRIBIO|PCATCH, "ulpt_sync_0", 0); - if (error) { - break; - } - } - } - - sc->sc_flags |= ULPT_FLAG_CLOSING; - - if (sc->sc_xfer[0]) { - usbd_transfer_stop(sc->sc_xfer[0]); - } - - if (sc->sc_xfer[1]) { - usbd_transfer_stop(sc->sc_xfer[1]); - } - - while (sc->sc_flags & - (ULPT_FLAG_RD_SLP|ULPT_FLAG_RD_WUP|ULPT_FLAG_RD_UIO| - ULPT_FLAG_WR_SLP|ULPT_FLAG_WR_WUP|ULPT_FLAG_WR_UIO| - ULPT_FLAG_RST_SLP|ULPT_FLAG_RST_WUP)) { - - if (sc->sc_flags & ULPT_FLAG_RD_WUP) { - sc->sc_flags &= ~ULPT_FLAG_RD_WUP; - wakeup(&(sc->sc_wakeup_read)); - } - - if (sc->sc_flags & ULPT_FLAG_WR_WUP) { - sc->sc_flags &= ~ULPT_FLAG_WR_WUP; - wakeup(&(sc->sc_wakeup_write)); - } - - if (sc->sc_flags & ULPT_FLAG_RST_WUP) { - sc->sc_flags &= ~ULPT_FLAG_RST_WUP; - wakeup(&(sc->sc_wakeup_reset)); - } - - error = msleep(&(sc->sc_wakeup_sync_1), &(sc->sc_mtx), - PRIBIO, "ulpt_sync_1", 0); - } - - sc->sc_flags &= ~(ULPT_FLAG_DEV_OPEN| - ULPT_FLAG_CLOSING| - ULPT_FLAG_WR_FLUSH| - ULPT_FLAG_NO_FLUSH| - ULPT_FLAG_PIPE_ERR); - } - - done: - mtx_unlock(&(sc->sc_mtx)); - - DPRINTF(0, "closed\n"); - - return 0; -} - -static int -ulpt_write(struct cdev *dev, struct uio *uio, int flags) -{ - struct ulpt_softc *sc = DEV2SC(dev); - struct usbd_mbuf *m; - int error = 0; - int io_len; - - DPRINTF(1, "\n"); - - if (sc == NULL) { - return EIO; - } - - mtx_lock(&(sc->sc_mtx)); - - if(sc->sc_flags & (ULPT_FLAG_CLOSING|ULPT_FLAG_GONE| - ULPT_FLAG_WR_SLP|ULPT_FLAG_WR_UIO| - ULPT_FLAG_PIPE_ERR)) { - error = EIO; - goto done; - } - - while (uio->uio_resid) { - - USBD_IF_DEQUEUE(&sc->sc_wrq_free, m); - - if (m == NULL) { - error = ulpt_msleep(sc, (ULPT_FLAG_WR_SLP|ULPT_FLAG_WR_WUP), - &(sc->sc_wakeup_write)); - if (error) { - break; - } else { - continue; - } - } - - USBD_MBUF_RESET(m); - - io_len = min(m->cur_data_len, uio->uio_resid); - - m->cur_data_len = io_len; - - DPRINTF(1, "transfer %d bytes to %p\n", - io_len, m->cur_data_ptr); - - error = ulpt_uiomove(sc, ULPT_FLAG_WR_UIO, - m->cur_data_ptr, io_len, uio); - - if (error) { - USBD_IF_ENQUEUE(&sc->sc_wrq_free, m); - break; - } else { - USBD_IF_ENQUEUE(&sc->sc_wrq_used, m); - usbd_transfer_start(sc->sc_xfer[0]); - } - } - done: - mtx_unlock(&(sc->sc_mtx)); - - return error; -} - -static int -ulpt_read(struct cdev *dev, struct uio *uio, int flags) -{ - struct ulpt_softc *sc = DEV2SC(dev); - struct usbd_mbuf *m; - int error = 0; - int io_len; - - if (sc == NULL) { - return EIO; - } - - DPRINTF(1, "\n"); - - mtx_lock(&(sc->sc_mtx)); - - if(sc->sc_flags & (ULPT_FLAG_CLOSING|ULPT_FLAG_GONE| - ULPT_FLAG_RD_UIO|ULPT_FLAG_RD_SLP| - ULPT_FLAG_PIPE_ERR)) { - error = EIO; - goto done; - } - - while (uio->uio_resid) { - - USBD_IF_DEQUEUE(&sc->sc_rdq_used, m); - - if (m == NULL) { - - /* start reader thread */ - - usbd_transfer_start(sc->sc_xfer[1]); - - error = ulpt_msleep(sc, (ULPT_FLAG_RD_SLP|ULPT_FLAG_RD_WUP), - &(sc->sc_wakeup_read)); - if (error) { - break; - } else { - continue; - } - } - - io_len = min(m->cur_data_len, uio->uio_resid); - - DPRINTF(1, "transfer %d bytes from %p\n", - io_len, m->cur_data_ptr); - - error = ulpt_uiomove(sc, ULPT_FLAG_RD_UIO, >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606051536.k55Favuf098827>