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