xref: /freebsd/sys/dev/usb/storage/urio.c (revision ca48e43ba9ee73a07cdbad8365117793b01273bb)
1  /*-
2   * SPDX-License-Identifier: BSD-2-Clause
3   *
4   * Copyright (c) 2000 Iwasa Kazmi
5   * All rights reserved.
6   *
7   * Redistribution and use in source and binary forms, with or without
8   * modification, are permitted provided that the following conditions
9   * are met:
10   * 1. Redistributions of source code must retain the above copyright
11   *    notice, this list of conditions, and the following disclaimer.
12   * 2. Redistributions in binary form must reproduce the above copyright
13   *    notice, this list of conditions and the following disclaimer in the
14   *    documentation and/or other materials provided with the distribution.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26   * SUCH DAMAGE.
27   *
28   * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
29   * This code includes software developed by the NetBSD Foundation, Inc. and
30   * its contributors.
31   */
32  
33  /*
34   * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
35   * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
36   * 2000/3/06  change major number(143), and copyright header
37   *            some fix for 4.0 (Dirk)
38   * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
39   * 2000/3/01  remove retry code from urioioctl()
40   *            change method of bulk transfer (no interrupt)
41   * 2000/2/28  small fixes for new rio_usb.h
42   * 2000/2/24  first version.
43   */
44  
45  #include <sys/stdint.h>
46  #include <sys/stddef.h>
47  #include <sys/param.h>
48  #include <sys/queue.h>
49  #include <sys/types.h>
50  #include <sys/systm.h>
51  #include <sys/kernel.h>
52  #include <sys/bus.h>
53  #include <sys/module.h>
54  #include <sys/lock.h>
55  #include <sys/mutex.h>
56  #include <sys/condvar.h>
57  #include <sys/sysctl.h>
58  #include <sys/sx.h>
59  #include <sys/unistd.h>
60  #include <sys/callout.h>
61  #include <sys/malloc.h>
62  #include <sys/priv.h>
63  #include <sys/conf.h>
64  #include <sys/fcntl.h>
65  
66  #include <dev/usb/usb.h>
67  #include <dev/usb/usbdi.h>
68  #include "usbdevs.h"
69  
70  #include <dev/usb/usb_ioctl.h>
71  #include <dev/usb/usb_generic.h>
72  
73  #define	USB_DEBUG_VAR urio_debug
74  #include <dev/usb/usb_debug.h>
75  
76  #include <dev/usb/storage/rio500_usb.h>
77  
78  #ifdef USB_DEBUG
79  static int urio_debug = 0;
80  
81  static SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
82      "USB urio");
83  SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RWTUN,
84      &urio_debug, 0, "urio debug level");
85  #endif
86  
87  #define	URIO_T_WR     0
88  #define	URIO_T_RD     1
89  #define	URIO_T_WR_CS  2
90  #define	URIO_T_RD_CS  3
91  #define	URIO_T_MAX    4
92  
93  #define	URIO_BSIZE	(1<<12)		/* bytes */
94  #define	URIO_IFQ_MAXLEN      2		/* units */
95  
96  struct urio_softc {
97  	struct usb_fifo_sc sc_fifo;
98  	struct mtx sc_mtx;
99  
100  	struct usb_device *sc_udev;
101  	struct usb_xfer *sc_xfer[URIO_T_MAX];
102  
103  	uint8_t	sc_flags;
104  #define	URIO_FLAG_READ_STALL    0x01	/* read transfer stalled */
105  #define	URIO_FLAG_WRITE_STALL   0x02	/* write transfer stalled */
106  
107  	uint8_t	sc_name[16];
108  };
109  
110  /* prototypes */
111  
112  static device_probe_t urio_probe;
113  static device_attach_t urio_attach;
114  static device_detach_t urio_detach;
115  
116  static usb_callback_t urio_write_callback;
117  static usb_callback_t urio_write_clear_stall_callback;
118  static usb_callback_t urio_read_callback;
119  static usb_callback_t urio_read_clear_stall_callback;
120  
121  static usb_fifo_close_t urio_close;
122  static usb_fifo_cmd_t urio_start_read;
123  static usb_fifo_cmd_t urio_start_write;
124  static usb_fifo_cmd_t urio_stop_read;
125  static usb_fifo_cmd_t urio_stop_write;
126  static usb_fifo_ioctl_t urio_ioctl;
127  static usb_fifo_open_t urio_open;
128  
129  static struct usb_fifo_methods urio_fifo_methods = {
130  	.f_close = &urio_close,
131  	.f_ioctl = &urio_ioctl,
132  	.f_open = &urio_open,
133  	.f_start_read = &urio_start_read,
134  	.f_start_write = &urio_start_write,
135  	.f_stop_read = &urio_stop_read,
136  	.f_stop_write = &urio_stop_write,
137  	.basename[0] = "urio",
138  };
139  
140  static const struct usb_config urio_config[URIO_T_MAX] = {
141  	[URIO_T_WR] = {
142  		.type = UE_BULK,
143  		.endpoint = UE_ADDR_ANY,
144  		.direction = UE_DIR_OUT,
145  		.bufsize = URIO_BSIZE,
146  		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
147  		.callback = &urio_write_callback,
148  	},
149  
150  	[URIO_T_RD] = {
151  		.type = UE_BULK,
152  		.endpoint = UE_ADDR_ANY,
153  		.direction = UE_DIR_IN,
154  		.bufsize = URIO_BSIZE,
155  		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
156  		.callback = &urio_read_callback,
157  	},
158  
159  	[URIO_T_WR_CS] = {
160  		.type = UE_CONTROL,
161  		.endpoint = 0x00,	/* Control pipe */
162  		.direction = UE_DIR_ANY,
163  		.bufsize = sizeof(struct usb_device_request),
164  		.callback = &urio_write_clear_stall_callback,
165  		.timeout = 1000,	/* 1 second */
166  		.interval = 50,	/* 50ms */
167  	},
168  
169  	[URIO_T_RD_CS] = {
170  		.type = UE_CONTROL,
171  		.endpoint = 0x00,	/* Control pipe */
172  		.direction = UE_DIR_ANY,
173  		.bufsize = sizeof(struct usb_device_request),
174  		.callback = &urio_read_clear_stall_callback,
175  		.timeout = 1000,	/* 1 second */
176  		.interval = 50,	/* 50ms */
177  	},
178  };
179  
180  static device_method_t urio_methods[] = {
181  	/* Device interface */
182  	DEVMETHOD(device_probe, urio_probe),
183  	DEVMETHOD(device_attach, urio_attach),
184  	DEVMETHOD(device_detach, urio_detach),
185  
186  	DEVMETHOD_END
187  };
188  
189  static driver_t urio_driver = {
190  	.name = "urio",
191  	.methods = urio_methods,
192  	.size = sizeof(struct urio_softc),
193  };
194  
195  static const STRUCT_USB_HOST_ID urio_devs[] = {
196  	{USB_VPI(USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB, 0)},
197  	{USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB, 0)},
198  	{USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB, 0)},
199  };
200  
201  DRIVER_MODULE(urio, uhub, urio_driver, NULL, NULL);
202  MODULE_DEPEND(urio, usb, 1, 1, 1);
203  MODULE_VERSION(urio, 1);
204  USB_PNP_HOST_INFO(urio_devs);
205  
206  static int
urio_probe(device_t dev)207  urio_probe(device_t dev)
208  {
209  	struct usb_attach_arg *uaa = device_get_ivars(dev);
210  
211  	if (uaa->usb_mode != USB_MODE_HOST)
212  		return (ENXIO);
213  	if (uaa->info.bConfigIndex != 0)
214  		return (ENXIO);
215  	if (uaa->info.bIfaceIndex != 0)
216  		return (ENXIO);
217  
218  	return (usbd_lookup_id_by_uaa(urio_devs, sizeof(urio_devs), uaa));
219  }
220  
221  static int
urio_attach(device_t dev)222  urio_attach(device_t dev)
223  {
224  	struct usb_attach_arg *uaa = device_get_ivars(dev);
225  	struct urio_softc *sc = device_get_softc(dev);
226  	int error;
227  
228  	device_set_usb_desc(dev);
229  
230  	sc->sc_udev = uaa->device;
231  
232  	mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE);
233  
234  	snprintf(sc->sc_name, sizeof(sc->sc_name),
235  	    "%s", device_get_nameunit(dev));
236  
237  	error = usbd_transfer_setup(uaa->device,
238  	    &uaa->info.bIfaceIndex, sc->sc_xfer,
239  	    urio_config, URIO_T_MAX, sc, &sc->sc_mtx);
240  
241  	if (error) {
242  		DPRINTF("error=%s\n", usbd_errstr(error));
243  		goto detach;
244  	}
245  
246  	error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
247  	    &urio_fifo_methods, &sc->sc_fifo,
248  	    device_get_unit(dev), -1, uaa->info.bIfaceIndex,
249  	    UID_ROOT, GID_OPERATOR, 0644);
250  	if (error) {
251  		goto detach;
252  	}
253  	return (0);			/* success */
254  
255  detach:
256  	urio_detach(dev);
257  	return (ENOMEM);		/* failure */
258  }
259  
260  static void
urio_write_callback(struct usb_xfer * xfer,usb_error_t error)261  urio_write_callback(struct usb_xfer *xfer, usb_error_t error)
262  {
263  	struct urio_softc *sc = usbd_xfer_softc(xfer);
264  	struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX];
265  	struct usb_page_cache *pc;
266  	uint32_t actlen;
267  
268  	switch (USB_GET_STATE(xfer)) {
269  	case USB_ST_TRANSFERRED:
270  	case USB_ST_SETUP:
271  		if (sc->sc_flags & URIO_FLAG_WRITE_STALL) {
272  			usbd_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
273  			return;
274  		}
275  		pc = usbd_xfer_get_frame(xfer, 0);
276  		if (usb_fifo_get_data(f, pc, 0,
277  		    usbd_xfer_max_len(xfer), &actlen, 0)) {
278  			usbd_xfer_set_frame_len(xfer, 0, actlen);
279  			usbd_transfer_submit(xfer);
280  		}
281  		return;
282  
283  	default:			/* Error */
284  		if (error != USB_ERR_CANCELLED) {
285  			/* try to clear stall first */
286  			sc->sc_flags |= URIO_FLAG_WRITE_STALL;
287  			usbd_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
288  		}
289  		return;
290  	}
291  }
292  
293  static void
urio_write_clear_stall_callback(struct usb_xfer * xfer,usb_error_t error)294  urio_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
295  {
296  	struct urio_softc *sc = usbd_xfer_softc(xfer);
297  	struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_WR];
298  
299  	if (usbd_clear_stall_callback(xfer, xfer_other)) {
300  		DPRINTF("stall cleared\n");
301  		sc->sc_flags &= ~URIO_FLAG_WRITE_STALL;
302  		usbd_transfer_start(xfer_other);
303  	}
304  }
305  
306  static void
urio_read_callback(struct usb_xfer * xfer,usb_error_t error)307  urio_read_callback(struct usb_xfer *xfer, usb_error_t error)
308  {
309  	struct urio_softc *sc = usbd_xfer_softc(xfer);
310  	struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
311  	struct usb_page_cache *pc;
312  	int actlen;
313  
314  	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
315  
316  	switch (USB_GET_STATE(xfer)) {
317  	case USB_ST_TRANSFERRED:
318  		pc = usbd_xfer_get_frame(xfer, 0);
319  		usb_fifo_put_data(f, pc, 0, actlen, 1);
320  
321  	case USB_ST_SETUP:
322  		if (sc->sc_flags & URIO_FLAG_READ_STALL) {
323  			usbd_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
324  			return;
325  		}
326  		if (usb_fifo_put_bytes_max(f) != 0) {
327  			usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
328  			usbd_transfer_submit(xfer);
329  		}
330  		return;
331  
332  	default:			/* Error */
333  		if (error != USB_ERR_CANCELLED) {
334  			/* try to clear stall first */
335  			sc->sc_flags |= URIO_FLAG_READ_STALL;
336  			usbd_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
337  		}
338  		return;
339  	}
340  }
341  
342  static void
urio_read_clear_stall_callback(struct usb_xfer * xfer,usb_error_t error)343  urio_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
344  {
345  	struct urio_softc *sc = usbd_xfer_softc(xfer);
346  	struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_RD];
347  
348  	if (usbd_clear_stall_callback(xfer, xfer_other)) {
349  		DPRINTF("stall cleared\n");
350  		sc->sc_flags &= ~URIO_FLAG_READ_STALL;
351  		usbd_transfer_start(xfer_other);
352  	}
353  }
354  
355  static void
urio_start_read(struct usb_fifo * fifo)356  urio_start_read(struct usb_fifo *fifo)
357  {
358  	struct urio_softc *sc = usb_fifo_softc(fifo);
359  
360  	usbd_transfer_start(sc->sc_xfer[URIO_T_RD]);
361  }
362  
363  static void
urio_stop_read(struct usb_fifo * fifo)364  urio_stop_read(struct usb_fifo *fifo)
365  {
366  	struct urio_softc *sc = usb_fifo_softc(fifo);
367  
368  	usbd_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]);
369  	usbd_transfer_stop(sc->sc_xfer[URIO_T_RD]);
370  }
371  
372  static void
urio_start_write(struct usb_fifo * fifo)373  urio_start_write(struct usb_fifo *fifo)
374  {
375  	struct urio_softc *sc = usb_fifo_softc(fifo);
376  
377  	usbd_transfer_start(sc->sc_xfer[URIO_T_WR]);
378  }
379  
380  static void
urio_stop_write(struct usb_fifo * fifo)381  urio_stop_write(struct usb_fifo *fifo)
382  {
383  	struct urio_softc *sc = usb_fifo_softc(fifo);
384  
385  	usbd_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]);
386  	usbd_transfer_stop(sc->sc_xfer[URIO_T_WR]);
387  }
388  
389  static int
urio_open(struct usb_fifo * fifo,int fflags)390  urio_open(struct usb_fifo *fifo, int fflags)
391  {
392  	struct urio_softc *sc = usb_fifo_softc(fifo);
393  
394  	if (fflags & FREAD) {
395  		/* clear stall first */
396  		mtx_lock(&sc->sc_mtx);
397  		sc->sc_flags |= URIO_FLAG_READ_STALL;
398  		mtx_unlock(&sc->sc_mtx);
399  
400  		if (usb_fifo_alloc_buffer(fifo,
401  		    usbd_xfer_max_len(sc->sc_xfer[URIO_T_RD]),
402  		    URIO_IFQ_MAXLEN)) {
403  			return (ENOMEM);
404  		}
405  	}
406  	if (fflags & FWRITE) {
407  		/* clear stall first */
408  		sc->sc_flags |= URIO_FLAG_WRITE_STALL;
409  
410  		if (usb_fifo_alloc_buffer(fifo,
411  		    usbd_xfer_max_len(sc->sc_xfer[URIO_T_WR]),
412  		    URIO_IFQ_MAXLEN)) {
413  			return (ENOMEM);
414  		}
415  	}
416  	return (0);			/* success */
417  }
418  
419  static void
urio_close(struct usb_fifo * fifo,int fflags)420  urio_close(struct usb_fifo *fifo, int fflags)
421  {
422  	if (fflags & (FREAD | FWRITE)) {
423  		usb_fifo_free_buffer(fifo);
424  	}
425  }
426  
427  static int
urio_ioctl(struct usb_fifo * fifo,u_long cmd,void * addr,int fflags)428  urio_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
429      int fflags)
430  {
431  	struct usb_ctl_request ur;
432  	struct RioCommand *rio_cmd;
433  	int error;
434  
435  	switch (cmd) {
436  	case RIO_RECV_COMMAND:
437  		if (!(fflags & FWRITE)) {
438  			error = EPERM;
439  			goto done;
440  		}
441  		memset(&ur, 0, sizeof(ur));
442  		rio_cmd = addr;
443  		ur.ucr_request.bmRequestType =
444  		    rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
445  		break;
446  
447  	case RIO_SEND_COMMAND:
448  		if (!(fflags & FWRITE)) {
449  			error = EPERM;
450  			goto done;
451  		}
452  		memset(&ur, 0, sizeof(ur));
453  		rio_cmd = addr;
454  		ur.ucr_request.bmRequestType =
455  		    rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
456  		break;
457  
458  	default:
459  		error = EINVAL;
460  		goto done;
461  	}
462  
463  	DPRINTFN(2, "Sending command\n");
464  
465  	/* Send rio control message */
466  	ur.ucr_request.bRequest = rio_cmd->request;
467  	USETW(ur.ucr_request.wValue, rio_cmd->value);
468  	USETW(ur.ucr_request.wIndex, rio_cmd->index);
469  	USETW(ur.ucr_request.wLength, rio_cmd->length);
470  	ur.ucr_data = rio_cmd->buffer;
471  
472  	/* reuse generic USB code */
473  	error = ugen_do_request(fifo, &ur);
474  
475  done:
476  	return (error);
477  }
478  
479  static int
urio_detach(device_t dev)480  urio_detach(device_t dev)
481  {
482  	struct urio_softc *sc = device_get_softc(dev);
483  
484  	DPRINTF("\n");
485  
486  	usb_fifo_detach(&sc->sc_fifo);
487  
488  	usbd_transfer_unsetup(sc->sc_xfer, URIO_T_MAX);
489  
490  	mtx_destroy(&sc->sc_mtx);
491  
492  	return (0);
493  }
494