From owner-p4-projects@FreeBSD.ORG Fri Mar 30 21:57:52 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 840B116A406; Fri, 30 Mar 2007 21:57:52 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 3ECF516A404 for ; Fri, 30 Mar 2007 21:57:52 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 2E9EB13C4AE for ; Fri, 30 Mar 2007 21:57:52 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l2ULvqHZ014148 for ; Fri, 30 Mar 2007 21:57:52 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l2ULvpYn014145 for perforce@freebsd.org; Fri, 30 Mar 2007 21:57:51 GMT (envelope-from hselasky@FreeBSD.org) Date: Fri, 30 Mar 2007 21:57:51 GMT Message-Id: <200703302157.l2ULvpYn014145@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 116977 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: Fri, 30 Mar 2007 21:57:52 -0000 http://perforce.freebsd.org/chv.cgi?CH=116977 Change 116977 by hselasky@hselasky_mini_itx on 2007/03/30 21:57:38 Finished converting uark to the new USB stack. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/uark.c#2 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/uark.c#2 (text+ko) ==== @@ -17,43 +17,34 @@ * * $FreeBSD: src/sys/dev/usb/uark.c,v 1.1 2006/11/15 09:13:24 maxim Exp $ */ + +/* + * NOTE: all function names beginning like "uark_cfg_" can only + * be called from within the config thread function ! + */ + #include #include #include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include +#include + +#include + #include "usbdevs.h" -#include +#define DPRINTF(...) { } -#ifdef UARK_DEBUG -#define DPRINTFN(n, x) do { \ - if (uarkdebug > (n)) \ - logprintf x; \ -} while (0) -int uarkebug = 0; -#else -#define DPRINTFN(n, x) -#endif -#define DPRINTF(x) DPRINTFN(0, x) +#define UARK_BUF_SIZE 512 -#define UARKBUFSZ 256 -#define UARK_CONFIG_NO 0 -#define UARK_IFACE_NO 0 +#define UARK_N_TRANSFER 4 /* units */ -#define UARK_SET_DATA_BITS(x) (x - 5) +#define UARK_SET_DATA_BITS(x) ((x) - 5) #define UARK_PARITY_NONE 0x00 #define UARK_PARITY_ODD 0x08 @@ -73,177 +64,367 @@ #define UARK_IFACE_INDEX 0 struct uark_softc { + struct ucom_super_softc sc_super_ucom; struct ucom_softc sc_ucom; - usbd_interface_handle sc_iface; + + struct usbd_xfer *sc_xfer[UARK_N_TRANSFER]; + struct usbd_device *sc_udev; + + uint8_t sc_flags; +#define UARK_FLAG_BULK_READ_STALL 0x01 +#define UARK_FLAG_BULK_WRITE_STALL 0x02 + uint8_t sc_msr; + uint8_t sc_lsr; +}; + +/* prototypes */ + +static device_probe_t uark_probe; +static device_attach_t uark_attach; +static device_detach_t uark_detach; + +static usbd_callback_t uark_bulk_write_callback; +static usbd_callback_t uark_bulk_write_clear_stall_callback; +static usbd_callback_t uark_bulk_read_callback; +static usbd_callback_t uark_bulk_read_clear_stall_callback; + +static void uark_start_read(struct ucom_softc *ucom); +static void uark_stop_read(struct ucom_softc *ucom); +static void uark_start_write(struct ucom_softc *ucom); +static void uark_stop_write(struct ucom_softc *ucom); + +static int uark_pre_param(struct ucom_softc *ucom, struct termios *t); +static void uark_cfg_param(struct ucom_softc *ucom, struct termios *t); +static void uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr); +static void uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff); +static void uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value); + +static const struct usbd_config +uark_xfer_config[UARK_N_TRANSFER] = { + + [0] = { + .type = UE_BULK, + .endpoint = -1, /* any */ + .direction = UE_DIR_OUT, + .bufsize = UARK_BUF_SIZE, + .flags = 0, + .callback = &uark_bulk_write_callback, + }, + + [1] = { + .type = UE_BULK, + .endpoint = -1, /* any */ + .direction = UE_DIR_IN, + .bufsize = UARK_BUF_SIZE, + .flags = USBD_SHORT_XFER_OK, + .callback = &uark_bulk_read_callback, + }, + + [2] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .flags = (USBD_USE_DMA), + .callback = &uark_bulk_write_clear_stall_callback, + .timeout = 1000, /* 1 second */ + }, + + [3] = { + .type = UE_CONTROL, + .endpoint = 0x00, /* Control pipe */ + .direction = -1, + .bufsize = sizeof(usb_device_request_t), + .flags = (USBD_USE_DMA), + .callback = &uark_bulk_read_clear_stall_callback, + .timeout = 1000, /* 1 second */ + }, +}; + +static const struct ucom_callback uark_callback = { + .ucom_cfg_get_status = &uark_cfg_get_status, + .ucom_cfg_set_break = &uark_cfg_set_break, + .ucom_cfg_param = &uark_cfg_param, + .ucom_pre_param = &uark_pre_param, + .ucom_start_read = &uark_start_read, + .ucom_stop_read = &uark_stop_read, + .ucom_start_write = &uark_start_write, + .ucom_stop_write = &uark_stop_write, +}; - u_char sc_msr; - u_char sc_lsr; +static device_method_t uark_methods[] = { + /* Device methods */ + DEVMETHOD(device_probe, uark_probe), + DEVMETHOD(device_attach, uark_attach), + DEVMETHOD(device_detach, uark_detach), + { 0, 0 } }; -static void uark_get_status(void *, int portno, u_char *lsr, u_char *msr); -static void uark_set(void *, int, int, int); -static int uark_param(void *, int, struct termios *); -static void uark_break(void *, int, int); -static int uark_cmd(struct uark_softc *, uint16_t, uint16_t); +static devclass_t uark_devclass; -struct ucom_callback uark_callback = { - uark_get_status, - uark_set, - uark_param, - NULL, - NULL, - NULL, - NULL, - NULL, +static driver_t uark_driver = { + .name = "uark", + .methods = uark_methods, + .size = sizeof(struct uark_softc), }; -static const struct uark_product { - uint16_t vendor; - uint16_t product; -} uark_products[] = { +DRIVER_MODULE(uark, uhub, uark_driver, uark_devclass, usbd_driver_load, 0); +MODULE_DEPEND(uark, usb, 1, 1, 1); +MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER); + +static const struct usb_devno uark_devs[] = { { USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116 }, - { 0, 0 } }; -USB_MATCH(uark) +#define uark_lookup(v, p) usb_lookup(uark_devs, v, p) + +static int +uark_probe(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + + if (uaa->iface) { + return UMATCH_NONE; + } + + return (uark_lookup(uaa->vendor, uaa->product) ? + UMATCH_VENDOR_PRODUCT : UMATCH_NONE); +} + +static int +uark_attach(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + struct uark_softc *sc = device_get_softc(dev); + int32_t error; + + if (sc == NULL) { + return ENOMEM; + } + + usbd_set_desc(dev, uaa->device); + + sc->sc_udev = uaa->device; + + /* Move the device into the configured state */ + error = usbd_set_config_index(uaa->device, UARK_CONFIG_INDEX, 1); + if (error) { + device_printf(dev, "failed to set configuration, err=%s\n", + usbd_errstr(error)); + goto detach; + } + + error = usbd_transfer_setup + (uaa->device, UARK_IFACE_INDEX, + sc->sc_xfer, uark_xfer_config, UARK_N_TRANSFER, + sc, &Giant); + + if (error) { + device_printf(dev, "allocating control USB " + "transfers failed!\n"); + goto detach; + } + + /* clear stall at first run */ + sc->sc_flags |= (UARK_FLAG_BULK_WRITE_STALL| + UARK_FLAG_BULK_READ_STALL); + + error = ucom_attach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1, sc, + &uark_callback, &Giant); + if (error) { + DPRINTF(0, "ucom_attach failed\n"); + goto detach; + } + + return 0; /* success */ + + detach: + uark_detach(dev); + return ENXIO; /* failure */ +} + +static int +uark_detach(device_t dev) +{ + struct uark_softc *sc = device_get_softc(dev); + + ucom_detach(&(sc->sc_super_ucom), &(sc->sc_ucom), 1); + + usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER); + + return 0; +} + +static void +uark_bulk_write_callback(struct usbd_xfer *xfer) { - USB_MATCH_START(uark, uaa); - int i; + struct uark_softc *sc = xfer->priv_sc; + uint32_t actlen; + + USBD_CHECK_STATUS(xfer); - if (uaa->iface != NULL) - return (UMATCH_NONE); +tr_error: + if (xfer->error != USBD_CANCELLED) { + sc->sc_flags |= UARK_FLAG_BULK_WRITE_STALL; + usbd_transfer_start(sc->sc_xfer[2]); + } + return; - for (i = 0; uark_products[i].vendor != 0; i++) { - if (uark_products[i].vendor == uaa->vendor && - uark_products[i].product == uaa->product) { - return (UMATCH_VENDOR_PRODUCT); - } +tr_setup: +tr_transferred: + if (sc->sc_flags & UARK_FLAG_BULK_WRITE_STALL) { + usbd_transfer_start(sc->sc_xfer[2]); + return; } - return (UMATCH_NONE); + if (ucom_get_data(&(sc->sc_ucom), xfer->buffer, + UARK_BUF_SIZE, &actlen)) { + xfer->length = actlen; + usbd_start_hardware(xfer); + } + return; } -USB_ATTACH(uark) +static void +uark_bulk_write_clear_stall_callback(struct usbd_xfer *xfer) { - USB_ATTACH_START(uark, sc, uaa); - usbd_device_handle dev = uaa->device; - usbd_interface_handle iface; - usb_interface_descriptor_t *id; - usb_endpoint_descriptor_t *ed; - usbd_status error; - char *devinfo; - const char *devname; - int i; - struct ucom_softc *ucom = &sc->sc_ucom; + struct uark_softc *sc = xfer->priv_sc; + struct usbd_xfer *xfer_other = sc->sc_xfer[0]; - devinfo = malloc(1024, M_USBDEV, M_WAITOK); + USBD_CHECK_STATUS(xfer); - bzero(ucom, sizeof(struct ucom_softc)); - ucom->sc_dev = self; - ucom->sc_udev = dev; + tr_setup: + /* start clear stall */ + usbd_clear_stall_tr_setup(xfer, xfer_other); + return; - devname = device_get_nameunit(ucom->sc_dev); + tr_transferred: + usbd_clear_stall_tr_transferred(xfer, xfer_other); + sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL; + usbd_transfer_start(xfer_other); + return; - if (uaa->iface == NULL) { - /* Move the device into the configured state. */ - error = usbd_set_config_index(dev, UARK_CONFIG_INDEX, 1); - if (error) { - printf("\n%s: failed to set configuration, err=%s\n", - devname, usbd_errstr(error)); - goto bad; - } - error = - usbd_device2interface_handle(dev, UARK_IFACE_INDEX, &iface); - if (error) { - printf("\n%s: failed to get interface, err=%s\n", - devname, usbd_errstr(error)); - goto bad; - } - } else - iface = uaa->iface; + tr_error: + sc->sc_flags &= ~UARK_FLAG_BULK_WRITE_STALL; + DPRINTF(sc, 0, "clear stall failed, error=%s\n", + usbd_errstr(xfer->error)); + return; +} - usbd_devinfo(dev, 0, devinfo); - printf("%s: %s\n", devname, devinfo); +static void +uark_bulk_read_callback(struct usbd_xfer *xfer) +{ + struct uark_softc *sc = xfer->priv_sc; - id = usbd_get_interface_descriptor(iface); - ucom->sc_iface = iface; + USBD_CHECK_STATUS(xfer); - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1; - for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(iface, i); - if (ed == NULL) { - printf("%s: could not read endpoint descriptor\n", - devname); - goto bad; - } - if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkin_no = ed->bEndpointAddress; - else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && - UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) - ucom->sc_bulkout_no = ed->bEndpointAddress; + tr_error: + if (xfer->error != USBD_CANCELLED) { + sc->sc_flags |= UARK_FLAG_BULK_READ_STALL; + usbd_transfer_start(sc->sc_xfer[3]); } - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) { - printf("%s: missing endpoint\n", devname); - goto bad; + return; + + tr_transferred: + ucom_put_data(&(sc->sc_ucom), xfer->buffer, + xfer->actlen); + + tr_setup: + if (sc->sc_flags & UARK_FLAG_BULK_READ_STALL) { + usbd_transfer_start(sc->sc_xfer[3]); + } else { + usbd_start_hardware(xfer); } - ucom->sc_parent = sc; - ucom->sc_ibufsize = UARKBUFSZ; - ucom->sc_obufsize = UARKBUFSZ; - ucom->sc_ibufsizepad = UARKBUFSZ; - ucom->sc_opkthdrlen = 0; + return; +} - ucom->sc_callback = &uark_callback; +static void +uark_bulk_read_clear_stall_callback(struct usbd_xfer *xfer) +{ + struct uark_softc *sc = xfer->priv_sc; + struct usbd_xfer *xfer_other = sc->sc_xfer[1]; - DPRINTF(("uark: in=0x%x out=0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no)); - ucom_attach(&sc->sc_ucom); - free(devinfo, M_USBDEV); + USBD_CHECK_STATUS(xfer); - USB_ATTACH_SUCCESS_RETURN; + tr_setup: + /* start clear stall */ + usbd_clear_stall_tr_setup(xfer, xfer_other); + return; -bad: - DPRINTF(("uftdi_attach: ATTACH ERROR\n")); - ucom->sc_dying = 1; - free(devinfo, M_USBDEV); + tr_transferred: + usbd_clear_stall_tr_transferred(xfer, xfer_other); + sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL; + usbd_transfer_start(xfer_other); + return; - USB_ATTACH_ERROR_RETURN; + tr_error: + sc->sc_flags &= ~UARK_FLAG_BULK_READ_STALL; + DPRINTF(sc, 0, "clear stall failed, error=%s\n", + usbd_errstr(xfer->error)); + return; } -USB_DETACH(uark) +static void +uark_start_read(struct ucom_softc *ucom) { - USB_DETACH_START(uark, sc); - int rv = 0; + struct uark_softc *sc = ucom->sc_parent; + usbd_transfer_start(sc->sc_xfer[1]); + return; +} - DPRINTF(("uark_detach: sc=%p\n", sc)); - sc->sc_ucom.sc_dying = 1; - rv = ucom_detach(&sc->sc_ucom); +static void +uark_stop_read(struct ucom_softc *ucom) +{ + struct uark_softc *sc = ucom->sc_parent; + usbd_transfer_stop(sc->sc_xfer[3]); + usbd_transfer_stop(sc->sc_xfer[1]); + return; +} - return (rv); +static void +uark_start_write(struct ucom_softc *ucom) +{ + struct uark_softc *sc = ucom->sc_parent; + usbd_transfer_start(sc->sc_xfer[0]); + return; } static void -uark_set(void *vsc, int portno, int reg, int onoff) +uark_stop_write(struct ucom_softc *ucom) { - struct uark_softc *sc = vsc; + struct uark_softc *sc = ucom->sc_parent; + usbd_transfer_stop(sc->sc_xfer[2]); + usbd_transfer_stop(sc->sc_xfer[0]); + return; +} - switch (reg) { - case UCOM_SET_BREAK: - uark_break(sc, portno, onoff); - return; - /* NOTREACHED */ - case UCOM_SET_DTR: - case UCOM_SET_RTS: +static int +uark_pre_param(struct ucom_softc *ucom, struct termios *t) +{ + switch (t->c_ospeed) { + case 300: + case 600: + case 1200: + case 1800: + case 2400: + case 4800: + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + break; default: - return; - /* NOTREACHED */ + return EINVAL; } + return 0; } -static int -uark_param(void *vsc, int portno, struct termios *t) +static void +uark_cfg_param(struct ucom_softc *ucom, struct termios *t) { - struct uark_softc *sc = (struct uark_softc *)vsc; - int data; + struct uark_softc *sc = ucom->sc_parent; + uint16_t data; switch (t->c_ospeed) { case 300: @@ -257,29 +438,30 @@ case 38400: case 57600: case 115200: - uark_cmd(sc, 3, 0x83); - uark_cmd(sc, 0, (UARK_BAUD_REF / t->c_ospeed) & 0xFF); - uark_cmd(sc, 1, (UARK_BAUD_REF / t->c_ospeed) >> 8); - uark_cmd(sc, 3, 0x03); + data = (UARK_BAUD_REF / t->c_ospeed); + uark_cfg_write(sc, 3, 0x83); + uark_cfg_write(sc, 0, data & 0xFF); + uark_cfg_write(sc, 1, data >> 8); + uark_cfg_write(sc, 3, 0x03); break; default: - return (EINVAL); - /* NOTREACHED */ + return; } - if (ISSET(t->c_cflag, CSTOPB)) + + if (t->c_cflag & CSTOPB) data = UARK_STOP_BITS_2; else data = UARK_STOP_BITS_1; - if (ISSET(t->c_cflag, PARENB)) { - if (ISSET(t->c_cflag, PARODD)) + if (t->c_cflag & PARENB) { + if (t->c_cflag & PARODD) data |= UARK_PARITY_ODD; else data |= UARK_PARITY_EVEN; } else data |= UARK_PARITY_NONE; - switch (ISSET(t->c_cflag, CSIZE)) { + switch (t->c_cflag & CSIZE) { case CS5: data |= UARK_SET_DATA_BITS(5); break; @@ -289,79 +471,58 @@ case CS7: data |= UARK_SET_DATA_BITS(7); break; + default: case CS8: data |= UARK_SET_DATA_BITS(8); break; } - uark_cmd(sc, 3, 0x00); - uark_cmd(sc, 3, data); - - return (0); + uark_cfg_write(sc, 3, 0x00); + uark_cfg_write(sc, 3, data); + return; } -void -uark_get_status(void *vsc, int portno, u_char *lsr, u_char *msr) +static void +uark_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) { - struct uark_softc *sc = vsc; + struct uark_softc *sc = ucom->sc_parent; - if (msr != NULL) - *msr = sc->sc_msr; - if (lsr != NULL) - *lsr = sc->sc_lsr; + *lsr = sc->sc_lsr; + *msr = sc->sc_msr; + return; } -void -uark_break(void *vsc, int portno, int onoff) +static void +uark_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff) { -#ifdef UARK_DEBUG - struct uark_softc *sc = vsc; + struct uark_softc *sc = ucom->sc_parent; - printf("%s: break %s!\n", device_get_nameunit(sc->sc_dev), - onoff ? "on" : "off"); + DPRINTF(sc, 0, "onoff=%d\n", onoff); - if (onoff) - /* break on */ - uark_cmd(sc, 4, 0x01); - else - uark_cmd(sc, 4, 0x00); -#endif + uark_cfg_write(sc, 4, onoff ? 0x01 : 0x00); + return; } -int -uark_cmd(struct uark_softc *sc, uint16_t index, uint16_t value) +static void +uark_cfg_write(struct uark_softc *sc, uint16_t index, uint16_t value) { usb_device_request_t req; usbd_status err; - struct ucom_softc *ucom = &sc->sc_ucom; + + if (ucom_cfg_is_gone(&(sc->sc_ucom))) { + return; + } req.bmRequestType = UARK_WRITE; req.bRequest = UARK_REQUEST; USETW(req.wValue, value); USETW(req.wIndex, index); USETW(req.wLength, 0); - err = usbd_do_request(ucom->sc_udev, &req, NULL); - if (err) - return (EIO); - - return (0); + err = usbd_do_request_flags_mtx(sc->sc_udev, &Giant, &req, + NULL, 0, NULL, 1000); + if (err) { + DPRINTF(sc, -1, "device request failed, err=%s " + "(ignored)\n", usbd_errstr(err)); + } + return; } - -static device_method_t uark_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, uark_match), - DEVMETHOD(device_attach, uark_attach), - DEVMETHOD(device_detach, uark_detach), - - { 0, 0 } -}; - -static driver_t uark_driver = { - "ucom", - uark_methods, - sizeof (struct uark_softc) -}; - -DRIVER_MODULE(uark, uhub, uark_driver, ucom_devclass, usbd_driver_load, 0); -MODULE_DEPEND(uark, usb, 1, 1, 1); -MODULE_DEPEND(uark, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);