Home | History | Annotate | Line # | Download | only in usb
utoppy.c revision 1.25
      1  1.25     skrll /*	$NetBSD: utoppy.c,v 1.25 2016/04/23 10:15:32 skrll Exp $	*/
      2   1.1       scw 
      3   1.1       scw /*-
      4   1.1       scw  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5   1.1       scw  * All rights reserved.
      6   1.1       scw  *
      7   1.1       scw  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1       scw  * by Steve C. Woodford.
      9   1.1       scw  *
     10   1.1       scw  * Redistribution and use in source and binary forms, with or without
     11   1.1       scw  * modification, are permitted provided that the following conditions
     12   1.1       scw  * are met:
     13   1.1       scw  * 1. Redistributions of source code must retain the above copyright
     14   1.1       scw  *    notice, this list of conditions and the following disclaimer.
     15   1.1       scw  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       scw  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       scw  *    documentation and/or other materials provided with the distribution.
     18   1.1       scw  *
     19   1.1       scw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1       scw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1       scw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1       scw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1       scw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1       scw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1       scw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1       scw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1       scw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1       scw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1       scw  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1       scw  */
     31   1.1       scw 
     32   1.1       scw #include <sys/cdefs.h>
     33  1.25     skrll __KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.25 2016/04/23 10:15:32 skrll Exp $");
     34   1.1       scw 
     35   1.1       scw #include <sys/param.h>
     36   1.1       scw #include <sys/systm.h>
     37   1.1       scw #include <sys/proc.h>
     38   1.1       scw #include <sys/kernel.h>
     39   1.1       scw #include <sys/fcntl.h>
     40   1.1       scw #include <sys/device.h>
     41   1.1       scw #include <sys/ioctl.h>
     42   1.1       scw #include <sys/uio.h>
     43   1.1       scw #include <sys/conf.h>
     44   1.1       scw #include <sys/vnode.h>
     45  1.19       mrg #include <sys/bus.h>
     46   1.1       scw 
     47   1.1       scw #include <dev/usb/usb.h>
     48   1.1       scw #include <dev/usb/usbdi.h>
     49  1.19       mrg #include <dev/usb/usbdivar.h>
     50   1.1       scw #include <dev/usb/usbdi_util.h>
     51   1.1       scw #include <dev/usb/usbdevs.h>
     52   1.1       scw #include <dev/usb/usb_quirks.h>
     53   1.1       scw #include <dev/usb/utoppy.h>
     54   1.1       scw 
     55   1.1       scw #undef UTOPPY_DEBUG
     56   1.1       scw #ifdef UTOPPY_DEBUG
     57   1.1       scw #define	UTOPPY_DBG_OPEN		0x0001
     58   1.1       scw #define	UTOPPY_DBG_CLOSE	0x0002
     59   1.1       scw #define	UTOPPY_DBG_READ		0x0004
     60   1.1       scw #define	UTOPPY_DBG_WRITE	0x0008
     61   1.1       scw #define	UTOPPY_DBG_IOCTL	0x0010
     62   1.1       scw #define	UTOPPY_DBG_SEND_PACKET	0x0020
     63   1.1       scw #define	UTOPPY_DBG_RECV_PACKET	0x0040
     64   1.1       scw #define	UTOPPY_DBG_ADDPATH	0x0080
     65   1.1       scw #define	UTOPPY_DBG_READDIR	0x0100
     66   1.1       scw #define	UTOPPY_DBG_DUMP		0x0200
     67   1.1       scw #define	DPRINTF(l, m)				\
     68   1.1       scw 		do {				\
     69   1.1       scw 			if (utoppy_debug & l)	\
     70   1.1       scw 				printf m;	\
     71   1.1       scw 		} while (/*CONSTCOND*/0)
     72   1.1       scw static int utoppy_debug = 0;
     73   1.1       scw static void utoppy_dump_packet(const void *, size_t);
     74   1.1       scw #define	DDUMP_PACKET(p, l)					\
     75   1.1       scw 		do {						\
     76   1.1       scw 			if (utoppy_debug & UTOPPY_DBG_DUMP)	\
     77   1.1       scw 				utoppy_dump_packet((p), (l));	\
     78   1.1       scw 		} while (/*CONSTCOND*/0)
     79   1.1       scw #else
     80   1.1       scw #define	DPRINTF(l, m)		/* nothing */
     81   1.1       scw #define	DDUMP_PACKET(p, l)	/* nothing */
     82   1.1       scw #endif
     83   1.1       scw 
     84   1.1       scw 
     85   1.1       scw #define	UTOPPY_CONFIG_NO	1
     86   1.1       scw #define	UTOPPY_NUMENDPOINTS	2
     87   1.1       scw 
     88   1.1       scw #define	UTOPPY_BSIZE		0xffff
     89   1.1       scw #define	UTOPPY_FRAG_SIZE	0x1000
     90   1.1       scw #define	UTOPPY_HEADER_SIZE	8
     91   1.1       scw #define	UTOPPY_SHORT_TIMEOUT	(500)		/* 0.5 seconds */
     92   1.1       scw #define	UTOPPY_LONG_TIMEOUT	(10 * 1000)	/* 10 seconds */
     93   1.1       scw 
     94   1.1       scw /* Protocol Commands and Responses */
     95   1.1       scw #define	UTOPPY_RESP_ERROR		0x0001
     96   1.1       scw #define	UTOPPY_CMD_ACK			0x0002
     97   1.1       scw #define	 UTOPPY_RESP_SUCCESS		UTOPPY_CMD_ACK
     98   1.1       scw #define	UTOPPY_CMD_CANCEL		0x0003
     99   1.1       scw #define	UTOPPY_CMD_READY		0x0100
    100   1.1       scw #define	UTOPPY_CMD_RESET		0x0101
    101   1.1       scw #define	UTOPPY_CMD_TURBO		0x0102
    102   1.1       scw #define	UTOPPY_CMD_STATS		0x1000
    103   1.1       scw #define  UTOPPY_RESP_STATS_DATA		0x1001
    104   1.1       scw #define	UTOPPY_CMD_READDIR		0x1002
    105   1.1       scw #define	 UTOPPY_RESP_READDIR_DATA	0x1003
    106   1.1       scw #define	 UTOPPY_RESP_READDIR_END	0x1004
    107   1.1       scw #define	UTOPPY_CMD_DELETE		0x1005
    108   1.1       scw #define	UTOPPY_CMD_RENAME		0x1006
    109   1.1       scw #define	UTOPPY_CMD_MKDIR		0x1007
    110   1.1       scw #define	UTOPPY_CMD_FILE			0x1008
    111   1.1       scw #define  UTOPPY_FILE_WRITE		0
    112   1.1       scw #define  UTOPPY_FILE_READ		1
    113   1.1       scw #define	 UTOPPY_RESP_FILE_HEADER	0x1009
    114   1.1       scw #define	 UTOPPY_RESP_FILE_DATA		0x100a
    115   1.1       scw #define	 UTOPPY_RESP_FILE_END		0x100b
    116   1.1       scw 
    117   1.1       scw enum utoppy_state {
    118   1.1       scw 	UTOPPY_STATE_CLOSED,
    119   1.1       scw 	UTOPPY_STATE_OPENING,
    120   1.1       scw 	UTOPPY_STATE_IDLE,
    121   1.1       scw 	UTOPPY_STATE_READDIR,
    122   1.1       scw 	UTOPPY_STATE_READFILE,
    123   1.1       scw 	UTOPPY_STATE_WRITEFILE
    124   1.1       scw };
    125   1.1       scw 
    126   1.1       scw struct utoppy_softc {
    127  1.15    dyoung 	device_t sc_dev;
    128  1.25     skrll 	struct usbd_device *sc_udev;	/* device */
    129  1.25     skrll 	struct usbd_interface *sc_iface;	/* interface */
    130   1.1       scw 	int sc_dying;
    131   1.1       scw 	int sc_refcnt;
    132   1.1       scw 
    133   1.1       scw 	enum utoppy_state sc_state;
    134   1.1       scw 	u_int sc_turbo_mode;
    135   1.1       scw 
    136   1.1       scw 	int sc_out;
    137  1.25     skrll 	struct usbd_pipe *sc_out_pipe;	/* bulk out pipe */
    138  1.25     skrll 	struct usbd_xfer *sc_out_xfer;
    139   1.1       scw 	void *sc_out_buf;
    140   1.1       scw 	void *sc_out_data;
    141   1.1       scw 	uint64_t sc_wr_offset;
    142   1.1       scw 	uint64_t sc_wr_size;
    143   1.1       scw 
    144   1.1       scw 	int sc_in;
    145  1.25     skrll 	struct usbd_pipe *sc_in_pipe;	/* bulk in pipe */
    146  1.25     skrll 	struct usbd_xfer *sc_in_xfer;
    147   1.1       scw 	void *sc_in_buf;
    148   1.1       scw 	void *sc_in_data;
    149   1.1       scw 	size_t sc_in_len;
    150   1.1       scw 	u_int sc_in_offset;
    151   1.1       scw };
    152   1.1       scw 
    153   1.1       scw struct utoppy_header {
    154   1.1       scw 	uint16_t h_len;
    155   1.1       scw 	uint16_t h_crc;
    156   1.1       scw 	uint16_t h_cmd2;
    157   1.1       scw 	uint16_t h_cmd;
    158   1.1       scw 	uint8_t h_data[0];
    159   1.1       scw };
    160   1.1       scw #define	UTOPPY_OUT_INIT(sc)					\
    161   1.1       scw 	do {							\
    162   1.1       scw 		struct utoppy_header *_h = sc->sc_out_data;	\
    163   1.1       scw 		_h->h_len = 0;					\
    164   1.1       scw 	} while (/*CONSTCOND*/0)
    165   1.1       scw 
    166   1.1       scw #define	UTOPPY_MJD_1970 40587u	/* MJD value for Jan 1 00:00:00 1970 */
    167   1.1       scw 
    168   1.1       scw #define	UTOPPY_FTYPE_DIR	1
    169   1.1       scw #define	UTOPPY_FTYPE_FILE	2
    170   1.1       scw 
    171   1.1       scw #define	UTOPPY_IN_DATA(sc)	\
    172   1.1       scw  ((void*)&(((uint8_t*)(sc)->sc_in_data)[(sc)->sc_in_offset+UTOPPY_HEADER_SIZE]))
    173   1.1       scw 
    174   1.1       scw dev_type_open(utoppyopen);
    175   1.1       scw dev_type_close(utoppyclose);
    176   1.1       scw dev_type_read(utoppyread);
    177   1.1       scw dev_type_write(utoppywrite);
    178   1.1       scw dev_type_ioctl(utoppyioctl);
    179   1.1       scw 
    180   1.1       scw const struct cdevsw utoppy_cdevsw = {
    181  1.23  dholland 	.d_open = utoppyopen,
    182  1.23  dholland 	.d_close = utoppyclose,
    183  1.23  dholland 	.d_read = utoppyread,
    184  1.23  dholland 	.d_write = utoppywrite,
    185  1.23  dholland 	.d_ioctl = utoppyioctl,
    186  1.23  dholland 	.d_stop = nostop,
    187  1.23  dholland 	.d_tty = notty,
    188  1.23  dholland 	.d_poll = nopoll,
    189  1.23  dholland 	.d_mmap = nommap,
    190  1.23  dholland 	.d_kqfilter = nokqfilter,
    191  1.24  dholland 	.d_discard = nodiscard,
    192  1.23  dholland 	.d_flag = D_OTHER
    193   1.1       scw };
    194   1.1       scw 
    195   1.1       scw #define	UTOPPYUNIT(n)	(minor(n))
    196   1.1       scw 
    197  1.15    dyoung int             utoppy_match(device_t, cfdata_t, void *);
    198  1.15    dyoung void            utoppy_attach(device_t, device_t, void *);
    199  1.15    dyoung int             utoppy_detach(device_t, int);
    200  1.15    dyoung int             utoppy_activate(device_t, enum devact);
    201  1.15    dyoung extern struct cfdriver utoppy_cd;
    202  1.15    dyoung CFATTACH_DECL_NEW(utoppy, sizeof(struct utoppy_softc), utoppy_match, utoppy_attach, utoppy_detach, utoppy_activate);
    203   1.1       scw 
    204  1.25     skrll int
    205  1.15    dyoung utoppy_match(device_t parent, cfdata_t match, void *aux)
    206   1.1       scw {
    207  1.15    dyoung 	struct usb_attach_arg *uaa = aux;
    208   1.1       scw 
    209  1.25     skrll 	if (uaa->uaa_vendor == USB_VENDOR_TOPFIELD &&
    210  1.25     skrll 	    uaa->uaa_product == USB_PRODUCT_TOPFIELD_TF5000PVR)
    211  1.25     skrll 		return UMATCH_VENDOR_PRODUCT;
    212   1.1       scw 
    213  1.25     skrll 	return UMATCH_NONE;
    214   1.1       scw }
    215   1.1       scw 
    216  1.25     skrll void
    217  1.15    dyoung utoppy_attach(device_t parent, device_t self, void *aux)
    218   1.1       scw {
    219  1.15    dyoung 	struct utoppy_softc *sc = device_private(self);
    220  1.15    dyoung 	struct usb_attach_arg *uaa = aux;
    221  1.25     skrll 	struct usbd_device *dev = uaa->uaa_device;
    222  1.25     skrll 	struct usbd_interface *iface;
    223   1.1       scw 	usb_endpoint_descriptor_t *ed;
    224   1.1       scw 	char *devinfop;
    225  1.25     skrll 	uint8_t epcount;
    226   1.1       scw 	int i;
    227   1.1       scw 
    228  1.12      cube 	sc->sc_dev = self;
    229  1.12      cube 
    230  1.13    plunky 	aprint_naive("\n");
    231  1.13    plunky 	aprint_normal("\n");
    232  1.13    plunky 
    233   1.1       scw 	devinfop = usbd_devinfo_alloc(dev, 0);
    234  1.12      cube 	aprint_normal_dev(self, "%s\n", devinfop);
    235   1.1       scw 	usbd_devinfo_free(devinfop);
    236   1.1       scw 
    237   1.1       scw 	sc->sc_dying = 0;
    238   1.1       scw 	sc->sc_refcnt = 0;
    239   1.1       scw 	sc->sc_udev = dev;
    240   1.1       scw 
    241  1.10  drochner 	if (usbd_set_config_index(dev, 0, 1)
    242  1.10  drochner 	    || usbd_device2interface_handle(dev, 0, &iface)) {
    243  1.12      cube 		aprint_error_dev(self, "Configuration failed\n");
    244  1.15    dyoung 		return;
    245  1.10  drochner 	}
    246  1.10  drochner 
    247   1.1       scw 	epcount = 0;
    248  1.10  drochner 	(void) usbd_endpoint_count(iface, &epcount);
    249   1.1       scw 	if (epcount != UTOPPY_NUMENDPOINTS) {
    250  1.12      cube 		aprint_error_dev(self, "Expected %d endpoints, got %d\n",
    251  1.12      cube 		    UTOPPY_NUMENDPOINTS, epcount);
    252  1.15    dyoung 		return;
    253   1.1       scw 	}
    254   1.1       scw 
    255   1.1       scw 	sc->sc_in = -1;
    256   1.1       scw 	sc->sc_out = -1;
    257   1.1       scw 
    258   1.1       scw 	for (i = 0; i < epcount; i++) {
    259  1.10  drochner 		ed = usbd_interface2endpoint_descriptor(iface, i);
    260   1.1       scw 		if (ed == NULL) {
    261  1.12      cube 			aprint_error_dev(self, "couldn't get ep %d\n", i);
    262  1.15    dyoung 			return;
    263   1.1       scw 		}
    264   1.1       scw 
    265   1.1       scw 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    266   1.1       scw 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    267   1.1       scw 			sc->sc_in = ed->bEndpointAddress;
    268   1.1       scw 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    269   1.1       scw 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    270   1.1       scw 			sc->sc_out = ed->bEndpointAddress;
    271   1.1       scw 		}
    272   1.1       scw 	}
    273   1.1       scw 
    274   1.1       scw 	if (sc->sc_out == -1 || sc->sc_in == -1) {
    275  1.12      cube 		aprint_error_dev(self,
    276  1.12      cube 		    "could not find bulk in/out endpoints\n");
    277   1.1       scw 		sc->sc_dying = 1;
    278  1.15    dyoung 		return;
    279   1.1       scw 	}
    280   1.1       scw 
    281  1.10  drochner 	sc->sc_iface = iface;
    282   1.1       scw 	sc->sc_udev = dev;
    283   1.1       scw 
    284  1.25     skrll 	sc->sc_out_pipe = NULL;
    285  1.25     skrll 	sc->sc_in_pipe = NULL;
    286  1.25     skrll 
    287  1.25     skrll 	if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) {
    288  1.25     skrll 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(OUT) failed\n",
    289  1.25     skrll 		    device_xname(sc->sc_dev)));
    290  1.25     skrll 		aprint_error_dev(self, "could not open OUT pipe\n");
    291  1.25     skrll 		sc->sc_dying = 1;
    292  1.25     skrll 		return;
    293  1.25     skrll 	}
    294  1.25     skrll 
    295  1.25     skrll 	if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) {
    296  1.25     skrll 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(IN) failed\n",
    297  1.25     skrll 		    device_xname(sc->sc_dev)));
    298  1.25     skrll 		aprint_error_dev(self, "could not open IN pipe\n");
    299  1.25     skrll 
    300  1.25     skrll 		usbd_close_pipe(sc->sc_out_pipe);
    301  1.25     skrll 		sc->sc_out_pipe = NULL;
    302  1.25     skrll 		sc->sc_dying = 1;
    303  1.25     skrll 		return;
    304  1.25     skrll 	}
    305  1.25     skrll 
    306  1.25     skrll 	int error;
    307  1.25     skrll 	error = usbd_create_xfer(sc->sc_out_pipe, UTOPPY_FRAG_SIZE, 0, 0,
    308  1.25     skrll 	    &sc->sc_out_xfer);
    309  1.25     skrll 	if (error) {
    310  1.12      cube 		aprint_error_dev(self, "could not allocate bulk out xfer\n");
    311   1.1       scw 		goto fail0;
    312   1.1       scw 	}
    313   1.1       scw 
    314  1.25     skrll 	error = usbd_create_xfer(sc->sc_in_pipe, UTOPPY_FRAG_SIZE,
    315  1.25     skrll 	    USBD_SHORT_XFER_OK, 0, &sc->sc_in_xfer);
    316  1.25     skrll 	if (error) {
    317  1.12      cube 		aprint_error_dev(self, "could not allocate bulk in xfer\n");
    318   1.1       scw 		goto fail1;
    319   1.1       scw 	}
    320   1.1       scw 
    321  1.25     skrll 	sc->sc_out_buf = usbd_get_buffer(sc->sc_out_xfer);
    322  1.25     skrll 	sc->sc_in_buf = usbd_get_buffer(sc->sc_in_xfer);
    323   1.1       scw 
    324   1.1       scw 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    325  1.15    dyoung 			   sc->sc_dev);
    326   1.1       scw 
    327  1.15    dyoung 	return;
    328   1.1       scw 
    329  1.25     skrll  fail1:	usbd_destroy_xfer(sc->sc_out_xfer);
    330   1.1       scw 	sc->sc_out_xfer = NULL;
    331   1.1       scw 
    332   1.1       scw  fail0:	sc->sc_dying = 1;
    333  1.15    dyoung 	return;
    334   1.1       scw }
    335   1.1       scw 
    336   1.1       scw int
    337  1.15    dyoung utoppy_activate(device_t self, enum devact act)
    338   1.1       scw {
    339  1.12      cube 	struct utoppy_softc *sc = device_private(self);
    340   1.1       scw 
    341   1.1       scw 	switch (act) {
    342   1.1       scw 	case DVACT_DEACTIVATE:
    343   1.1       scw 		sc->sc_dying = 1;
    344  1.14    dyoung 		return 0;
    345  1.14    dyoung 	default:
    346  1.14    dyoung 		return EOPNOTSUPP;
    347   1.1       scw 	}
    348   1.1       scw }
    349   1.1       scw 
    350  1.25     skrll int
    351  1.15    dyoung utoppy_detach(device_t self, int flags)
    352   1.1       scw {
    353  1.15    dyoung 	struct utoppy_softc *sc = device_private(self);
    354   1.1       scw 	int maj, mn;
    355   1.1       scw 	int s;
    356   1.1       scw 
    357   1.1       scw 	sc->sc_dying = 1;
    358   1.1       scw 	if (sc->sc_out_pipe != NULL)
    359   1.1       scw 		usbd_abort_pipe(sc->sc_out_pipe);
    360   1.1       scw 	if (sc->sc_in_pipe != NULL)
    361   1.1       scw 		usbd_abort_pipe(sc->sc_in_pipe);
    362   1.1       scw 
    363   1.1       scw 	if (sc->sc_in_xfer != NULL)
    364  1.25     skrll 		usbd_destroy_xfer(sc->sc_in_xfer);
    365   1.1       scw 	if (sc->sc_out_xfer != NULL)
    366  1.25     skrll 		usbd_destroy_xfer(sc->sc_out_xfer);
    367  1.25     skrll 
    368  1.25     skrll 	if (sc->sc_out_pipe != NULL)
    369  1.25     skrll 		usbd_close_pipe(sc->sc_out_pipe);
    370  1.25     skrll 	if (sc->sc_in_pipe != NULL)
    371  1.25     skrll 		usbd_close_pipe(sc->sc_in_pipe);
    372   1.1       scw 
    373   1.1       scw 	s = splusb();
    374   1.1       scw 	if (--sc->sc_refcnt >= 0)
    375  1.18       mrg 		usb_detach_waitold(sc->sc_dev);
    376   1.1       scw 	splx(s);
    377   1.1       scw 
    378   1.1       scw 	/* locate the major number */
    379   1.1       scw 	maj = cdevsw_lookup_major(&utoppy_cdevsw);
    380   1.1       scw 
    381   1.1       scw 	/* Nuke the vnodes for any open instances (calls close). */
    382  1.21       chs 	mn = device_unit(self);
    383   1.1       scw 	vdevgone(maj, mn, mn, VCHR);
    384   1.1       scw 
    385   1.1       scw 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    386  1.15    dyoung 			   sc->sc_dev);
    387   1.1       scw 
    388  1.25     skrll 	return 0;
    389   1.1       scw }
    390   1.1       scw 
    391   1.1       scw static const uint16_t utoppy_crc16_lookup[] = {
    392   1.1       scw 	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    393   1.1       scw 	0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    394   1.1       scw 	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    395   1.1       scw 	0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    396   1.1       scw 	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    397   1.1       scw 	0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    398   1.1       scw 	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    399   1.1       scw 	0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    400   1.1       scw 	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    401   1.1       scw 	0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    402   1.1       scw 	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    403   1.1       scw 	0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    404   1.1       scw 	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    405   1.1       scw 	0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    406   1.1       scw 	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    407   1.1       scw 	0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    408   1.1       scw 	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    409   1.1       scw 	0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    410   1.1       scw 	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    411   1.1       scw 	0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    412   1.1       scw 	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    413   1.1       scw 	0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    414   1.1       scw 	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    415   1.1       scw 	0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    416   1.1       scw 	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    417   1.1       scw 	0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    418   1.1       scw 	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    419   1.1       scw 	0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    420   1.1       scw 	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    421   1.1       scw 	0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    422   1.1       scw 	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    423   1.1       scw 	0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
    424   1.1       scw };
    425   1.1       scw 
    426   1.1       scw #define	UTOPPY_CRC16(ccrc,b)	\
    427   1.1       scw 	(utoppy_crc16_lookup[((ccrc) ^ (b)) & 0xffu] ^ ((ccrc) >> 8))
    428   1.1       scw 
    429   1.1       scw static const int utoppy_usbdstatus_lookup[] = {
    430   1.1       scw 	0,		/* USBD_NORMAL_COMPLETION */
    431   1.1       scw 	EINPROGRESS,	/* USBD_IN_PROGRESS */
    432   1.1       scw 	EALREADY,	/* USBD_PENDING_REQUESTS */
    433   1.1       scw 	EAGAIN,		/* USBD_NOT_STARTED */
    434   1.1       scw 	EINVAL,		/* USBD_INVAL */
    435   1.1       scw 	ENOMEM,		/* USBD_NOMEM */
    436   1.1       scw 	ECONNRESET,	/* USBD_CANCELLED */
    437   1.1       scw 	EFAULT,		/* USBD_BAD_ADDRESS */
    438   1.1       scw 	EBUSY,		/* USBD_IN_USE */
    439   1.1       scw 	EADDRNOTAVAIL,	/* USBD_NO_ADDR */
    440   1.1       scw 	ENETDOWN,	/* USBD_SET_ADDR_FAILED */
    441   1.1       scw 	EIO,		/* USBD_NO_POWER */
    442   1.1       scw 	EMLINK,		/* USBD_TOO_DEEP */
    443   1.1       scw 	EIO,		/* USBD_IOERROR */
    444   1.1       scw 	ENXIO,		/* USBD_NOT_CONFIGURED */
    445   1.1       scw 	ETIMEDOUT,	/* USBD_TIMEOUT */
    446   1.1       scw 	EBADMSG,	/* USBD_SHORT_XFER */
    447   1.1       scw 	EHOSTDOWN,	/* USBD_STALLED */
    448   1.1       scw 	EINTR		/* USBD_INTERRUPTED */
    449   1.1       scw };
    450   1.1       scw 
    451   1.1       scw static __inline int
    452   1.1       scw utoppy_usbd_status2errno(usbd_status err)
    453   1.1       scw {
    454   1.1       scw 
    455   1.1       scw 	if (err >= USBD_ERROR_MAX)
    456  1.25     skrll 		return EFAULT;
    457  1.25     skrll 	return utoppy_usbdstatus_lookup[err];
    458   1.1       scw }
    459   1.1       scw 
    460   1.1       scw #ifdef UTOPPY_DEBUG
    461   1.1       scw static const char *
    462   1.1       scw utoppy_state_string(enum utoppy_state state)
    463   1.1       scw {
    464   1.1       scw 	const char *str;
    465   1.1       scw 
    466   1.1       scw 	switch (state) {
    467   1.1       scw 	case UTOPPY_STATE_CLOSED:
    468   1.1       scw 		str = "CLOSED";
    469   1.1       scw 		break;
    470   1.1       scw 	case UTOPPY_STATE_OPENING:
    471   1.1       scw 		str = "OPENING";
    472   1.1       scw 		break;
    473   1.1       scw 	case UTOPPY_STATE_IDLE:
    474   1.1       scw 		str = "IDLE";
    475   1.1       scw 		break;
    476   1.1       scw 	case UTOPPY_STATE_READDIR:
    477   1.1       scw 		str = "READ DIRECTORY";
    478   1.1       scw 		break;
    479   1.1       scw 	case UTOPPY_STATE_READFILE:
    480   1.1       scw 		str = "READ FILE";
    481   1.1       scw 		break;
    482   1.1       scw 	case UTOPPY_STATE_WRITEFILE:
    483   1.1       scw 		str = "WRITE FILE";
    484   1.1       scw 		break;
    485   1.1       scw 	default:
    486   1.1       scw 		str = "INVALID!";
    487   1.1       scw 		break;
    488   1.1       scw 	}
    489   1.1       scw 
    490  1.25     skrll 	return str;
    491   1.1       scw }
    492   1.1       scw 
    493   1.1       scw static void
    494   1.1       scw utoppy_dump_packet(const void *b, size_t len)
    495   1.1       scw {
    496   1.1       scw 	const uint8_t *buf = b, *l;
    497   1.1       scw 	uint8_t c;
    498   1.1       scw 	size_t i, j;
    499   1.1       scw 
    500   1.1       scw 	if (len == 0)
    501   1.1       scw 		return;
    502   1.1       scw 
    503   1.1       scw 	len = min(len, 256);
    504   1.1       scw 
    505   1.1       scw 	printf("00: ");
    506   1.1       scw 
    507   1.1       scw 	for (i = 0, l = buf; i < len; i++) {
    508   1.1       scw 		printf("%02x ", *buf++);
    509   1.1       scw 
    510   1.1       scw 		if ((i % 16) == 15) {
    511   1.1       scw 			for (j = 0; j < 16; j++) {
    512   1.1       scw 				c = *l++;
    513   1.1       scw 				if (c < ' ' || c > 0x7e)
    514   1.1       scw 					c = '.';
    515   1.1       scw 				printf("%c", c);
    516   1.1       scw 			}
    517   1.1       scw 
    518   1.1       scw 			printf("\n");
    519   1.1       scw 			l = buf;
    520   1.1       scw 
    521   1.1       scw 			if ((i + 1) < len)
    522   1.1       scw 				printf("%02x: ", (u_int)i + 1);
    523   1.1       scw 		}
    524   1.1       scw 	}
    525   1.1       scw 
    526   1.1       scw 	while ((i++ % 16) != 0)
    527   1.1       scw 		printf("   ");
    528   1.1       scw 
    529   1.1       scw 	if (l < buf) {
    530   1.1       scw 		while (l < buf) {
    531   1.1       scw 			c = *l++;
    532   1.1       scw 			if (c < ' ' || c > 0x7e)
    533   1.1       scw 				c = '.';
    534   1.1       scw 			printf("%c", c);
    535   1.1       scw 		}
    536   1.1       scw 
    537   1.1       scw 		printf("\n");
    538   1.1       scw 	}
    539   1.1       scw }
    540   1.1       scw #endif
    541   1.1       scw 
    542   1.1       scw static usbd_status
    543  1.25     skrll utoppy_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
    544  1.25     skrll     uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
    545   1.1       scw {
    546   1.1       scw 	usbd_status err;
    547   1.1       scw 
    548  1.25     skrll 	usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
    549  1.22     skrll 
    550  1.22     skrll 	err = usbd_sync_transfer_sig(xfer);
    551  1.22     skrll 
    552  1.22     skrll 	usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
    553  1.25     skrll 	return err;
    554   1.1       scw }
    555   1.1       scw 
    556   1.1       scw static int
    557   1.1       scw utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout)
    558   1.1       scw {
    559   1.1       scw 	struct utoppy_header *h;
    560   1.1       scw 	usbd_status err;
    561   1.1       scw 	uint32_t len;
    562   1.1       scw 	uint16_t dlen, crc;
    563   1.1       scw 	uint8_t *data, *e, t1, t2;
    564   1.1       scw 
    565   1.1       scw 	h = sc->sc_out_data;
    566   1.1       scw 
    567   1.1       scw 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, "
    568  1.15    dyoung 	    "len %d\n", device_xname(sc->sc_dev), (u_int)cmd, h->h_len));
    569   1.1       scw 
    570   1.1       scw 	dlen = h->h_len;
    571   1.1       scw 	len = dlen + UTOPPY_HEADER_SIZE;
    572   1.1       scw 
    573   1.1       scw 	if (len & 1)
    574   1.1       scw 		len++;
    575   1.1       scw 	if ((len % 64) == 0)
    576   1.1       scw 		len += 2;
    577   1.1       scw 
    578   1.1       scw 	if (len >= UTOPPY_BSIZE) {
    579   1.1       scw 		DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
    580  1.15    dyoung 		    "packet too big (%d)\n", device_xname(sc->sc_dev), (int)len));
    581  1.25     skrll 		return EINVAL;
    582   1.1       scw 	}
    583   1.1       scw 
    584   1.1       scw 	h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE);
    585   1.1       scw 	h->h_cmd2 = 0;
    586   1.1       scw 	h->h_cmd = htole16(cmd);
    587   1.1       scw 
    588   1.1       scw 	/* The command word is part of the CRC */
    589   1.1       scw 	crc = UTOPPY_CRC16(0,   0);
    590   1.1       scw 	crc = UTOPPY_CRC16(crc, 0);
    591   1.1       scw 	crc = UTOPPY_CRC16(crc, cmd >> 8);
    592   1.1       scw 	crc = UTOPPY_CRC16(crc, cmd);
    593   1.1       scw 
    594   1.1       scw 	/*
    595   1.1       scw 	 * If there is data following the header, calculate the CRC and
    596   1.1       scw 	 * byte-swap as we go.
    597   1.1       scw 	 */
    598   1.1       scw 	if (dlen) {
    599   1.1       scw 		data = h->h_data;
    600   1.1       scw 		e = data + (dlen & ~1);
    601   1.1       scw 
    602   1.1       scw 		do {
    603   1.1       scw 			t1 = data[0];
    604   1.1       scw 			t2 = data[1];
    605   1.1       scw 			crc = UTOPPY_CRC16(crc, t1);
    606   1.1       scw 			crc = UTOPPY_CRC16(crc, t2);
    607   1.1       scw 			*data++ = t2;
    608   1.1       scw 			*data++ = t1;
    609   1.1       scw 		} while (data < e);
    610   1.1       scw 
    611   1.1       scw 		if (dlen & 1) {
    612   1.1       scw 			t1 = data[0];
    613   1.1       scw 			crc = UTOPPY_CRC16(crc, t1);
    614   1.1       scw 			data[1] = t1;
    615   1.1       scw 		}
    616   1.1       scw 	}
    617   1.1       scw 
    618   1.1       scw 	h->h_crc = htole16(crc);
    619   1.1       scw 	data = sc->sc_out_data;
    620   1.1       scw 
    621   1.1       scw 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len "
    622  1.15    dyoung 	    "%d...\n", device_xname(sc->sc_dev), (int)len));
    623   1.1       scw 	DDUMP_PACKET(data, len);
    624   1.1       scw 
    625   1.1       scw 	do {
    626   1.1       scw 		uint32_t thislen;
    627   1.1       scw 
    628   1.1       scw 		thislen = min(len, UTOPPY_FRAG_SIZE);
    629   1.1       scw 
    630   1.1       scw 		memcpy(sc->sc_out_buf, data, thislen);
    631   1.1       scw 
    632   1.1       scw 		err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe,
    633  1.25     skrll 		    0, timeout, sc->sc_out_buf, &thislen);
    634   1.1       scw 
    635   1.1       scw 		if (thislen != min(len, UTOPPY_FRAG_SIZE)) {
    636   1.1       scw 			DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: "
    637   1.1       scw 			    "utoppy_send_packet: sent %ld, err %d\n",
    638  1.15    dyoung 			    device_xname(sc->sc_dev), (u_long)thislen, err));
    639   1.1       scw 		}
    640   1.1       scw 
    641   1.1       scw 		if (err == 0) {
    642   1.1       scw 			len -= thislen;
    643   1.1       scw 			data += thislen;
    644   1.1       scw 		}
    645   1.1       scw 	} while (err == 0 && len);
    646   1.1       scw 
    647   1.1       scw 	DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
    648  1.15    dyoung 	    "usbd_bulk_transfer() returned %d.\n", device_xname(sc->sc_dev),err));
    649   1.1       scw 
    650  1.25     skrll 	return err ? utoppy_usbd_status2errno(err) : 0;
    651   1.1       scw }
    652   1.1       scw 
    653   1.1       scw static int
    654   1.1       scw utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout)
    655   1.1       scw {
    656   1.1       scw 	struct utoppy_header *h;
    657   1.1       scw 	usbd_status err;
    658   1.1       scw 	uint32_t len, thislen, requested, bytesleft;
    659   1.4       scw 	uint16_t crc;
    660   1.1       scw 	uint8_t *data, *e, t1, t2;
    661   1.1       scw 
    662   1.1       scw 	data = sc->sc_in_data;
    663   1.1       scw 	len = 0;
    664   1.1       scw 	bytesleft = UTOPPY_BSIZE;
    665   1.1       scw 
    666   1.1       scw 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n",
    667  1.15    dyoung 	    device_xname(sc->sc_dev)));
    668   1.1       scw 
    669   1.1       scw 	do {
    670   1.1       scw 		requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE);
    671   1.1       scw 
    672   1.1       scw 		err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe,
    673  1.25     skrll 		    USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf,
    674  1.25     skrll 		    &thislen);
    675   1.1       scw 
    676   1.1       scw 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
    677   1.1       scw 		    "usbd_bulk_transfer() returned %d, thislen %d, data %p\n",
    678  1.15    dyoung 		    device_xname(sc->sc_dev), err, (u_int)thislen, data));
    679   1.1       scw 
    680   1.1       scw 		if (err == 0) {
    681   1.1       scw 			memcpy(data, sc->sc_in_buf, thislen);
    682   1.1       scw 			DDUMP_PACKET(data, thislen);
    683   1.1       scw 			len += thislen;
    684   1.1       scw 			bytesleft -= thislen;
    685   1.1       scw 			data += thislen;
    686   1.1       scw 		}
    687   1.1       scw 	} while (err == 0 && bytesleft && thislen == requested);
    688   1.1       scw 
    689   1.1       scw 	if (err)
    690  1.25     skrll 		return utoppy_usbd_status2errno(err);
    691   1.1       scw 
    692   1.1       scw 	h = sc->sc_in_data;
    693   1.1       scw 
    694   1.1       scw 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d "
    695  1.15    dyoung 	    "bytes in total to %p\n", device_xname(sc->sc_dev), (u_int)len, h));
    696   1.1       scw 	DDUMP_PACKET(h, len);
    697   1.1       scw 
    698   1.1       scw 	if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) {
    699   1.1       scw 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad "
    700  1.15    dyoung 		    " length (len %d, h_len %d)\n", device_xname(sc->sc_dev),
    701   1.1       scw 		    (int)len, le16toh(h->h_len)));
    702  1.25     skrll 		return EIO;
    703   1.1       scw 	}
    704   1.1       scw 
    705   1.1       scw 	len = h->h_len = le16toh(h->h_len);
    706   1.1       scw 	h->h_crc = le16toh(h->h_crc);
    707   1.1       scw 	*respp = h->h_cmd = le16toh(h->h_cmd);
    708   1.1       scw 	h->h_cmd2 = le16toh(h->h_cmd2);
    709   1.1       scw 
    710   1.1       scw 	/*
    711   1.1       scw 	 * To maximise data throughput when transferring files, acknowledge
    712   1.1       scw 	 * data blocks as soon as we receive them. If we detect an error
    713   1.1       scw 	 * later on, we can always cancel.
    714   1.1       scw 	 */
    715   1.1       scw 	if (*respp == UTOPPY_RESP_FILE_DATA) {
    716   1.1       scw 		DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
    717  1.15    dyoung 		    "ACKing file data\n", device_xname(sc->sc_dev)));
    718   1.1       scw 
    719   1.1       scw 		UTOPPY_OUT_INIT(sc);
    720   1.1       scw 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
    721   1.1       scw 		    UTOPPY_SHORT_TIMEOUT);
    722   1.1       scw 		if (err) {
    723   1.1       scw 			DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: "
    724   1.1       scw 			    "utoppy_recv_packet: failed to ACK file data: %d\n",
    725  1.15    dyoung 			    device_xname(sc->sc_dev), err));
    726  1.25     skrll 			return err;
    727   1.1       scw 		}
    728   1.1       scw 	}
    729   1.1       scw 
    730   1.1       scw 	/* The command word is part of the CRC */
    731   1.4       scw 	crc = UTOPPY_CRC16(0,   h->h_cmd2 >> 8);
    732   1.4       scw 	crc = UTOPPY_CRC16(crc, h->h_cmd2);
    733   1.1       scw 	crc = UTOPPY_CRC16(crc, h->h_cmd >> 8);
    734   1.1       scw 	crc = UTOPPY_CRC16(crc, h->h_cmd);
    735   1.1       scw 
    736   1.1       scw 	/*
    737   1.1       scw 	 * Extract any payload, byte-swapping and calculating the CRC16
    738   1.1       scw 	 * as we go.
    739   1.1       scw 	 */
    740   1.1       scw 	if (len > UTOPPY_HEADER_SIZE) {
    741   1.1       scw 		data = h->h_data;
    742   1.1       scw 		e = data + ((len & ~1) - UTOPPY_HEADER_SIZE);
    743   1.1       scw 
    744   1.1       scw 		while (data < e) {
    745   1.1       scw 			t1 = data[0];
    746   1.1       scw 			t2 = data[1];
    747   1.1       scw 			crc = UTOPPY_CRC16(crc, t2);
    748   1.1       scw 			crc = UTOPPY_CRC16(crc, t1);
    749   1.1       scw 			*data++ = t2;
    750   1.1       scw 			*data++ = t1;
    751   1.1       scw 		}
    752   1.1       scw 
    753   1.1       scw 		if (len & 1) {
    754   1.1       scw 			t1 = data[1];
    755   1.1       scw 			crc = UTOPPY_CRC16(crc, t1);
    756   1.1       scw 			*data = t1;
    757   1.1       scw 		}
    758   1.1       scw 	}
    759   1.1       scw 
    760   1.1       scw 	sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE;
    761   1.1       scw 	sc->sc_in_offset = 0;
    762   1.1       scw 
    763   1.1       scw 	DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, "
    764  1.15    dyoung 	    "crc 0x%04x, hdrcrc 0x%04x\n", device_xname(sc->sc_dev),
    765   1.1       scw 	    (int)len, crc, h->h_crc));
    766   1.1       scw 	DDUMP_PACKET(h, len);
    767   1.1       scw 
    768  1.25     skrll 	return (crc == h->h_crc) ? 0 : EBADMSG;
    769   1.1       scw }
    770   1.1       scw 
    771   1.1       scw static __inline void *
    772   1.1       scw utoppy_current_ptr(void *b)
    773   1.1       scw {
    774   1.1       scw 	struct utoppy_header *h = b;
    775   1.1       scw 
    776  1.25     skrll 	return &h->h_data[h->h_len];
    777   1.1       scw }
    778   1.1       scw 
    779   1.1       scw static __inline void
    780   1.1       scw utoppy_advance_ptr(void *b, size_t len)
    781   1.1       scw {
    782   1.1       scw 	struct utoppy_header *h = b;
    783   1.1       scw 
    784   1.1       scw 	h->h_len += len;
    785   1.1       scw }
    786   1.1       scw 
    787   1.1       scw static __inline void
    788   1.1       scw utoppy_add_8(struct utoppy_softc *sc, uint8_t v)
    789   1.1       scw {
    790   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    791   1.1       scw 	uint8_t *p;
    792   1.1       scw 
    793   1.1       scw 	p = utoppy_current_ptr(h);
    794   1.1       scw 	*p = v;
    795   1.1       scw 	utoppy_advance_ptr(h, sizeof(v));
    796   1.1       scw }
    797   1.1       scw 
    798   1.1       scw static __inline void
    799   1.1       scw utoppy_add_16(struct utoppy_softc *sc, uint16_t v)
    800   1.1       scw {
    801   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    802   1.1       scw 	uint8_t *p;
    803   1.1       scw 
    804   1.1       scw 	p = utoppy_current_ptr(h);
    805   1.1       scw 	*p++ = (uint8_t)(v >> 8);
    806   1.1       scw 	*p = (uint8_t)v;
    807   1.1       scw 	utoppy_advance_ptr(h, sizeof(v));
    808   1.1       scw }
    809   1.1       scw 
    810   1.1       scw static __inline void
    811   1.1       scw utoppy_add_32(struct utoppy_softc *sc, uint32_t v)
    812   1.1       scw {
    813   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    814   1.1       scw 	uint8_t *p;
    815   1.1       scw 
    816   1.1       scw 	p = utoppy_current_ptr(h);
    817   1.1       scw 	*p++ = (uint8_t)(v >> 24);
    818   1.1       scw 	*p++ = (uint8_t)(v >> 16);
    819   1.1       scw 	*p++ = (uint8_t)(v >> 8);
    820   1.1       scw 	*p = (uint8_t)v;
    821   1.1       scw 	utoppy_advance_ptr(h, sizeof(v));
    822   1.1       scw }
    823   1.1       scw 
    824   1.1       scw static __inline void
    825   1.1       scw utoppy_add_64(struct utoppy_softc *sc, uint64_t v)
    826   1.1       scw {
    827   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    828   1.1       scw 	uint8_t *p;
    829   1.1       scw 
    830   1.1       scw 	p = utoppy_current_ptr(h);
    831   1.1       scw 	*p++ = (uint8_t)(v >> 56);
    832   1.1       scw 	*p++ = (uint8_t)(v >> 48);
    833   1.1       scw 	*p++ = (uint8_t)(v >> 40);
    834   1.1       scw 	*p++ = (uint8_t)(v >> 32);
    835   1.1       scw 	*p++ = (uint8_t)(v >> 24);
    836   1.1       scw 	*p++ = (uint8_t)(v >> 16);
    837   1.1       scw 	*p++ = (uint8_t)(v >> 8);
    838   1.1       scw 	*p = (uint8_t)v;
    839   1.1       scw 	utoppy_advance_ptr(h, sizeof(v));
    840   1.1       scw }
    841   1.1       scw 
    842   1.1       scw static __inline void
    843   1.1       scw utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len)
    844   1.1       scw {
    845   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    846   1.1       scw 	char *p;
    847   1.1       scw 
    848   1.1       scw 	p = utoppy_current_ptr(h);
    849   1.1       scw 	memset(p, 0, len);
    850   1.1       scw 	strncpy(p, str, len);
    851   1.1       scw 	utoppy_advance_ptr(h, len);
    852   1.1       scw }
    853   1.1       scw 
    854   1.1       scw static int
    855   1.1       scw utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen)
    856   1.1       scw {
    857   1.1       scw 	struct utoppy_header *h = sc->sc_out_data;
    858   1.1       scw 	uint8_t *p, *str, *s;
    859   1.1       scw 	size_t len;
    860   1.1       scw 	int err;
    861   1.1       scw 
    862   1.1       scw 	p = utoppy_current_ptr(h);
    863   1.1       scw 
    864   1.1       scw 	str = putlen ? (p + sizeof(uint16_t)) : p;
    865   1.1       scw 
    866   1.1       scw 	err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len);
    867   1.1       scw 
    868   1.1       scw 	DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n",
    869   1.1       scw 	    err, (int)len));
    870   1.1       scw 
    871   1.1       scw 	if (err)
    872  1.25     skrll 		return err;
    873   1.1       scw 
    874   1.1       scw 	if (len < 2)
    875  1.25     skrll 		return EINVAL;
    876   1.1       scw 
    877   1.1       scw 	/*
    878   1.1       scw 	 * copyinstr(9) has already copied the terminating NUL character,
    879   1.1       scw 	 * but we append another one in case we have to pad the length
    880   1.1       scw 	 * later on.
    881   1.1       scw 	 */
    882   1.1       scw 	str[len] = '\0';
    883   1.1       scw 
    884   1.1       scw 	/*
    885   1.1       scw 	 * The Toppy uses backslash as the directory separator, so convert
    886   1.1       scw 	 * all forward slashes.
    887   1.1       scw 	 */
    888   1.1       scw 	for (s = &str[len - 2]; s >= str; s--)
    889   1.1       scw 		if (*s == '/')
    890   1.1       scw 			*s = '\\';
    891   1.1       scw 
    892   1.1       scw 	if ((len + h->h_len) & 1)
    893   1.1       scw 		len++;
    894   1.1       scw 
    895   1.1       scw 	if (putlen)
    896   1.1       scw 		utoppy_add_16(sc, len);
    897   1.1       scw 
    898   1.1       scw 	utoppy_advance_ptr(h, len);
    899   1.1       scw 
    900   1.1       scw 	DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n",
    901   1.1       scw 	    (u_int)len));
    902   1.1       scw 
    903  1.25     skrll 	return 0;
    904   1.1       scw }
    905   1.1       scw 
    906   1.1       scw static __inline int
    907   1.1       scw utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp)
    908   1.1       scw {
    909   1.1       scw 	uint8_t *p;
    910   1.1       scw 
    911   1.1       scw 	if (sc->sc_in_len < sizeof(*vp))
    912  1.25     skrll 		return 1;
    913   1.1       scw 
    914   1.1       scw 	p = UTOPPY_IN_DATA(sc);
    915   1.1       scw 	*vp = *p;
    916   1.1       scw 	sc->sc_in_offset += sizeof(*vp);
    917   1.1       scw 	sc->sc_in_len -= sizeof(*vp);
    918  1.25     skrll 	return 0;
    919   1.1       scw }
    920   1.1       scw 
    921   1.1       scw static __inline int
    922   1.1       scw utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp)
    923   1.1       scw {
    924   1.1       scw 	uint16_t v;
    925   1.1       scw 	uint8_t *p;
    926   1.1       scw 
    927   1.1       scw 	if (sc->sc_in_len < sizeof(v))
    928  1.25     skrll 		return 1;
    929   1.1       scw 
    930   1.1       scw 	p = UTOPPY_IN_DATA(sc);
    931   1.1       scw 	v = *p++;
    932   1.1       scw 	v = (v << 8) | *p;
    933   1.1       scw 	*vp = v;
    934   1.1       scw 	sc->sc_in_offset += sizeof(v);
    935   1.1       scw 	sc->sc_in_len -= sizeof(v);
    936  1.25     skrll 	return 0;
    937   1.1       scw }
    938   1.1       scw 
    939   1.1       scw static __inline int
    940   1.1       scw utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp)
    941   1.1       scw {
    942   1.1       scw 	uint32_t v;
    943   1.1       scw 	uint8_t *p;
    944   1.1       scw 
    945   1.1       scw 	if (sc->sc_in_len < sizeof(v))
    946  1.25     skrll 		return 1;
    947   1.1       scw 
    948   1.1       scw 	p = UTOPPY_IN_DATA(sc);
    949   1.1       scw 	v = *p++;
    950   1.1       scw 	v = (v << 8) | *p++;
    951   1.1       scw 	v = (v << 8) | *p++;
    952   1.1       scw 	v = (v << 8) | *p;
    953   1.1       scw 	*vp = v;
    954   1.1       scw 	sc->sc_in_offset += sizeof(v);
    955   1.1       scw 	sc->sc_in_len -= sizeof(v);
    956  1.25     skrll 	return 0;
    957   1.1       scw }
    958   1.1       scw 
    959   1.1       scw static __inline int
    960   1.1       scw utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp)
    961   1.1       scw {
    962   1.1       scw 	uint64_t v;
    963   1.1       scw 	uint8_t *p;
    964   1.1       scw 
    965   1.1       scw 	if (sc->sc_in_len < sizeof(v))
    966  1.25     skrll 		return 1;
    967   1.1       scw 
    968   1.1       scw 	p = UTOPPY_IN_DATA(sc);
    969   1.1       scw 	v = *p++;
    970   1.1       scw 	v = (v << 8) | *p++;
    971   1.1       scw 	v = (v << 8) | *p++;
    972   1.1       scw 	v = (v << 8) | *p++;
    973   1.1       scw 	v = (v << 8) | *p++;
    974   1.1       scw 	v = (v << 8) | *p++;
    975   1.1       scw 	v = (v << 8) | *p++;
    976   1.1       scw 	v = (v << 8) | *p;
    977   1.1       scw 	*vp = v;
    978   1.1       scw 	sc->sc_in_offset += sizeof(v);
    979   1.1       scw 	sc->sc_in_len -= sizeof(v);
    980  1.25     skrll 	return 0;
    981   1.1       scw }
    982   1.1       scw 
    983   1.1       scw static __inline int
    984   1.1       scw utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len)
    985   1.1       scw {
    986   1.1       scw 	char *p;
    987   1.1       scw 
    988   1.1       scw 	if (sc->sc_in_len < len)
    989  1.25     skrll 		return 1;
    990   1.1       scw 
    991   1.1       scw 	memset(str, 0, len);
    992   1.1       scw 	p = UTOPPY_IN_DATA(sc);
    993   1.1       scw 	strncpy(str, p, len);
    994   1.1       scw 	sc->sc_in_offset += len;
    995   1.1       scw 	sc->sc_in_len -= len;
    996  1.25     skrll 	return 0;
    997   1.1       scw }
    998   1.1       scw 
    999   1.1       scw static int
   1000   1.1       scw utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout,
   1001   1.1       scw     uint16_t *presp)
   1002   1.1       scw {
   1003   1.1       scw 	int err;
   1004   1.1       scw 
   1005   1.1       scw 	err = utoppy_send_packet(sc, cmd, timeout);
   1006   1.1       scw 	if (err)
   1007  1.25     skrll 		return err;
   1008   1.1       scw 
   1009   1.1       scw 	err = utoppy_recv_packet(sc, presp, timeout);
   1010   1.1       scw 	if (err == EBADMSG) {
   1011   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1012   1.1       scw 		utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout);
   1013   1.1       scw 	}
   1014   1.1       scw 
   1015  1.25     skrll 	return err;
   1016   1.1       scw }
   1017   1.1       scw 
   1018   1.1       scw static int
   1019   1.1       scw utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp)
   1020   1.1       scw {
   1021   1.1       scw 	uint16_t mjd;
   1022   1.1       scw 	uint8_t hour, minute, sec;
   1023   1.1       scw 	uint32_t rv;
   1024   1.1       scw 
   1025   1.1       scw 	if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) ||
   1026   1.1       scw 	    utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec))
   1027  1.25     skrll 		return 1;
   1028   1.1       scw 
   1029   1.1       scw 	if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){
   1030   1.1       scw 		*tp = 0;
   1031  1.25     skrll 		return 0;
   1032   1.1       scw 	}
   1033   1.1       scw 
   1034   1.1       scw 	rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd;
   1035   1.1       scw 
   1036   1.1       scw 	/* Calculate seconds since 1970 */
   1037   1.1       scw 	rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24;
   1038   1.1       scw 
   1039   1.1       scw 	/* Add in the hours, minutes, and seconds */
   1040   1.1       scw 	rv += (uint32_t)hour * 60 * 60;
   1041   1.1       scw 	rv += (uint32_t)minute * 60;
   1042   1.1       scw 	rv += sec;
   1043   1.1       scw 	*tp = (time_t)rv;
   1044   1.1       scw 
   1045  1.25     skrll 	return 0;
   1046   1.1       scw }
   1047   1.1       scw 
   1048   1.1       scw static void
   1049   1.1       scw utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t)
   1050   1.1       scw {
   1051   1.1       scw 	u_int mjd, hour, minute;
   1052   1.1       scw 
   1053   1.1       scw 	mjd = t / (60 * 60 * 24);
   1054   1.1       scw 	t -= mjd * 60 * 60 * 24;
   1055   1.1       scw 
   1056   1.1       scw 	hour = t / (60 * 60);
   1057   1.1       scw 	t -= hour * 60 * 60;
   1058   1.1       scw 
   1059   1.1       scw 	minute = t / 60;
   1060   1.1       scw 	t -= minute * 60;
   1061   1.1       scw 
   1062   1.1       scw 	utoppy_add_16(sc, mjd + UTOPPY_MJD_1970);
   1063   1.1       scw 	utoppy_add_8(sc, hour);
   1064   1.1       scw 	utoppy_add_8(sc, minute);
   1065   1.1       scw 	utoppy_add_8(sc, t);
   1066   1.1       scw }
   1067   1.1       scw 
   1068   1.1       scw static int
   1069   1.1       scw utoppy_turbo_mode(struct utoppy_softc *sc, int state)
   1070   1.1       scw {
   1071   1.1       scw 	uint16_t r;
   1072   1.1       scw 	int err;
   1073   1.1       scw 
   1074   1.1       scw 	UTOPPY_OUT_INIT(sc);
   1075   1.1       scw 	utoppy_add_32(sc, state);
   1076   1.1       scw 
   1077   1.1       scw 	err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r);
   1078   1.1       scw 	if (err)
   1079  1.25     skrll 		return err;
   1080   1.1       scw 
   1081  1.25     skrll 	return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO;
   1082   1.1       scw }
   1083   1.1       scw 
   1084   1.1       scw static int
   1085   1.1       scw utoppy_check_ready(struct utoppy_softc *sc)
   1086   1.1       scw {
   1087   1.1       scw 	uint16_t r;
   1088   1.1       scw 	int err;
   1089   1.1       scw 
   1090   1.1       scw 	UTOPPY_OUT_INIT(sc);
   1091   1.1       scw 
   1092   1.1       scw 	err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r);
   1093   1.1       scw 	if (err)
   1094  1.25     skrll 		return err;
   1095   1.1       scw 
   1096  1.25     skrll 	return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO;
   1097   1.1       scw }
   1098   1.1       scw 
   1099   1.1       scw static int
   1100   1.1       scw utoppy_cancel(struct utoppy_softc *sc)
   1101   1.1       scw {
   1102   1.1       scw 	uint16_t r;
   1103   1.1       scw 	int err, i;
   1104   1.1       scw 
   1105   1.1       scw 	/*
   1106   1.1       scw 	 * Issue the cancel command serveral times. the Toppy doesn't
   1107   1.1       scw 	 * always respond to the first.
   1108   1.1       scw 	 */
   1109   1.1       scw 	for (i = 0; i < 3; i++) {
   1110   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1111   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_CANCEL,
   1112   1.1       scw 		    UTOPPY_SHORT_TIMEOUT, &r);
   1113   1.1       scw 		if (err == 0 && r == UTOPPY_RESP_SUCCESS)
   1114   1.1       scw 			break;
   1115   1.1       scw 		err = ETIMEDOUT;
   1116   1.1       scw 	}
   1117   1.1       scw 
   1118   1.1       scw 	if (err)
   1119  1.25     skrll 		return err;
   1120   1.1       scw 
   1121   1.1       scw 	/*
   1122   1.1       scw 	 * Make sure turbo mode is off, otherwise the Toppy will not
   1123   1.1       scw 	 * respond to remote control input.
   1124   1.1       scw 	 */
   1125   1.1       scw 	(void) utoppy_turbo_mode(sc, 0);
   1126   1.1       scw 
   1127   1.1       scw 	sc->sc_state = UTOPPY_STATE_IDLE;
   1128  1.25     skrll 	return 0;
   1129   1.1       scw }
   1130   1.1       scw 
   1131   1.1       scw static int
   1132   1.1       scw utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us)
   1133   1.1       scw {
   1134   1.1       scw 	uint32_t hsize, hfree;
   1135   1.1       scw 	uint16_t r;
   1136   1.1       scw 	int err;
   1137   1.1       scw 
   1138   1.1       scw 	UTOPPY_OUT_INIT(sc);
   1139   1.1       scw 	err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r);
   1140   1.1       scw 	if (err)
   1141  1.25     skrll 		return err;
   1142   1.1       scw 
   1143   1.1       scw 	if (r != UTOPPY_RESP_STATS_DATA)
   1144  1.25     skrll 		return EIO;
   1145   1.1       scw 
   1146   1.1       scw 	if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree))
   1147  1.25     skrll 		return EIO;
   1148   1.1       scw 
   1149   1.1       scw 	us->us_hdd_size = hsize;
   1150   1.1       scw 	us->us_hdd_size *= 1024;
   1151   1.1       scw 	us->us_hdd_free = hfree;
   1152   1.1       scw 	us->us_hdd_free *= 1024;
   1153   1.1       scw 
   1154  1.25     skrll 	return 0;
   1155   1.1       scw }
   1156   1.1       scw 
   1157   1.1       scw static int
   1158   1.1       scw utoppy_readdir_next(struct utoppy_softc *sc)
   1159   1.1       scw {
   1160   1.1       scw 	uint16_t resp;
   1161   1.1       scw 	int err;
   1162   1.1       scw 
   1163   1.1       scw 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n",
   1164  1.15    dyoung 	    device_xname(sc->sc_dev)));
   1165   1.1       scw 
   1166   1.1       scw 	/*
   1167   1.1       scw 	 * Fetch the next READDIR response
   1168   1.1       scw 	 */
   1169   1.1       scw 	err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
   1170   1.1       scw 	if (err) {
   1171   1.1       scw 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1172   1.1       scw 		    "utoppy_recv_packet() returned %d\n",
   1173  1.15    dyoung 		    device_xname(sc->sc_dev), err));
   1174   1.1       scw 		if (err == EBADMSG) {
   1175   1.1       scw 			UTOPPY_OUT_INIT(sc);
   1176   1.1       scw 			utoppy_send_packet(sc, UTOPPY_RESP_ERROR,
   1177   1.1       scw 			    UTOPPY_LONG_TIMEOUT);
   1178   1.1       scw 		}
   1179   1.1       scw 		utoppy_cancel(sc);
   1180  1.25     skrll 		return err;
   1181   1.1       scw 	}
   1182   1.1       scw 
   1183   1.1       scw 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1184   1.1       scw 	    "utoppy_recv_packet() returned %d, len %ld\n",
   1185  1.15    dyoung 	    device_xname(sc->sc_dev), err, (u_long)sc->sc_in_len));
   1186   1.1       scw 
   1187   1.1       scw 	switch (resp) {
   1188   1.1       scw 	case UTOPPY_RESP_READDIR_DATA:
   1189   1.1       scw 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1190  1.15    dyoung 		    "UTOPPY_RESP_READDIR_DATA\n", device_xname(sc->sc_dev)));
   1191   1.1       scw 
   1192   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1193   1.1       scw 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
   1194   1.1       scw 		    UTOPPY_LONG_TIMEOUT);
   1195   1.1       scw 		if (err) {
   1196   1.1       scw 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1197   1.1       scw 			    "utoppy_send_packet(ACK) returned %d\n",
   1198  1.15    dyoung 			    device_xname(sc->sc_dev), err));
   1199   1.1       scw 			utoppy_cancel(sc);
   1200  1.25     skrll 			return err;
   1201   1.1       scw 		}
   1202   1.1       scw 		sc->sc_state = UTOPPY_STATE_READDIR;
   1203   1.1       scw 		sc->sc_in_offset = 0;
   1204   1.1       scw 		break;
   1205   1.1       scw 
   1206   1.1       scw 	case UTOPPY_RESP_READDIR_END:
   1207   1.1       scw 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1208  1.15    dyoung 		    "UTOPPY_RESP_READDIR_END\n", device_xname(sc->sc_dev)));
   1209   1.1       scw 
   1210   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1211   1.1       scw 		utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
   1212   1.1       scw 		sc->sc_state = UTOPPY_STATE_IDLE;
   1213   1.1       scw 		sc->sc_in_len = 0;
   1214   1.1       scw 		break;
   1215   1.1       scw 
   1216   1.1       scw 	default:
   1217   1.1       scw 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
   1218  1.15    dyoung 		    "bad response: 0x%x\n", device_xname(sc->sc_dev), resp));
   1219   1.1       scw 		sc->sc_state = UTOPPY_STATE_IDLE;
   1220   1.1       scw 		sc->sc_in_len = 0;
   1221  1.25     skrll 		return EIO;
   1222   1.1       scw 	}
   1223   1.1       scw 
   1224  1.25     skrll 	return 0;
   1225   1.1       scw }
   1226   1.1       scw 
   1227   1.1       scw static size_t
   1228   1.1       scw utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud)
   1229   1.1       scw {
   1230   1.1       scw 	uint8_t ftype;
   1231   1.1       scw 
   1232   1.1       scw 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left"
   1233  1.15    dyoung 	    " %d\n", device_xname(sc->sc_dev), (int)sc->sc_in_len));
   1234   1.1       scw 
   1235   1.1       scw 	if (utoppy_timestamp_decode(sc, &ud->ud_mtime) ||
   1236   1.1       scw 	    utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) ||
   1237   1.1       scw 	    utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) ||
   1238   1.1       scw 	    utoppy_get_32(sc, &ud->ud_attributes)) {
   1239   1.1       scw 		DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no "
   1240  1.15    dyoung 		    "more to decode\n", device_xname(sc->sc_dev)));
   1241  1.25     skrll 		return 0;
   1242   1.1       scw 	}
   1243   1.1       scw 
   1244   1.1       scw 	switch (ftype) {
   1245   1.1       scw 	case UTOPPY_FTYPE_DIR:
   1246   1.1       scw 		ud->ud_type = UTOPPY_DIRENT_DIRECTORY;
   1247   1.1       scw 		break;
   1248   1.1       scw 	case UTOPPY_FTYPE_FILE:
   1249   1.1       scw 		ud->ud_type = UTOPPY_DIRENT_FILE;
   1250   1.1       scw 		break;
   1251   1.1       scw 	default:
   1252   1.1       scw 		ud->ud_type = UTOPPY_DIRENT_UNKNOWN;
   1253   1.1       scw 		break;
   1254   1.1       scw 	}
   1255   1.1       scw 
   1256   1.1       scw 	DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', "
   1257  1.15    dyoung 	    "size %lld, time 0x%08lx, attr 0x%08x\n", device_xname(sc->sc_dev),
   1258   1.1       scw 	    (ftype == UTOPPY_FTYPE_DIR) ? "DIR" :
   1259   1.1       scw 	    ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path,
   1260   1.1       scw 	    ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes));
   1261   1.1       scw 
   1262  1.25     skrll 	return 1;
   1263   1.1       scw }
   1264   1.1       scw 
   1265   1.1       scw static int
   1266   1.1       scw utoppy_readfile_next(struct utoppy_softc *sc)
   1267   1.1       scw {
   1268   1.1       scw 	uint64_t off;
   1269   1.1       scw 	uint16_t resp;
   1270   1.1       scw 	int err;
   1271   1.1       scw 
   1272   1.1       scw 	err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
   1273   1.1       scw 	if (err) {
   1274   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1275   1.1       scw 		    "utoppy_recv_packet() returned %d\n",
   1276  1.15    dyoung 		    device_xname(sc->sc_dev), err));
   1277   1.1       scw 		utoppy_cancel(sc);
   1278  1.25     skrll 		return err;
   1279   1.1       scw 	}
   1280   1.1       scw 
   1281   1.1       scw 	switch (resp) {
   1282   1.1       scw 	case UTOPPY_RESP_FILE_HEADER:
   1283   1.1       scw 		/* ACK it */
   1284   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1285   1.1       scw 		err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
   1286   1.1       scw 		    UTOPPY_LONG_TIMEOUT);
   1287   1.1       scw 		if (err) {
   1288   1.1       scw 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1289   1.1       scw 			    "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n",
   1290  1.15    dyoung 			    device_xname(sc->sc_dev), err));
   1291   1.1       scw 			utoppy_cancel(sc);
   1292  1.25     skrll 			return err;
   1293   1.1       scw 		}
   1294   1.1       scw 
   1295   1.1       scw 		sc->sc_in_len = 0;
   1296   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1297  1.15    dyoung 		    "FILE_HEADER done\n", device_xname(sc->sc_dev)));
   1298   1.1       scw 		break;
   1299   1.1       scw 
   1300   1.1       scw 	case UTOPPY_RESP_FILE_DATA:
   1301   1.1       scw 		/* Already ACK'd */
   1302   1.1       scw 		if (utoppy_get_64(sc, &off)) {
   1303   1.1       scw 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1304   1.1       scw 			    "UTOPPY_RESP_FILE_DATA did not provide offset\n",
   1305  1.15    dyoung 			    device_xname(sc->sc_dev)));
   1306   1.1       scw 			utoppy_cancel(sc);
   1307  1.25     skrll 			return EBADMSG;
   1308   1.1       scw 		}
   1309   1.1       scw 
   1310   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1311   1.1       scw 		    "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n",
   1312  1.15    dyoung 		    device_xname(sc->sc_dev), off, (u_long)sc->sc_in_len));
   1313   1.1       scw 		break;
   1314   1.1       scw 
   1315   1.1       scw 	case UTOPPY_RESP_FILE_END:
   1316   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
   1317   1.1       scw 		    "UTOPPY_RESP_FILE_END: sending ACK\n",
   1318  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1319   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1320   1.1       scw 		utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
   1321   1.1       scw 		/*FALLTHROUGH*/
   1322   1.1       scw 
   1323   1.1       scw 	case UTOPPY_RESP_SUCCESS:
   1324   1.1       scw 		sc->sc_state = UTOPPY_STATE_IDLE;
   1325   1.1       scw 		(void) utoppy_turbo_mode(sc, 0);
   1326   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all "
   1327  1.15    dyoung 		    "done\n", device_xname(sc->sc_dev)));
   1328   1.1       scw 		break;
   1329   1.1       scw 
   1330   1.1       scw 	case UTOPPY_RESP_ERROR:
   1331   1.1       scw 	default:
   1332   1.1       scw 		DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad "
   1333  1.15    dyoung 		    "response code 0x%0x\n", device_xname(sc->sc_dev), resp));
   1334   1.1       scw 		utoppy_cancel(sc);
   1335  1.25     skrll 		return EIO;
   1336   1.1       scw 	}
   1337   1.1       scw 
   1338  1.25     skrll 	return 0;
   1339   1.1       scw }
   1340   1.1       scw 
   1341   1.1       scw int
   1342   1.8  christos utoppyopen(dev_t dev, int flag, int mode,
   1343   1.8  christos     struct lwp *l)
   1344   1.1       scw {
   1345   1.1       scw 	struct utoppy_softc *sc;
   1346   1.1       scw 	int error = 0;
   1347   1.1       scw 
   1348  1.15    dyoung 	sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
   1349  1.15    dyoung 	if (sc == NULL)
   1350  1.15    dyoung 		return ENXIO;
   1351   1.1       scw 
   1352   1.1       scw 	if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
   1353  1.25     skrll 		return ENXIO;
   1354   1.1       scw 
   1355   1.1       scw 	if (sc->sc_state != UTOPPY_STATE_CLOSED) {
   1356   1.1       scw 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n",
   1357  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1358  1.25     skrll 		return EBUSY;
   1359   1.1       scw 	}
   1360   1.1       scw 
   1361   1.1       scw 	DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n",
   1362  1.15    dyoung 	    device_xname(sc->sc_dev)));
   1363   1.1       scw 
   1364   1.1       scw 	sc->sc_refcnt++;
   1365   1.1       scw 	sc->sc_state = UTOPPY_STATE_OPENING;
   1366   1.1       scw 	sc->sc_turbo_mode = 0;
   1367  1.25     skrll 	sc->sc_out_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP);
   1368   1.1       scw 	if (sc->sc_out_data == NULL) {
   1369   1.1       scw 		error = ENOMEM;
   1370   1.1       scw 		goto error;
   1371   1.1       scw 	}
   1372   1.1       scw 
   1373  1.25     skrll 	sc->sc_in_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP);
   1374   1.1       scw 	if (sc->sc_in_data == NULL) {
   1375  1.25     skrll 		kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1);
   1376   1.1       scw 		sc->sc_out_data = NULL;
   1377   1.1       scw 		error = ENOMEM;
   1378   1.1       scw 		goto error;
   1379   1.1       scw 	}
   1380   1.1       scw 
   1381   1.1       scw 	if ((error = utoppy_cancel(sc)) != 0)
   1382   1.1       scw 		goto error;
   1383   1.1       scw 
   1384   1.1       scw 	if ((error = utoppy_check_ready(sc)) != 0) {
   1385   1.1       scw 		DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()"
   1386  1.15    dyoung 		    " returned %d\n", device_xname(sc->sc_dev), error));
   1387   1.1       scw 	}
   1388   1.1       scw 
   1389  1.25     skrll  error:
   1390   1.1       scw 	sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE;
   1391   1.1       scw 
   1392   1.1       scw 	DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state "
   1393  1.15    dyoung 	    "'%s'\n", device_xname(sc->sc_dev), error,
   1394   1.1       scw 	    utoppy_state_string(sc->sc_state)));
   1395   1.1       scw 
   1396   1.1       scw 	if (--sc->sc_refcnt < 0)
   1397  1.18       mrg 		usb_detach_wakeupold(sc->sc_dev);
   1398   1.1       scw 
   1399  1.25     skrll 	return error;
   1400   1.1       scw }
   1401   1.1       scw 
   1402   1.1       scw int
   1403   1.8  christos utoppyclose(dev_t dev, int flag, int mode,
   1404   1.8  christos     struct lwp *l)
   1405   1.1       scw {
   1406   1.1       scw 	struct utoppy_softc *sc;
   1407   1.1       scw 	usbd_status err;
   1408   1.1       scw 
   1409  1.15    dyoung 	sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
   1410   1.1       scw 
   1411   1.1       scw 	DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
   1412  1.15    dyoung 	    device_xname(sc->sc_dev)));
   1413   1.1       scw 
   1414   1.1       scw 	if (sc->sc_state < UTOPPY_STATE_IDLE) {
   1415   1.1       scw 		/* We are being forced to close before the open completed. */
   1416   1.1       scw 		DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
   1417  1.15    dyoung 		    " %s\n", device_xname(sc->sc_dev),
   1418   1.1       scw 		    utoppy_state_string(sc->sc_state)));
   1419  1.25     skrll 		return 0;
   1420   1.1       scw 	}
   1421   1.1       scw 
   1422   1.3  christos 	if (sc->sc_out_data)
   1423   1.3  christos 		(void) utoppy_cancel(sc);
   1424   1.1       scw 
   1425   1.1       scw 	if (sc->sc_out_pipe != NULL) {
   1426   1.1       scw 		if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
   1427   1.1       scw 			printf("usbd_abort_pipe(OUT) returned %d\n", err);
   1428   1.1       scw 		sc->sc_out_pipe = NULL;
   1429   1.1       scw 	}
   1430   1.1       scw 
   1431   1.1       scw 	if (sc->sc_in_pipe != NULL) {
   1432   1.1       scw 		if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
   1433   1.1       scw 			printf("usbd_abort_pipe(IN) returned %d\n", err);
   1434   1.1       scw 		sc->sc_in_pipe = NULL;
   1435   1.1       scw 	}
   1436   1.1       scw 
   1437   1.1       scw 	if (sc->sc_out_data) {
   1438  1.25     skrll 		kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1);
   1439   1.1       scw 		sc->sc_out_data = NULL;
   1440   1.1       scw 	}
   1441   1.1       scw 
   1442   1.1       scw 	if (sc->sc_in_data) {
   1443  1.25     skrll 		kmem_free(sc->sc_in_data, UTOPPY_BSIZE + 1);
   1444   1.1       scw 		sc->sc_in_data = NULL;
   1445   1.1       scw 	}
   1446   1.1       scw 
   1447   1.1       scw 	sc->sc_state = UTOPPY_STATE_CLOSED;
   1448   1.1       scw 
   1449   1.1       scw 	DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n",
   1450  1.15    dyoung 	    device_xname(sc->sc_dev)));
   1451   1.1       scw 
   1452  1.25     skrll 	return 0;
   1453   1.1       scw }
   1454   1.1       scw 
   1455   1.1       scw int
   1456   1.8  christos utoppyread(dev_t dev, struct uio *uio, int flags)
   1457   1.1       scw {
   1458   1.1       scw 	struct utoppy_softc *sc;
   1459   1.1       scw 	struct utoppy_dirent ud;
   1460   1.1       scw 	size_t len;
   1461   1.1       scw 	int err;
   1462   1.1       scw 
   1463  1.15    dyoung 	sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
   1464   1.1       scw 
   1465   1.1       scw 	if (sc->sc_dying)
   1466  1.25     skrll 		return EIO;
   1467   1.1       scw 
   1468   1.1       scw 	sc->sc_refcnt++;
   1469   1.1       scw 
   1470   1.1       scw 	DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n",
   1471  1.15    dyoung 	    device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state)));
   1472   1.1       scw 
   1473   1.1       scw 	switch (sc->sc_state) {
   1474   1.1       scw 	case UTOPPY_STATE_READDIR:
   1475   1.1       scw 		err = 0;
   1476   1.1       scw 		while (err == 0 && uio->uio_resid >= sizeof(ud) &&
   1477   1.1       scw 		    sc->sc_state != UTOPPY_STATE_IDLE) {
   1478   1.1       scw 			if (utoppy_readdir_decode(sc, &ud) == 0)
   1479   1.1       scw 				err = utoppy_readdir_next(sc);
   1480   1.1       scw 			else
   1481   1.1       scw 			if ((err = uiomove(&ud, sizeof(ud), uio)) != 0)
   1482  1.25     skrll 				utoppy_cancel(sc);
   1483   1.1       scw 		}
   1484   1.1       scw 		break;
   1485   1.1       scw 
   1486   1.1       scw 	case UTOPPY_STATE_READFILE:
   1487   1.1       scw 		err = 0;
   1488   1.1       scw 		while (err == 0 && uio->uio_resid > 0 &&
   1489   1.1       scw 		    sc->sc_state != UTOPPY_STATE_IDLE) {
   1490   1.1       scw 			DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: "
   1491   1.1       scw 			    "resid %ld, bytes_left %ld\n",
   1492  1.15    dyoung 			    device_xname(sc->sc_dev), (u_long)uio->uio_resid,
   1493   1.1       scw 			    (u_long)sc->sc_in_len));
   1494   1.1       scw 
   1495   1.1       scw 			if (sc->sc_in_len == 0 &&
   1496   1.1       scw 			    (err = utoppy_readfile_next(sc)) != 0) {
   1497   1.1       scw 				DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: "
   1498   1.1       scw 				    "READFILE: utoppy_readfile_next returned "
   1499  1.15    dyoung 				    "%d\n", device_xname(sc->sc_dev), err));
   1500   1.1       scw 				break;
   1501   1.1       scw 			}
   1502   1.1       scw 
   1503   1.1       scw 			len = min(uio->uio_resid, sc->sc_in_len);
   1504   1.1       scw 			if (len) {
   1505   1.1       scw 				err = uiomove(UTOPPY_IN_DATA(sc), len, uio);
   1506   1.1       scw 				if (err == 0) {
   1507   1.1       scw 					sc->sc_in_offset += len;
   1508   1.1       scw 					sc->sc_in_len -= len;
   1509   1.1       scw 				}
   1510   1.1       scw 			}
   1511   1.1       scw 		}
   1512   1.1       scw 		break;
   1513   1.1       scw 
   1514   1.1       scw 	case UTOPPY_STATE_IDLE:
   1515   1.1       scw 		err = 0;
   1516   1.1       scw 		break;
   1517   1.1       scw 
   1518   1.1       scw 	case UTOPPY_STATE_WRITEFILE:
   1519   1.1       scw 		err = EBUSY;
   1520   1.1       scw 		break;
   1521   1.1       scw 
   1522   1.1       scw 	default:
   1523   1.1       scw 		err = EIO;
   1524   1.1       scw 		break;
   1525   1.1       scw 	}
   1526   1.1       scw 
   1527   1.1       scw 	DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n",
   1528  1.15    dyoung 	    device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
   1529   1.1       scw 
   1530   1.1       scw 	if (--sc->sc_refcnt < 0)
   1531  1.18       mrg 		usb_detach_wakeupold(sc->sc_dev);
   1532   1.1       scw 
   1533  1.25     skrll 	return err;
   1534   1.1       scw }
   1535   1.1       scw 
   1536   1.1       scw int
   1537   1.8  christos utoppywrite(dev_t dev, struct uio *uio, int flags)
   1538   1.1       scw {
   1539   1.1       scw 	struct utoppy_softc *sc;
   1540   1.1       scw 	uint16_t resp;
   1541   1.1       scw 	size_t len;
   1542   1.1       scw 	int err;
   1543   1.1       scw 
   1544  1.15    dyoung 	sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
   1545   1.1       scw 
   1546   1.1       scw 	if (sc->sc_dying)
   1547  1.25     skrll 		return EIO;
   1548   1.1       scw 
   1549   1.1       scw 	switch(sc->sc_state) {
   1550   1.1       scw 	case UTOPPY_STATE_WRITEFILE:
   1551   1.1       scw 		break;
   1552   1.1       scw 
   1553   1.1       scw 	case UTOPPY_STATE_IDLE:
   1554  1.25     skrll 		return 0;
   1555   1.1       scw 
   1556   1.1       scw 	default:
   1557  1.25     skrll 		return EIO;
   1558   1.1       scw 	}
   1559   1.1       scw 
   1560   1.1       scw 	sc->sc_refcnt++;
   1561   1.1       scw 	err = 0;
   1562   1.1       scw 
   1563   1.1       scw 	DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, "
   1564  1.15    dyoung 	    "wr_size %lld, wr_offset %lld\n", device_xname(sc->sc_dev),
   1565   1.1       scw 	    (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset));
   1566   1.1       scw 
   1567   1.1       scw 	while (sc->sc_state == UTOPPY_STATE_WRITEFILE &&
   1568   1.1       scw 	    (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) {
   1569   1.1       scw 
   1570   1.1       scw 		len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE +
   1571   1.1       scw 		    sizeof(uint64_t) + 3));
   1572   1.1       scw 
   1573   1.1       scw 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n",
   1574  1.15    dyoung 		    device_xname(sc->sc_dev), (u_long)len));
   1575   1.1       scw 
   1576   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1577   1.1       scw 		utoppy_add_64(sc, sc->sc_wr_offset);
   1578   1.1       scw 
   1579   1.1       scw 		err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio);
   1580   1.1       scw 		if (err) {
   1581   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() "
   1582  1.15    dyoung 			    "returned %d\n", device_xname(sc->sc_dev), err));
   1583   1.1       scw 			break;
   1584   1.1       scw 		}
   1585   1.1       scw 
   1586   1.1       scw 		utoppy_advance_ptr(sc->sc_out_data, len);
   1587   1.1       scw 
   1588   1.1       scw 		err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA,
   1589   1.1       scw 		    UTOPPY_LONG_TIMEOUT, &resp);
   1590   1.1       scw 		if (err) {
   1591   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1592   1.1       scw 			    "utoppy_command(UTOPPY_RESP_FILE_DATA) "
   1593  1.15    dyoung 			    "returned %d\n", device_xname(sc->sc_dev), err));
   1594   1.1       scw 			break;
   1595   1.1       scw 		}
   1596   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS) {
   1597   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1598   1.1       scw 			    "utoppy_command(UTOPPY_RESP_FILE_DATA) returned "
   1599  1.15    dyoung 			    "bad response 0x%x\n", device_xname(sc->sc_dev),
   1600   1.1       scw 			    resp));
   1601   1.1       scw 			utoppy_cancel(sc);
   1602   1.1       scw 			err = EIO;
   1603   1.1       scw 			break;
   1604   1.1       scw 		}
   1605   1.1       scw 
   1606   1.1       scw 		sc->sc_wr_offset += len;
   1607   1.1       scw 		sc->sc_wr_size -= len;
   1608   1.1       scw 	}
   1609   1.1       scw 
   1610   1.1       scw 	DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld,"
   1611  1.15    dyoung 	    " wr_size %lld, wr_offset %lld, err %d\n", device_xname(sc->sc_dev),
   1612   1.1       scw 	    (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err));
   1613   1.1       scw 
   1614   1.1       scw 	if (err == 0 && sc->sc_wr_size == 0) {
   1615   1.1       scw 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending "
   1616  1.15    dyoung 		    "FILE_END...\n", device_xname(sc->sc_dev)));
   1617   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1618   1.1       scw 		err = utoppy_command(sc, UTOPPY_RESP_FILE_END,
   1619   1.1       scw 		    UTOPPY_LONG_TIMEOUT, &resp);
   1620   1.1       scw 		if (err) {
   1621   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
   1622   1.1       scw 			    "utoppy_command(UTOPPY_RESP_FILE_END) returned "
   1623  1.15    dyoung 			    "%d\n", device_xname(sc->sc_dev), err));
   1624   1.1       scw 
   1625   1.1       scw 			utoppy_cancel(sc);
   1626   1.1       scw 		}
   1627   1.1       scw 
   1628   1.1       scw 		sc->sc_state = UTOPPY_STATE_IDLE;
   1629   1.1       scw 		DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n",
   1630  1.15    dyoung 		    device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state)));
   1631   1.1       scw 	}
   1632   1.1       scw 
   1633   1.1       scw 	if (--sc->sc_refcnt < 0)
   1634  1.18       mrg 		usb_detach_wakeupold(sc->sc_dev);
   1635   1.1       scw 
   1636  1.25     skrll 	return err;
   1637   1.1       scw }
   1638   1.1       scw 
   1639   1.1       scw int
   1640   1.9  christos utoppyioctl(dev_t dev, u_long cmd, void *data, int flag,
   1641   1.8  christos     struct lwp *l)
   1642   1.1       scw {
   1643   1.1       scw 	struct utoppy_softc *sc;
   1644   1.1       scw 	struct utoppy_rename *ur;
   1645   1.1       scw 	struct utoppy_readfile *urf;
   1646   1.1       scw 	struct utoppy_writefile *uw;
   1647   1.1       scw 	char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp;
   1648   1.1       scw 	uint16_t resp;
   1649   1.1       scw 	int err;
   1650   1.1       scw 
   1651  1.15    dyoung 	sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
   1652   1.1       scw 
   1653   1.1       scw 	if (sc->sc_dying)
   1654  1.25     skrll 		return EIO;
   1655   1.1       scw 
   1656   1.1       scw 	DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n",
   1657  1.15    dyoung 	    device_xname(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state)));
   1658   1.1       scw 
   1659   1.1       scw 	if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) {
   1660   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n",
   1661  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1662  1.25     skrll 		return EBUSY;
   1663   1.1       scw 	}
   1664   1.1       scw 
   1665   1.1       scw 	sc->sc_refcnt++;
   1666   1.1       scw 
   1667   1.1       scw 	switch (cmd) {
   1668   1.1       scw 	case UTOPPYIOTURBO:
   1669   1.1       scw 		err = 0;
   1670   1.1       scw 		sc->sc_turbo_mode = *((int *)data) ? 1 : 0;
   1671   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: "
   1672  1.15    dyoung 		    "%s\n", device_xname(sc->sc_dev), sc->sc_turbo_mode ? "On" :
   1673   1.1       scw 		    "Off"));
   1674   1.1       scw 		break;
   1675   1.1       scw 
   1676   1.1       scw 	case UTOPPYIOCANCEL:
   1677   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n",
   1678  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1679   1.1       scw 		err = utoppy_cancel(sc);
   1680   1.1       scw 		break;
   1681   1.1       scw 
   1682   1.1       scw 	case UTOPPYIOREBOOT:
   1683   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n",
   1684  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1685   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1686   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT,
   1687   1.1       scw 		    &resp);
   1688   1.1       scw 		if (err)
   1689   1.1       scw 			break;
   1690   1.1       scw 
   1691   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS)
   1692   1.1       scw 			err = EIO;
   1693   1.1       scw 		break;
   1694   1.1       scw 
   1695   1.1       scw 	case UTOPPYIOSTATS:
   1696   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n",
   1697  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1698   1.1       scw 		err = utoppy_stats(sc, (struct utoppy_stats *)data);
   1699   1.1       scw 		break;
   1700   1.1       scw 
   1701   1.1       scw 	case UTOPPYIORENAME:
   1702   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n",
   1703  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1704   1.1       scw 		ur = (struct utoppy_rename *)data;
   1705   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1706   1.1       scw 
   1707   1.1       scw 		if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0)
   1708   1.1       scw 			break;
   1709   1.1       scw 		if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0)
   1710   1.1       scw 			break;
   1711   1.1       scw 
   1712   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT,
   1713   1.1       scw 		    &resp);
   1714   1.1       scw 		if (err)
   1715   1.1       scw 			break;
   1716   1.1       scw 
   1717   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS)
   1718   1.1       scw 			err = EIO;
   1719   1.1       scw 		break;
   1720   1.1       scw 
   1721   1.1       scw 	case UTOPPYIOMKDIR:
   1722   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n",
   1723  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1724   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1725   1.1       scw 		err = utoppy_add_path(sc, *((const char **)data), 1);
   1726   1.1       scw 		if (err)
   1727   1.1       scw 			break;
   1728   1.1       scw 
   1729   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT,
   1730   1.1       scw 		    &resp);
   1731   1.1       scw 		if (err)
   1732   1.1       scw 			break;
   1733   1.1       scw 
   1734   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS)
   1735   1.1       scw 			err = EIO;
   1736   1.1       scw 		break;
   1737   1.1       scw 
   1738   1.1       scw 	case UTOPPYIODELETE:
   1739   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n",
   1740  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1741   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1742   1.1       scw 		err = utoppy_add_path(sc, *((const char **)data), 0);
   1743   1.1       scw 		if (err)
   1744   1.1       scw 			break;
   1745   1.1       scw 
   1746   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT,
   1747   1.1       scw 		    &resp);
   1748   1.1       scw 		if (err)
   1749   1.1       scw 			break;
   1750   1.1       scw 
   1751   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS)
   1752   1.1       scw 			err = EIO;
   1753   1.1       scw 		break;
   1754   1.1       scw 
   1755   1.1       scw 	case UTOPPYIOREADDIR:
   1756   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n",
   1757  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1758   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1759   1.1       scw 		err = utoppy_add_path(sc, *((const char **)data), 0);
   1760   1.1       scw 		if (err) {
   1761   1.1       scw 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1762   1.1       scw 			    "utoppy_add_path() returned %d\n",
   1763  1.15    dyoung 			    device_xname(sc->sc_dev), err));
   1764   1.1       scw 			break;
   1765   1.1       scw 		}
   1766   1.1       scw 
   1767   1.1       scw 		err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR,
   1768   1.1       scw 		    UTOPPY_LONG_TIMEOUT);
   1769   1.1       scw 		if (err != 0) {
   1770   1.1       scw 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1771   1.1       scw 			    "UTOPPY_CMD_READDIR returned %d\n",
   1772  1.15    dyoung 			    device_xname(sc->sc_dev), err));
   1773   1.1       scw 			break;
   1774   1.1       scw 		}
   1775   1.1       scw 
   1776   1.1       scw 		err = utoppy_readdir_next(sc);
   1777   1.1       scw 		if (err) {
   1778   1.1       scw 			DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
   1779   1.1       scw 			    "utoppy_readdir_next() returned %d\n",
   1780  1.15    dyoung 			    device_xname(sc->sc_dev), err));
   1781   1.1       scw 		}
   1782   1.1       scw 		break;
   1783   1.1       scw 
   1784   1.1       scw 	case UTOPPYIOREADFILE:
   1785   1.1       scw 		urf = (struct utoppy_readfile *)data;
   1786   1.1       scw 
   1787   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE "
   1788  1.15    dyoung 		    "%s, offset %lld\n", device_xname(sc->sc_dev), urf->ur_path,
   1789   1.1       scw 		    urf->ur_offset));
   1790   1.1       scw 
   1791   1.1       scw 		if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
   1792   1.1       scw 			break;
   1793   1.1       scw 
   1794   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1795   1.1       scw 		utoppy_add_8(sc, UTOPPY_FILE_READ);
   1796   1.1       scw 
   1797   1.1       scw 		if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0)
   1798   1.1       scw 			break;
   1799   1.1       scw 
   1800   1.1       scw 		utoppy_add_64(sc, urf->ur_offset);
   1801   1.1       scw 
   1802   1.1       scw 		sc->sc_state = UTOPPY_STATE_READFILE;
   1803   1.1       scw 		sc->sc_in_offset = 0;
   1804   1.1       scw 
   1805   1.1       scw 		err = utoppy_send_packet(sc, UTOPPY_CMD_FILE,
   1806   1.1       scw 		    UTOPPY_LONG_TIMEOUT);
   1807   1.1       scw 		if (err == 0)
   1808   1.1       scw 			err = utoppy_readfile_next(sc);
   1809   1.1       scw 		break;
   1810   1.1       scw 
   1811   1.1       scw 	case UTOPPYIOWRITEFILE:
   1812   1.1       scw 		uw = (struct utoppy_writefile *)data;
   1813   1.1       scw 
   1814   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE "
   1815  1.15    dyoung 		    "%s, size %lld, offset %lld\n", device_xname(sc->sc_dev),
   1816   1.1       scw 		    uw->uw_path, uw->uw_size, uw->uw_offset));
   1817   1.1       scw 
   1818   1.1       scw 		if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
   1819   1.1       scw 			break;
   1820   1.1       scw 
   1821   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1822   1.1       scw 		utoppy_add_8(sc, UTOPPY_FILE_WRITE);
   1823   1.1       scw 		uwfp = utoppy_current_ptr(sc->sc_out_data);
   1824   1.1       scw 
   1825   1.1       scw 		if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) {
   1826   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() "
   1827  1.15    dyoung 			    "returned %d\n", device_xname(sc->sc_dev), err));
   1828   1.1       scw 			break;
   1829   1.1       scw 		}
   1830   1.1       scw 
   1831   1.1       scw 		strncpy(uwf, &uwfp[2], sizeof(uwf));
   1832   1.1       scw 		utoppy_add_64(sc, uw->uw_offset);
   1833   1.1       scw 
   1834   1.1       scw 		err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT,
   1835   1.1       scw 		    &resp);
   1836   1.1       scw 		if (err) {
   1837   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1838   1.1       scw 			    "utoppy_command(UTOPPY_CMD_FILE) returned "
   1839  1.15    dyoung 			    "%d\n", device_xname(sc->sc_dev), err));
   1840   1.1       scw 			break;
   1841   1.1       scw 		}
   1842   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS) {
   1843   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1844   1.1       scw 			    "utoppy_command(UTOPPY_CMD_FILE) returned "
   1845  1.15    dyoung 			    "bad response 0x%x\n", device_xname(sc->sc_dev),
   1846   1.1       scw 			    resp));
   1847   1.1       scw 			err = EIO;
   1848   1.1       scw 			break;
   1849   1.1       scw 		}
   1850   1.1       scw 
   1851   1.1       scw 		UTOPPY_OUT_INIT(sc);
   1852   1.1       scw 		utoppy_timestamp_encode(sc, uw->uw_mtime);
   1853   1.1       scw 		utoppy_add_8(sc, UTOPPY_FTYPE_FILE);
   1854   1.1       scw 		utoppy_add_64(sc, uw->uw_size);
   1855   1.1       scw 		utoppy_add_string(sc, uwf, sizeof(uwf));
   1856   1.1       scw 		utoppy_add_32(sc, 0);
   1857   1.1       scw 
   1858   1.1       scw 		err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER,
   1859   1.1       scw 		    UTOPPY_LONG_TIMEOUT, &resp);
   1860   1.1       scw 		if (err) {
   1861   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1862   1.1       scw 			    "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
   1863  1.15    dyoung 			    "returned %d\n", device_xname(sc->sc_dev), err));
   1864   1.1       scw 			break;
   1865   1.1       scw 		}
   1866   1.1       scw 		if (resp != UTOPPY_RESP_SUCCESS) {
   1867   1.1       scw 			DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
   1868   1.1       scw 			    "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
   1869   1.1       scw 			    "returned bad response 0x%x\n",
   1870  1.15    dyoung 			    device_xname(sc->sc_dev), resp));
   1871   1.1       scw 			err = EIO;
   1872   1.1       scw 			break;
   1873   1.1       scw 		}
   1874   1.1       scw 
   1875   1.1       scw 		sc->sc_wr_offset = uw->uw_offset;
   1876   1.1       scw 		sc->sc_wr_size = uw->uw_size;
   1877   1.1       scw 		sc->sc_state = UTOPPY_STATE_WRITEFILE;
   1878   1.1       scw 
   1879   1.1       scw 		DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to "
   1880   1.1       scw 		    "%s. wr_offset %lld, wr_size %lld\n",
   1881  1.15    dyoung 		    device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state),
   1882   1.1       scw 		    sc->sc_wr_offset, sc->sc_wr_size));
   1883   1.1       scw 		break;
   1884   1.1       scw 
   1885   1.1       scw 	default:
   1886   1.1       scw 		DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n",
   1887  1.15    dyoung 		    device_xname(sc->sc_dev)));
   1888   1.1       scw 		err = ENODEV;
   1889   1.1       scw 		break;
   1890   1.1       scw 	}
   1891   1.1       scw 
   1892   1.1       scw 	DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n",
   1893  1.15    dyoung 	    device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
   1894   1.1       scw 
   1895   1.1       scw 	if (err)
   1896   1.1       scw 		utoppy_cancel(sc);
   1897   1.1       scw 
   1898   1.1       scw 	if (--sc->sc_refcnt < 0)
   1899  1.18       mrg 		usb_detach_wakeupold(sc->sc_dev);
   1900   1.1       scw 
   1901  1.25     skrll 	return err;
   1902   1.1       scw }
   1903