Home | History | Annotate | Line # | Download | only in usb
uvscom.c revision 1.13.6.1
      1  1.13.6.1      yamt /*	$NetBSD: uvscom.c,v 1.13.6.1 2005/03/19 08:35:58 yamt Exp $	*/
      2       1.1  augustss /*-
      3       1.1  augustss  * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama (at) jp.FreeBSD.org>.
      4       1.1  augustss  * All rights reserved.
      5       1.1  augustss  *
      6       1.1  augustss  * Redistribution and use in source and binary forms, with or without
      7       1.1  augustss  * modification, are permitted provided that the following conditions
      8       1.1  augustss  * are met:
      9       1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     10       1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     11       1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     13       1.1  augustss  *    documentation and/or other materials provided with the distribution.
     14       1.1  augustss  *
     15       1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16       1.1  augustss  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17       1.1  augustss  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18       1.1  augustss  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19       1.1  augustss  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20       1.1  augustss  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21       1.1  augustss  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22       1.1  augustss  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23       1.1  augustss  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24       1.1  augustss  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25       1.1  augustss  * SUCH DAMAGE.
     26       1.1  augustss  *
     27       1.1  augustss  * $FreeBSD: src/sys/dev/usb/uvscom.c,v 1.1 2002/03/18 18:23:39 joe Exp $
     28       1.1  augustss  */
     29       1.1  augustss 
     30       1.1  augustss /*
     31       1.1  augustss  * uvscom: SUNTAC Slipper U VS-10U driver.
     32       1.1  augustss  * Slipper U is a PC card to USB converter for data communication card
     33       1.1  augustss  * adapter.  It supports DDI Pocket's Air H" C@rd, C@rd H" 64, NTT's P-in,
     34       1.1  augustss  * P-in m@ater and various data communication card adapters.
     35       1.1  augustss  */
     36      1.10     lukem 
     37      1.10     lukem #include <sys/cdefs.h>
     38  1.13.6.1      yamt __KERNEL_RCSID(0, "$NetBSD: uvscom.c,v 1.13.6.1 2005/03/19 08:35:58 yamt Exp $");
     39       1.1  augustss 
     40       1.1  augustss #include <sys/param.h>
     41       1.1  augustss #include <sys/systm.h>
     42       1.1  augustss #include <sys/kernel.h>
     43       1.1  augustss #include <sys/malloc.h>
     44       1.1  augustss #include <sys/fcntl.h>
     45       1.1  augustss #include <sys/conf.h>
     46       1.1  augustss #include <sys/tty.h>
     47       1.1  augustss #include <sys/file.h>
     48       1.1  augustss #if defined(__FreeBSD__)
     49       1.1  augustss #include <sys/bus.h>
     50       1.1  augustss #include <sys/ioccom.h>
     51       1.1  augustss #if __FreeBSD_version >= 500014
     52       1.1  augustss #include <sys/selinfo.h>
     53       1.1  augustss #else
     54       1.1  augustss #include <sys/select.h>
     55       1.1  augustss #endif
     56       1.1  augustss #else
     57       1.1  augustss #include <sys/ioctl.h>
     58       1.1  augustss #include <sys/device.h>
     59       1.1  augustss #endif
     60       1.1  augustss #include <sys/proc.h>
     61       1.1  augustss #include <sys/poll.h>
     62       1.1  augustss 
     63       1.1  augustss #include <dev/usb/usb.h>
     64       1.1  augustss #include <dev/usb/usbcdc.h>
     65       1.1  augustss 
     66       1.1  augustss #include <dev/usb/usbdi.h>
     67       1.1  augustss #include <dev/usb/usbdi_util.h>
     68       1.1  augustss #include <dev/usb/usbdevs.h>
     69       1.1  augustss #include <dev/usb/usb_quirks.h>
     70       1.1  augustss 
     71       1.1  augustss #include <dev/usb/ucomvar.h>
     72       1.1  augustss 
     73       1.1  augustss #ifdef UVSCOM_DEBUG
     74       1.1  augustss static int	uvscomdebug = 1;
     75       1.1  augustss 
     76       1.1  augustss #if defined(__FreeBSD__)
     77       1.1  augustss #include <sys/sysctl.h>
     78       1.1  augustss 
     79       1.1  augustss SYSCTL_DECL(_debug_usb);
     80       1.1  augustss SYSCTL_INT(_debug_usb, OID_AUTO, uvscom, CTLFLAG_RW,
     81       1.1  augustss 	   &uvscomdebug, 0, "uvscom debug level");
     82       1.1  augustss 
     83       1.1  augustss #endif
     84       1.1  augustss 
     85       1.1  augustss #define DPRINTFN(n, x)  do { \
     86       1.1  augustss 				if (uvscomdebug > (n)) \
     87       1.1  augustss 					logprintf x; \
     88       1.1  augustss 			} while (0)
     89       1.1  augustss #else
     90       1.1  augustss #define DPRINTFN(n, x)
     91       1.1  augustss #endif
     92       1.1  augustss #define DPRINTF(x) DPRINTFN(0, x)
     93       1.5  augustss 
     94       1.5  augustss #if defined(__FreeBSD__)
     95       1.5  augustss #define UVSCOM_MODVER		1	/* module version */
     96       1.5  augustss #endif
     97       1.1  augustss 
     98       1.1  augustss #define	UVSCOM_CONFIG_INDEX	0
     99       1.1  augustss #define	UVSCOM_IFACE_INDEX	0
    100       1.1  augustss 
    101       1.1  augustss #define UVSCOM_INTR_INTERVAL	100	/* mS */
    102       1.1  augustss 
    103       1.1  augustss #define UVSCOM_UNIT_WAIT	5
    104       1.1  augustss 
    105       1.1  augustss /* Request */
    106       1.1  augustss #define UVSCOM_SET_SPEED	0x10
    107       1.1  augustss #define UVSCOM_LINE_CTL		0x11
    108       1.1  augustss #define UVSCOM_SET_PARAM	0x12
    109       1.1  augustss #define UVSCOM_READ_STATUS	0xd0
    110       1.1  augustss #define UVSCOM_SHUTDOWN		0xe0
    111       1.1  augustss 
    112       1.1  augustss /* UVSCOM_SET_SPEED parameters */
    113       1.1  augustss #define UVSCOM_SPEED_150BPS	0x00
    114       1.1  augustss #define UVSCOM_SPEED_300BPS	0x01
    115       1.1  augustss #define UVSCOM_SPEED_600BPS	0x02
    116       1.1  augustss #define UVSCOM_SPEED_1200BPS	0x03
    117       1.1  augustss #define UVSCOM_SPEED_2400BPS	0x04
    118       1.1  augustss #define UVSCOM_SPEED_4800BPS	0x05
    119       1.1  augustss #define UVSCOM_SPEED_9600BPS	0x06
    120       1.1  augustss #define UVSCOM_SPEED_19200BPS	0x07
    121       1.1  augustss #define UVSCOM_SPEED_38400BPS	0x08
    122       1.1  augustss #define UVSCOM_SPEED_57600BPS	0x09
    123       1.1  augustss #define UVSCOM_SPEED_115200BPS	0x0a
    124       1.1  augustss 
    125       1.1  augustss /* UVSCOM_LINE_CTL parameters */
    126       1.1  augustss #define UVSCOM_BREAK		0x40
    127       1.1  augustss #define UVSCOM_RTS		0x02
    128       1.1  augustss #define UVSCOM_DTR		0x01
    129       1.1  augustss #define UVSCOM_LINE_INIT	0x08
    130       1.1  augustss 
    131       1.1  augustss /* UVSCOM_SET_PARAM parameters */
    132       1.1  augustss #define UVSCOM_DATA_MASK	0x03
    133       1.1  augustss #define UVSCOM_DATA_BIT_8	0x03
    134       1.1  augustss #define UVSCOM_DATA_BIT_7	0x02
    135       1.1  augustss #define UVSCOM_DATA_BIT_6	0x01
    136       1.1  augustss #define UVSCOM_DATA_BIT_5	0x00
    137       1.1  augustss 
    138       1.1  augustss #define UVSCOM_STOP_MASK	0x04
    139       1.1  augustss #define UVSCOM_STOP_BIT_2	0x04
    140       1.1  augustss #define UVSCOM_STOP_BIT_1	0x00
    141       1.1  augustss 
    142       1.1  augustss #define UVSCOM_PARITY_MASK	0x18
    143       1.1  augustss #define UVSCOM_PARITY_EVEN	0x18
    144       1.1  augustss #if 0
    145       1.1  augustss #define UVSCOM_PARITY_UNK	0x10
    146       1.1  augustss #endif
    147       1.1  augustss #define UVSCOM_PARITY_ODD	0x08
    148       1.1  augustss #define UVSCOM_PARITY_NONE	0x00
    149       1.1  augustss 
    150       1.1  augustss /* Status bits */
    151       1.1  augustss #define UVSCOM_TXRDY		0x04
    152       1.1  augustss #define UVSCOM_RXRDY		0x01
    153       1.1  augustss 
    154       1.1  augustss #define UVSCOM_DCD		0x08
    155       1.1  augustss #define UVSCOM_NOCARD		0x04
    156       1.1  augustss #define UVSCOM_DSR		0x02
    157       1.1  augustss #define UVSCOM_CTS		0x01
    158       1.1  augustss #define UVSCOM_USTAT_MASK	(UVSCOM_NOCARD | UVSCOM_DSR | UVSCOM_CTS)
    159       1.1  augustss 
    160       1.1  augustss struct	uvscom_softc {
    161       1.1  augustss 	USBBASEDEVICE		sc_dev;		/* base device */
    162       1.1  augustss 	usbd_device_handle	sc_udev;	/* USB device */
    163       1.1  augustss 	usbd_interface_handle	sc_iface;	/* interface */
    164       1.1  augustss 	int			sc_iface_number;/* interface number */
    165       1.1  augustss 
    166       1.1  augustss 	usbd_interface_handle	sc_intr_iface;	/* interrupt interface */
    167       1.1  augustss 	int			sc_intr_number;	/* interrupt number */
    168       1.1  augustss 	usbd_pipe_handle	sc_intr_pipe;	/* interrupt pipe */
    169       1.1  augustss 	u_char			*sc_intr_buf;	/* interrupt buffer */
    170       1.1  augustss 	int			sc_isize;
    171       1.1  augustss 
    172       1.1  augustss 	u_char			sc_dtr;		/* current DTR state */
    173       1.1  augustss 	u_char			sc_rts;		/* current RTS state */
    174       1.1  augustss 
    175       1.1  augustss 	u_char			sc_lsr;		/* Local status register */
    176       1.1  augustss 	u_char			sc_msr;		/* uvscom status register */
    177       1.1  augustss 
    178       1.1  augustss 	uint16_t		sc_lcr;		/* Line control */
    179       1.1  augustss 	u_char			sc_usr;		/* unit status */
    180       1.1  augustss 
    181       1.1  augustss 	device_ptr_t		sc_subdev;	/* ucom device */
    182       1.1  augustss 	u_char			sc_dying;	/* disconnecting */
    183       1.1  augustss };
    184       1.1  augustss 
    185       1.1  augustss /*
    186       1.1  augustss  * These are the maximum number of bytes transferred per frame.
    187       1.1  augustss  * The output buffer size cannot be increased due to the size encoding.
    188       1.1  augustss  */
    189       1.1  augustss #define UVSCOMIBUFSIZE 512
    190       1.1  augustss #define UVSCOMOBUFSIZE 64
    191       1.1  augustss 
    192       1.1  augustss Static	usbd_status uvscom_readstat(struct uvscom_softc *);
    193       1.1  augustss Static	usbd_status uvscom_shutdown(struct uvscom_softc *);
    194       1.1  augustss Static	usbd_status uvscom_reset(struct uvscom_softc *);
    195       1.1  augustss Static	usbd_status uvscom_set_line_coding(struct uvscom_softc *,
    196       1.1  augustss 					   uint16_t, uint16_t);
    197       1.1  augustss Static	usbd_status uvscom_set_line(struct uvscom_softc *, uint16_t);
    198       1.1  augustss Static	usbd_status uvscom_set_crtscts(struct uvscom_softc *);
    199       1.1  augustss Static	void uvscom_get_status(void *, int, u_char *, u_char *);
    200       1.1  augustss Static	void uvscom_dtr(struct uvscom_softc *, int);
    201       1.1  augustss Static	void uvscom_rts(struct uvscom_softc *, int);
    202       1.1  augustss Static	void uvscom_break(struct uvscom_softc *, int);
    203       1.1  augustss 
    204       1.1  augustss Static	void uvscom_set(void *, int, int, int);
    205       1.1  augustss Static	void uvscom_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
    206       1.1  augustss Static	int  uvscom_param(void *, int, struct termios *);
    207       1.1  augustss Static	int  uvscom_open(void *, int);
    208       1.1  augustss Static	void uvscom_close(void *, int);
    209       1.1  augustss 
    210       1.1  augustss struct ucom_methods uvscom_methods = {
    211       1.1  augustss 	uvscom_get_status,
    212       1.1  augustss 	uvscom_set,
    213       1.1  augustss 	uvscom_param,
    214       1.1  augustss 	NULL, /* uvscom_ioctl, TODO */
    215       1.1  augustss 	uvscom_open,
    216       1.1  augustss 	uvscom_close,
    217       1.1  augustss 	NULL,
    218       1.1  augustss 	NULL
    219       1.1  augustss };
    220       1.1  augustss 
    221       1.1  augustss static const struct usb_devno uvscom_devs [] = {
    222  1.13.6.1      yamt 	/* SUNTAC U-Cable type A4 */
    223  1.13.6.1      yamt 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4 },
    224       1.8    ichiro 	/* SUNTAC U-Cable type D2 */
    225       1.8    ichiro 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L },
    226       1.1  augustss 	/* SUNTAC U-Cable type P1 */
    227       1.1  augustss 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1 },
    228       1.1  augustss 	/* SUNTAC Slipper U  */
    229       1.1  augustss 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U },
    230       1.9    ichiro 	/* SUNTAC Ir-Trinity */
    231       1.9    ichiro 	{ USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U },
    232       1.1  augustss };
    233       1.1  augustss #define uvscom_lookup(v, p) usb_lookup(uvscom_devs, v, p)
    234       1.1  augustss 
    235       1.1  augustss USB_DECLARE_DRIVER(uvscom);
    236       1.1  augustss 
    237       1.1  augustss #ifdef __FreeBSD__
    238       1.1  augustss Static device_probe_t uvscom_match;
    239       1.1  augustss Static device_attach_t uvscom_attach;
    240       1.1  augustss Static device_detach_t uvscom_detach;
    241       1.1  augustss 
    242       1.1  augustss Static device_method_t uvscom_methods[] = {
    243       1.1  augustss 	/* Device interface */
    244       1.1  augustss 	DEVMETHOD(device_probe, uvscom_match),
    245       1.1  augustss 	DEVMETHOD(device_attach, uvscom_attach),
    246       1.1  augustss 	DEVMETHOD(device_detach, uvscom_detach),
    247       1.1  augustss 	{ 0, 0 }
    248       1.1  augustss };
    249       1.1  augustss 
    250       1.1  augustss Static driver_t uvscom_driver = {
    251       1.1  augustss 	"usio",
    252       1.1  augustss 	uvscom_methods,
    253       1.1  augustss 	sizeof (struct uvscom_softc)
    254       1.1  augustss };
    255       1.1  augustss 
    256       1.1  augustss DRIVER_MODULE(uvscom, uhub, uvscom_driver, ucom_devclass, usbd_driver_load, 0);
    257       1.1  augustss MODULE_DEPEND(uvscom, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
    258       1.1  augustss MODULE_VERSION(uvscom, UVSCOM_MODVER);
    259       1.1  augustss #endif
    260       1.1  augustss 
    261       1.1  augustss USB_MATCH(uvscom)
    262       1.1  augustss {
    263       1.1  augustss 	USB_MATCH_START(uvscom, uaa);
    264       1.1  augustss 
    265       1.1  augustss 	if (uaa->iface != NULL)
    266       1.1  augustss 		return (UMATCH_NONE);
    267       1.1  augustss 
    268       1.1  augustss 	return (uvscom_lookup(uaa->vendor, uaa->product) != NULL ?
    269       1.1  augustss 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
    270       1.1  augustss }
    271       1.1  augustss 
    272       1.1  augustss USB_ATTACH(uvscom)
    273       1.1  augustss {
    274       1.1  augustss 	USB_ATTACH_START(uvscom, sc, uaa);
    275       1.1  augustss 	usbd_device_handle dev = uaa->device;
    276       1.1  augustss 	usb_config_descriptor_t *cdesc;
    277       1.1  augustss 	usb_interface_descriptor_t *id;
    278       1.1  augustss 	usb_endpoint_descriptor_t *ed;
    279       1.4      taca 	char devinfo[1024];
    280       1.4      taca 	const char *devname = USBDEVNAME(sc->sc_dev);
    281       1.1  augustss 	usbd_status err;
    282       1.1  augustss 	int i;
    283       1.1  augustss 	struct ucom_attach_args uca;
    284       1.1  augustss 
    285      1.12    itojun         usbd_devinfo(dev, 0, devinfo, sizeof(devinfo));
    286       1.1  augustss         USB_ATTACH_SETUP;
    287       1.1  augustss         printf("%s: %s\n", devname, devinfo);
    288       1.1  augustss 
    289       1.1  augustss         sc->sc_udev = dev;
    290       1.1  augustss 
    291       1.1  augustss 	DPRINTF(("uvscom attach: sc = %p\n", sc));
    292       1.1  augustss 
    293       1.6  augustss 	/* initialize endpoints */
    294       1.1  augustss 	uca.bulkin = uca.bulkout = -1;
    295       1.1  augustss 	sc->sc_intr_number = -1;
    296       1.1  augustss 	sc->sc_intr_pipe = NULL;
    297       1.1  augustss 
    298       1.1  augustss 	/* Move the device into the configured state. */
    299       1.1  augustss 	err = usbd_set_config_index(dev, UVSCOM_CONFIG_INDEX, 1);
    300       1.1  augustss 	if (err) {
    301       1.1  augustss 		printf("%s: failed to set configuration, err=%s\n",
    302       1.1  augustss 			devname, usbd_errstr(err));
    303       1.1  augustss 		sc->sc_dying = 1;
    304       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    305       1.1  augustss 	}
    306       1.1  augustss 
    307       1.1  augustss 	/* get the config descriptor */
    308       1.1  augustss 	cdesc = usbd_get_config_descriptor(sc->sc_udev);
    309       1.1  augustss 
    310       1.1  augustss 	if (cdesc == NULL) {
    311       1.1  augustss 		printf("%s: failed to get configuration descriptor\n",
    312       1.1  augustss 			USBDEVNAME(sc->sc_dev));
    313       1.1  augustss 		sc->sc_dying = 1;
    314       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    315       1.1  augustss 	}
    316       1.1  augustss 
    317       1.1  augustss 	/* get the common interface */
    318       1.6  augustss 	err = usbd_device2interface_handle(dev, UVSCOM_IFACE_INDEX,
    319       1.1  augustss 					   &sc->sc_iface);
    320       1.1  augustss 	if (err) {
    321       1.1  augustss 		printf("%s: failed to get interface, err=%s\n",
    322       1.1  augustss 			devname, usbd_errstr(err));
    323       1.1  augustss 		sc->sc_dying = 1;
    324       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    325       1.1  augustss 	}
    326       1.1  augustss 
    327       1.1  augustss 	id = usbd_get_interface_descriptor(sc->sc_iface);
    328       1.1  augustss 	sc->sc_iface_number = id->bInterfaceNumber;
    329       1.1  augustss 
    330       1.1  augustss 	/* Find endpoints */
    331       1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
    332       1.1  augustss 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
    333       1.1  augustss 		if (ed == NULL) {
    334       1.1  augustss 			printf("%s: no endpoint descriptor for %d\n",
    335       1.1  augustss 				USBDEVNAME(sc->sc_dev), i);
    336       1.1  augustss 			sc->sc_dying = 1;
    337       1.1  augustss 			USB_ATTACH_ERROR_RETURN;
    338       1.1  augustss 		}
    339       1.1  augustss 
    340       1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    341       1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    342       1.1  augustss 			uca.bulkin = ed->bEndpointAddress;
    343       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    344       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    345       1.1  augustss 			uca.bulkout = ed->bEndpointAddress;
    346       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    347       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    348       1.1  augustss 			sc->sc_intr_number = ed->bEndpointAddress;
    349       1.1  augustss 			sc->sc_isize = UGETW(ed->wMaxPacketSize);
    350       1.6  augustss 		}
    351       1.1  augustss 	}
    352       1.1  augustss 
    353       1.1  augustss 	if (uca.bulkin == -1) {
    354       1.1  augustss 		printf("%s: Could not find data bulk in\n",
    355       1.1  augustss 			USBDEVNAME(sc->sc_dev));
    356       1.1  augustss 		sc->sc_dying = 1;
    357       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    358       1.1  augustss 	}
    359       1.1  augustss 	if (uca.bulkout == -1) {
    360       1.1  augustss 		printf("%s: Could not find data bulk out\n",
    361       1.1  augustss 			USBDEVNAME(sc->sc_dev));
    362       1.1  augustss 		sc->sc_dying = 1;
    363       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    364       1.1  augustss 	}
    365       1.1  augustss 	if (sc->sc_intr_number == -1) {
    366       1.1  augustss 		printf("%s: Could not find interrupt in\n",
    367       1.1  augustss 			USBDEVNAME(sc->sc_dev));
    368       1.1  augustss 		sc->sc_dying = 1;
    369       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    370       1.1  augustss 	}
    371       1.1  augustss 
    372       1.1  augustss 	sc->sc_dtr = sc->sc_rts = 0;
    373       1.1  augustss 	sc->sc_lcr = UVSCOM_LINE_INIT;
    374       1.1  augustss 
    375       1.1  augustss 	uca.portno = UCOM_UNK_PORTNO;
    376       1.1  augustss 	/* bulkin, bulkout set above */
    377       1.1  augustss 	uca.ibufsize = UVSCOMIBUFSIZE;
    378       1.1  augustss 	uca.obufsize = UVSCOMOBUFSIZE;
    379       1.1  augustss 	uca.ibufsizepad = UVSCOMIBUFSIZE;
    380       1.1  augustss 	uca.opkthdrlen = 0;
    381       1.1  augustss 	uca.device = dev;
    382       1.1  augustss 	uca.iface = sc->sc_iface;
    383       1.1  augustss 	uca.methods = &uvscom_methods;
    384       1.1  augustss 	uca.arg = sc;
    385       1.1  augustss 	uca.info = NULL;
    386       1.1  augustss 
    387       1.1  augustss 	err = uvscom_reset(sc);
    388       1.1  augustss 
    389       1.1  augustss 	if (err) {
    390       1.1  augustss 		printf("%s: reset failed, %s\n", USBDEVNAME(sc->sc_dev),
    391       1.1  augustss 			usbd_errstr(err));
    392       1.1  augustss 		sc->sc_dying = 1;
    393       1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    394       1.1  augustss 	}
    395       1.1  augustss 
    396       1.1  augustss 	DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n",
    397       1.1  augustss 		 ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number));
    398       1.1  augustss 
    399       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    400       1.1  augustss 			   USBDEV(sc->sc_dev));
    401       1.1  augustss 
    402       1.1  augustss 	DPRINTF(("uplcom: in=0x%x out=0x%x intr=0x%x\n",
    403       1.1  augustss 			uca.bulkin, uca.bulkout, sc->sc_intr_number ));
    404      1.13  drochner 	sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
    405      1.13  drochner 					    ucomprint, ucomsubmatch);
    406       1.1  augustss 
    407       1.1  augustss 	USB_ATTACH_SUCCESS_RETURN;
    408       1.1  augustss }
    409       1.1  augustss 
    410       1.1  augustss USB_DETACH(uvscom)
    411       1.1  augustss {
    412       1.1  augustss 	USB_DETACH_START(uvscom, sc);
    413       1.1  augustss 	int rv = 0;
    414       1.1  augustss 
    415       1.1  augustss 	DPRINTF(("uvscom_detach: sc = %p\n", sc));
    416       1.1  augustss 
    417       1.1  augustss 	sc->sc_dying = 1;
    418       1.1  augustss 
    419       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    420       1.1  augustss 		usbd_abort_pipe(sc->sc_intr_pipe);
    421       1.1  augustss 		usbd_close_pipe(sc->sc_intr_pipe);
    422       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    423       1.1  augustss 		sc->sc_intr_pipe = NULL;
    424       1.1  augustss 	}
    425       1.1  augustss 
    426       1.1  augustss 	sc->sc_dying = 1;
    427       1.1  augustss 	if (sc->sc_subdev != NULL) {
    428       1.1  augustss 		rv = config_detach(sc->sc_subdev, flags);
    429       1.1  augustss 		sc->sc_subdev = NULL;
    430       1.1  augustss 	}
    431       1.1  augustss 
    432       1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    433       1.1  augustss 			   USBDEV(sc->sc_dev));
    434       1.1  augustss 
    435       1.1  augustss 	return (rv);
    436       1.1  augustss }
    437       1.1  augustss 
    438       1.3  augustss int
    439       1.1  augustss uvscom_activate(device_ptr_t self, enum devact act)
    440       1.1  augustss {
    441       1.1  augustss 	struct uvscom_softc *sc = (struct uvscom_softc *)self;
    442       1.1  augustss 	int rv = 0;
    443       1.1  augustss 
    444       1.1  augustss 	switch (act) {
    445       1.1  augustss 	case DVACT_ACTIVATE:
    446       1.1  augustss 		return (EOPNOTSUPP);
    447       1.1  augustss 
    448       1.1  augustss 	case DVACT_DEACTIVATE:
    449       1.1  augustss 		if (sc->sc_subdev != NULL)
    450       1.1  augustss 			rv = config_deactivate(sc->sc_subdev);
    451       1.1  augustss 		sc->sc_dying = 1;
    452       1.1  augustss 		break;
    453       1.1  augustss 	}
    454       1.1  augustss 	return (rv);
    455       1.1  augustss }
    456       1.1  augustss 
    457       1.1  augustss Static usbd_status
    458       1.1  augustss uvscom_readstat(struct uvscom_softc *sc)
    459       1.1  augustss {
    460       1.1  augustss 	usb_device_request_t req;
    461       1.1  augustss 	usbd_status err;
    462       1.1  augustss 	uint16_t r;
    463       1.1  augustss 
    464       1.1  augustss 	DPRINTF(("%s: send readstat\n", USBDEVNAME(sc->sc_dev)));
    465       1.1  augustss 
    466       1.1  augustss 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    467       1.1  augustss 	req.bRequest = UVSCOM_READ_STATUS;
    468       1.1  augustss 	USETW(req.wValue, 0);
    469       1.1  augustss 	USETW(req.wIndex, 0);
    470       1.6  augustss 	USETW(req.wLength, 2);
    471       1.1  augustss 
    472       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, &r);
    473       1.1  augustss 	if (err) {
    474       1.1  augustss 		printf("%s: uvscom_readstat: %s\n",
    475       1.1  augustss 		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    476       1.1  augustss 		return (err);
    477       1.1  augustss 	}
    478       1.1  augustss 
    479       1.1  augustss 	DPRINTF(("%s: uvscom_readstat: r = %d\n",
    480       1.1  augustss 		 USBDEVNAME(sc->sc_dev), r));
    481       1.1  augustss 
    482       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    483       1.1  augustss }
    484       1.1  augustss 
    485       1.1  augustss Static usbd_status
    486       1.1  augustss uvscom_shutdown(struct uvscom_softc *sc)
    487       1.1  augustss {
    488       1.1  augustss 	usb_device_request_t req;
    489       1.1  augustss 	usbd_status err;
    490       1.1  augustss 
    491       1.1  augustss 	DPRINTF(("%s: send shutdown\n", USBDEVNAME(sc->sc_dev)));
    492       1.1  augustss 
    493       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    494       1.1  augustss 	req.bRequest = UVSCOM_SHUTDOWN;
    495       1.1  augustss 	USETW(req.wValue, 0);
    496       1.1  augustss 	USETW(req.wIndex, 0);
    497       1.6  augustss 	USETW(req.wLength, 0);
    498       1.1  augustss 
    499       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    500       1.1  augustss 	if (err) {
    501       1.1  augustss 		printf("%s: uvscom_shutdown: %s\n",
    502       1.1  augustss 		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    503       1.1  augustss 		return (err);
    504       1.1  augustss 	}
    505       1.1  augustss 
    506       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    507       1.1  augustss }
    508       1.1  augustss 
    509       1.1  augustss Static usbd_status
    510       1.1  augustss uvscom_reset(struct uvscom_softc *sc)
    511       1.1  augustss {
    512       1.1  augustss 	DPRINTF(("%s: uvscom_reset\n", USBDEVNAME(sc->sc_dev)));
    513       1.1  augustss 
    514       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    515       1.1  augustss }
    516       1.1  augustss 
    517       1.1  augustss Static usbd_status
    518       1.1  augustss uvscom_set_crtscts(struct uvscom_softc *sc)
    519       1.1  augustss {
    520       1.1  augustss 	DPRINTF(("%s: uvscom_set_crtscts\n", USBDEVNAME(sc->sc_dev)));
    521       1.1  augustss 
    522       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    523       1.1  augustss }
    524       1.1  augustss 
    525       1.1  augustss Static usbd_status
    526       1.1  augustss uvscom_set_line(struct uvscom_softc *sc, uint16_t line)
    527       1.1  augustss {
    528       1.1  augustss 	usb_device_request_t req;
    529       1.1  augustss 	usbd_status err;
    530       1.1  augustss 
    531       1.1  augustss 	DPRINTF(("%s: uvscom_set_line: %04x\n",
    532       1.1  augustss 		 USBDEVNAME(sc->sc_dev), line));
    533       1.1  augustss 
    534       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    535       1.1  augustss 	req.bRequest = UVSCOM_LINE_CTL;
    536       1.1  augustss 	USETW(req.wValue, line);
    537       1.1  augustss 	USETW(req.wIndex, 0);
    538       1.6  augustss 	USETW(req.wLength, 0);
    539       1.1  augustss 
    540       1.6  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    541       1.1  augustss 	if (err) {
    542       1.1  augustss 		printf("%s: uvscom_set_line: %s\n",
    543       1.1  augustss 		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    544       1.1  augustss 		return (err);
    545       1.1  augustss 	}
    546       1.1  augustss 
    547       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    548       1.1  augustss }
    549       1.1  augustss 
    550       1.1  augustss Static usbd_status
    551       1.1  augustss uvscom_set_line_coding(struct uvscom_softc *sc, uint16_t lsp, uint16_t ls)
    552       1.1  augustss {
    553       1.1  augustss 	usb_device_request_t req;
    554       1.1  augustss 	usbd_status err;
    555       1.1  augustss 
    556       1.1  augustss 	DPRINTF(("%s: uvscom_set_line_coding: %02x %02x\n",
    557       1.1  augustss 		 USBDEVNAME(sc->sc_dev), lsp, ls));
    558       1.1  augustss 
    559       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    560       1.1  augustss 	req.bRequest = UVSCOM_SET_SPEED;
    561       1.1  augustss 	USETW(req.wValue, lsp);
    562       1.1  augustss 	USETW(req.wIndex, 0);
    563       1.1  augustss 	USETW(req.wLength, 0);
    564       1.1  augustss 
    565       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    566       1.1  augustss 	if (err) {
    567       1.1  augustss 		printf("%s: uvscom_set_line_coding: %s\n",
    568       1.1  augustss 		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    569       1.1  augustss 		return (err);
    570       1.1  augustss 	}
    571       1.1  augustss 
    572       1.1  augustss 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    573       1.1  augustss 	req.bRequest = UVSCOM_SET_PARAM;
    574       1.1  augustss 	USETW(req.wValue, ls);
    575       1.1  augustss 	USETW(req.wIndex, 0);
    576       1.1  augustss 	USETW(req.wLength, 0);
    577       1.1  augustss 
    578       1.1  augustss 	err = usbd_do_request(sc->sc_udev, &req, NULL);
    579       1.1  augustss 	if (err) {
    580       1.1  augustss 		printf("%s: uvscom_set_line_coding: %s\n",
    581       1.1  augustss 		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    582       1.1  augustss 		return (err);
    583       1.1  augustss 	}
    584       1.1  augustss 
    585       1.1  augustss 	return (USBD_NORMAL_COMPLETION);
    586       1.1  augustss }
    587       1.1  augustss 
    588       1.1  augustss Static void
    589       1.1  augustss uvscom_dtr(struct uvscom_softc *sc, int onoff)
    590       1.1  augustss {
    591       1.1  augustss 	DPRINTF(("%s: uvscom_dtr: onoff = %d\n",
    592       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    593       1.1  augustss 
    594       1.1  augustss 	if (sc->sc_dtr == onoff)
    595       1.1  augustss 		return;			/* no change */
    596       1.1  augustss 
    597       1.1  augustss 	sc->sc_dtr = onoff;
    598       1.1  augustss 
    599       1.1  augustss 	if (onoff)
    600       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_DTR);
    601       1.1  augustss 	else
    602       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_DTR);
    603       1.1  augustss 
    604       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    605       1.1  augustss }
    606       1.1  augustss 
    607       1.1  augustss Static void
    608       1.1  augustss uvscom_rts(struct uvscom_softc *sc, int onoff)
    609       1.1  augustss {
    610       1.1  augustss 	DPRINTF(("%s: uvscom_rts: onoff = %d\n",
    611       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    612       1.1  augustss 
    613       1.1  augustss 	if (sc->sc_rts == onoff)
    614       1.1  augustss 		return;			/* no change */
    615       1.1  augustss 
    616       1.1  augustss 	sc->sc_rts = onoff;
    617       1.1  augustss 
    618       1.1  augustss 	if (onoff)
    619       1.1  augustss 		SET(sc->sc_lcr, UVSCOM_RTS);
    620       1.1  augustss 	else
    621       1.1  augustss 		CLR(sc->sc_lcr, UVSCOM_RTS);
    622       1.1  augustss 
    623       1.1  augustss 	uvscom_set_line(sc, sc->sc_lcr);
    624       1.1  augustss }
    625       1.1  augustss 
    626       1.1  augustss Static void
    627       1.1  augustss uvscom_break(struct uvscom_softc *sc, int onoff)
    628       1.1  augustss {
    629       1.1  augustss 	DPRINTF(("%s: uvscom_break: onoff = %d\n",
    630       1.1  augustss 		 USBDEVNAME(sc->sc_dev), onoff));
    631       1.1  augustss 
    632       1.1  augustss 	if (onoff)
    633       1.1  augustss 		uvscom_set_line(sc, SET(sc->sc_lcr, UVSCOM_BREAK));
    634       1.1  augustss }
    635       1.1  augustss 
    636       1.1  augustss Static void
    637       1.1  augustss uvscom_set(void *addr, int portno, int reg, int onoff)
    638       1.1  augustss {
    639       1.1  augustss 	struct uvscom_softc *sc = addr;
    640       1.1  augustss 
    641       1.1  augustss 	switch (reg) {
    642       1.1  augustss 	case UCOM_SET_DTR:
    643       1.1  augustss 		uvscom_dtr(sc, onoff);
    644       1.1  augustss 		break;
    645       1.1  augustss 	case UCOM_SET_RTS:
    646       1.1  augustss 		uvscom_rts(sc, onoff);
    647       1.1  augustss 		break;
    648       1.1  augustss 	case UCOM_SET_BREAK:
    649       1.1  augustss 		uvscom_break(sc, onoff);
    650       1.1  augustss 		break;
    651       1.1  augustss 	default:
    652       1.1  augustss 		break;
    653       1.1  augustss 	}
    654       1.1  augustss }
    655       1.1  augustss 
    656       1.1  augustss Static int
    657       1.1  augustss uvscom_param(void *addr, int portno, struct termios *t)
    658       1.1  augustss {
    659       1.1  augustss 	struct uvscom_softc *sc = addr;
    660       1.1  augustss 	usbd_status err;
    661       1.1  augustss 	uint16_t lsp;
    662       1.1  augustss 	uint16_t ls;
    663       1.1  augustss 
    664       1.1  augustss 	DPRINTF(("%s: uvscom_param: sc = %p\n",
    665       1.1  augustss 		 USBDEVNAME(sc->sc_dev), sc));
    666       1.1  augustss 
    667       1.1  augustss 	ls = 0;
    668       1.1  augustss 
    669       1.1  augustss 	switch (t->c_ospeed) {
    670       1.1  augustss 	case B150:
    671       1.1  augustss 		lsp = UVSCOM_SPEED_150BPS;
    672       1.1  augustss 		break;
    673       1.1  augustss 	case B300:
    674       1.1  augustss 		lsp = UVSCOM_SPEED_300BPS;
    675       1.1  augustss 		break;
    676       1.1  augustss 	case B600:
    677       1.1  augustss 		lsp = UVSCOM_SPEED_600BPS;
    678       1.1  augustss 		break;
    679       1.1  augustss 	case B1200:
    680       1.1  augustss 		lsp = UVSCOM_SPEED_1200BPS;
    681       1.1  augustss 		break;
    682       1.1  augustss 	case B2400:
    683       1.1  augustss 		lsp = UVSCOM_SPEED_2400BPS;
    684       1.1  augustss 		break;
    685       1.1  augustss 	case B4800:
    686       1.1  augustss 		lsp = UVSCOM_SPEED_4800BPS;
    687       1.1  augustss 		break;
    688       1.1  augustss 	case B9600:
    689       1.1  augustss 		lsp = UVSCOM_SPEED_9600BPS;
    690       1.1  augustss 		break;
    691       1.1  augustss 	case B19200:
    692       1.1  augustss 		lsp = UVSCOM_SPEED_19200BPS;
    693       1.1  augustss 		break;
    694       1.1  augustss 	case B38400:
    695       1.1  augustss 		lsp = UVSCOM_SPEED_38400BPS;
    696       1.1  augustss 		break;
    697       1.1  augustss 	case B57600:
    698       1.1  augustss 		lsp = UVSCOM_SPEED_57600BPS;
    699       1.1  augustss 		break;
    700       1.1  augustss 	case B115200:
    701       1.1  augustss 		lsp = UVSCOM_SPEED_115200BPS;
    702       1.1  augustss 		break;
    703       1.1  augustss 	default:
    704       1.1  augustss 		return (EIO);
    705       1.1  augustss 	}
    706       1.6  augustss 
    707       1.1  augustss 	if (ISSET(t->c_cflag, CSTOPB))
    708       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_2);
    709       1.1  augustss 	else
    710       1.1  augustss 		SET(ls, UVSCOM_STOP_BIT_1);
    711       1.1  augustss 
    712       1.1  augustss 	if (ISSET(t->c_cflag, PARENB)) {
    713       1.1  augustss 		if (ISSET(t->c_cflag, PARODD))
    714       1.1  augustss 			SET(ls, UVSCOM_PARITY_ODD);
    715       1.1  augustss 		else
    716       1.1  augustss 			SET(ls, UVSCOM_PARITY_EVEN);
    717       1.1  augustss 	} else
    718       1.1  augustss 		SET(ls, UVSCOM_PARITY_NONE);
    719       1.1  augustss 
    720       1.1  augustss 	switch (ISSET(t->c_cflag, CSIZE)) {
    721       1.1  augustss 	case CS5:
    722       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_5);
    723       1.1  augustss 		break;
    724       1.1  augustss 	case CS6:
    725       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_6);
    726       1.1  augustss 		break;
    727       1.1  augustss 	case CS7:
    728       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_7);
    729       1.1  augustss 		break;
    730       1.1  augustss 	case CS8:
    731       1.1  augustss 		SET(ls, UVSCOM_DATA_BIT_8);
    732       1.1  augustss 		break;
    733       1.1  augustss 	default:
    734       1.1  augustss 		return (EIO);
    735       1.1  augustss 	}
    736       1.1  augustss 
    737       1.1  augustss 	err = uvscom_set_line_coding(sc, lsp, ls);
    738       1.1  augustss 	if (err)
    739       1.1  augustss 		return (EIO);
    740       1.1  augustss 
    741       1.1  augustss 	if (ISSET(t->c_cflag, CRTSCTS)) {
    742       1.1  augustss 		err = uvscom_set_crtscts(sc);
    743       1.1  augustss 		if (err)
    744       1.1  augustss 			return (EIO);
    745       1.1  augustss 	}
    746       1.1  augustss 
    747       1.1  augustss 	return (0);
    748       1.1  augustss }
    749       1.1  augustss 
    750       1.1  augustss Static int
    751       1.1  augustss uvscom_open(void *addr, int portno)
    752       1.1  augustss {
    753       1.1  augustss 	struct uvscom_softc *sc = addr;
    754       1.1  augustss 	int err;
    755       1.1  augustss 	int i;
    756       1.6  augustss 
    757       1.1  augustss 	if (sc->sc_dying)
    758       1.1  augustss 		return (EIO);
    759       1.1  augustss 
    760       1.1  augustss 	DPRINTF(("uvscom_open: sc = %p\n", sc));
    761       1.1  augustss 
    762       1.1  augustss 	if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
    763       1.1  augustss 		DPRINTF(("uvscom_open: open interrupt pipe.\n"));
    764       1.1  augustss 
    765       1.1  augustss 		sc->sc_usr = 0;		/* clear unit status */
    766       1.1  augustss 
    767       1.1  augustss 		err = uvscom_readstat(sc);
    768       1.1  augustss 		if (err) {
    769       1.1  augustss 			DPRINTF(("%s: uvscom_open: readstat faild\n",
    770       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    771       1.1  augustss 			return (EIO);
    772       1.1  augustss 		}
    773       1.1  augustss 
    774       1.1  augustss 		sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
    775       1.1  augustss 		err = usbd_open_pipe_intr(sc->sc_iface,
    776       1.1  augustss 					  sc->sc_intr_number,
    777       1.1  augustss 					  USBD_SHORT_XFER_OK,
    778       1.1  augustss 					  &sc->sc_intr_pipe,
    779       1.1  augustss 					  sc,
    780       1.1  augustss 					  sc->sc_intr_buf,
    781       1.1  augustss 					  sc->sc_isize,
    782       1.1  augustss 					  uvscom_intr,
    783       1.1  augustss 					  UVSCOM_INTR_INTERVAL);
    784       1.1  augustss 		if (err) {
    785       1.1  augustss 			printf("%s: cannot open interrupt pipe (addr %d)\n",
    786       1.1  augustss 				 USBDEVNAME(sc->sc_dev),
    787       1.1  augustss 				 sc->sc_intr_number);
    788       1.1  augustss 			return (EIO);
    789       1.1  augustss 		}
    790       1.1  augustss 	} else {
    791       1.1  augustss 		DPRINTF(("uvscom_open: did not open interrupt pipe.\n"));
    792       1.1  augustss 	}
    793       1.1  augustss 
    794       1.1  augustss 	if ((sc->sc_usr & UVSCOM_USTAT_MASK) == 0) {
    795       1.1  augustss 		/* unit is not ready */
    796       1.1  augustss 
    797       1.1  augustss 		for (i = UVSCOM_UNIT_WAIT; i > 0; --i) {
    798       1.1  augustss 			tsleep(&err, TTIPRI, "uvsop", hz);	/* XXX */
    799       1.1  augustss 			if (ISSET(sc->sc_usr, UVSCOM_USTAT_MASK))
    800       1.1  augustss 				break;
    801       1.1  augustss 		}
    802       1.1  augustss 		if (i == 0) {
    803       1.1  augustss 			DPRINTF(("%s: unit is not ready\n",
    804       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    805       1.1  augustss 			return (EIO);
    806       1.1  augustss 		}
    807       1.1  augustss 
    808       1.1  augustss 		/* check PC card was inserted */
    809       1.1  augustss 		if (ISSET(sc->sc_usr, UVSCOM_NOCARD)) {
    810       1.1  augustss 			DPRINTF(("%s: no card\n",
    811       1.1  augustss 				 USBDEVNAME(sc->sc_dev)));
    812       1.1  augustss 			return (EIO);
    813       1.1  augustss 		}
    814       1.1  augustss 	}
    815       1.1  augustss 
    816       1.1  augustss 	return (0);
    817       1.1  augustss }
    818       1.1  augustss 
    819       1.1  augustss Static void
    820       1.6  augustss uvscom_close(void *addr, int portno)
    821       1.1  augustss {
    822       1.1  augustss 	struct uvscom_softc *sc = addr;
    823       1.1  augustss 	int err;
    824       1.1  augustss 
    825       1.1  augustss 	if (sc->sc_dying)
    826       1.1  augustss 		return;
    827       1.1  augustss 
    828       1.1  augustss 	DPRINTF(("uvscom_close: close\n"));
    829       1.1  augustss 
    830       1.1  augustss 	uvscom_shutdown(sc);
    831       1.1  augustss 
    832       1.1  augustss 	if (sc->sc_intr_pipe != NULL) {
    833       1.1  augustss 		err = usbd_abort_pipe(sc->sc_intr_pipe);
    834       1.1  augustss 		if (err)
    835       1.1  augustss 			printf("%s: abort interrupt pipe failed: %s\n",
    836       1.1  augustss 				USBDEVNAME(sc->sc_dev),
    837       1.1  augustss 					   usbd_errstr(err));
    838       1.1  augustss 		err = usbd_close_pipe(sc->sc_intr_pipe);
    839       1.1  augustss 		if (err)
    840       1.1  augustss 			printf("%s: close interrupt pipe failed: %s\n",
    841       1.1  augustss 				USBDEVNAME(sc->sc_dev),
    842       1.1  augustss 					   usbd_errstr(err));
    843       1.1  augustss 		free(sc->sc_intr_buf, M_USBDEV);
    844       1.1  augustss 		sc->sc_intr_pipe = NULL;
    845       1.1  augustss 	}
    846       1.1  augustss }
    847       1.1  augustss 
    848       1.1  augustss Static void
    849       1.1  augustss uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    850       1.1  augustss {
    851       1.1  augustss 	struct uvscom_softc *sc = priv;
    852       1.1  augustss 	u_char *buf = sc->sc_intr_buf;
    853       1.1  augustss 	u_char pstatus;
    854       1.1  augustss 
    855       1.1  augustss 	if (sc->sc_dying)
    856       1.1  augustss 		return;
    857       1.1  augustss 
    858       1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    859       1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    860       1.1  augustss 			return;
    861       1.1  augustss 
    862       1.1  augustss 		printf("%s: uvscom_intr: abnormal status: %s\n",
    863       1.1  augustss 			USBDEVNAME(sc->sc_dev),
    864       1.1  augustss 			usbd_errstr(status));
    865       1.1  augustss 		usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
    866       1.1  augustss 		return;
    867       1.1  augustss 	}
    868       1.1  augustss 
    869       1.1  augustss 	DPRINTFN(2, ("%s: uvscom status = %02x %02x\n",
    870       1.1  augustss 		 USBDEVNAME(sc->sc_dev), buf[0], buf[1]));
    871       1.1  augustss 
    872       1.1  augustss 	sc->sc_lsr = sc->sc_msr = 0;
    873       1.1  augustss 	sc->sc_usr = buf[1];
    874       1.1  augustss 
    875       1.1  augustss 	pstatus = buf[0];
    876       1.1  augustss 	if (ISSET(pstatus, UVSCOM_TXRDY))
    877       1.1  augustss 		SET(sc->sc_lsr, ULSR_TXRDY);
    878       1.1  augustss 	if (ISSET(pstatus, UVSCOM_RXRDY))
    879       1.1  augustss 		SET(sc->sc_lsr, ULSR_RXRDY);
    880       1.1  augustss 
    881       1.1  augustss 	pstatus = buf[1];
    882       1.1  augustss 	if (ISSET(pstatus, UVSCOM_CTS))
    883       1.1  augustss 		SET(sc->sc_msr, UMSR_CTS);
    884       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DSR))
    885       1.1  augustss 		SET(sc->sc_msr, UMSR_DSR);
    886       1.1  augustss 	if (ISSET(pstatus, UVSCOM_DCD))
    887       1.1  augustss 		SET(sc->sc_msr, UMSR_DCD);
    888       1.1  augustss 
    889       1.1  augustss 	ucom_status_change((struct ucom_softc *) sc->sc_subdev);
    890       1.1  augustss }
    891       1.1  augustss 
    892       1.1  augustss Static void
    893       1.1  augustss uvscom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
    894       1.1  augustss {
    895       1.1  augustss 	struct uvscom_softc *sc = addr;
    896       1.1  augustss 
    897       1.1  augustss 	if (lsr != NULL)
    898       1.1  augustss 		*lsr = sc->sc_lsr;
    899       1.1  augustss 	if (msr != NULL)
    900       1.1  augustss 		*msr = sc->sc_msr;
    901       1.1  augustss }
    902       1.1  augustss 
    903