urio.c revision 193045
16562Sphk/*-
237421Scharnier * Copyright (c) 2000 Iwasa Kazmi
36562Sphk * All rights reserved.
46562Sphk *
53995Spst * Redistribution and use in source and binary forms, with or without
63995Spst * modification, are permitted provided that the following conditions
76562Sphk * are met:
86562Sphk * 1. Redistributions of source code must retain the above copyright
96562Sphk *    notice, this list of conditions, and the following disclaimer.
106562Sphk * 2. Redistributions in binary form must reproduce the above copyright
116562Sphk *    notice, this list of conditions and the following disclaimer in the
126562Sphk *    documentation and/or other materials provided with the distribution.
136562Sphk *
146562Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156562Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166562Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176562Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
183995Spst * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193995Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20114589Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21114589Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2237421Scharnier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319168Sbde * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24110840Ssilby * SUCH DAMAGE.
25110840Ssilby *
2637421Scharnier * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
2719168Sbde * This code includes software developed by the NetBSD Foundation, Inc. and
28130351Seik * its contributors.
29130351Seik */
30143334Scperciva
313995Spst#include <sys/cdefs.h>
3278949Sdes__FBSDID("$FreeBSD: head/sys/dev/usb/storage/urio.c 193045 2009-05-29 18:46:57Z thompsa $");
3378949Sdes
343995Spst
3532074Ssteve/*
3619168Sbde * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
376562Sphk * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
386562Sphk * 2000/3/06  change major number(143), and copyright header
393995Spst *            some fix for 4.0 (Dirk)
4046226Skris * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
4146226Skris * 2000/3/01  remove retry code from urioioctl()
42130351Seik *            change method of bulk transfer (no interrupt)
433995Spst * 2000/2/28  small fixes for new rio_usb.h
4454109Sobrien * 2000/2/24  first version.
4552949Sobrien */
4688226Sphk
47229680Seadler#include "usbdevs.h"
48229680Seadler#include <dev/usb/usb.h>
4952949Sobrien#include <dev/usb/usb_mfunc.h>
50130351Seik#include <dev/usb/usb_error.h>
51130351Seik#include <dev/usb/usb_ioctl.h>
52130351Seik#include <dev/usb/storage/rio500_usb.h>
533995Spst
54130351Seik#define	USB_DEBUG_VAR urio_debug
55130351Seik
56143334Scperciva#include <dev/usb/usb_core.h>
57130351Seik#include <dev/usb/usb_debug.h>
58130351Seik#include <dev/usb/usb_process.h>
59130351Seik#include <dev/usb/usb_request.h>
60130351Seik#include <dev/usb/usb_lookup.h>
61130351Seik#include <dev/usb/usb_util.h>
62130351Seik#include <dev/usb/usb_busdma.h>
63130351Seik#include <dev/usb/usb_mbuf.h>
64130351Seik#include <dev/usb/usb_dev.h>
65130351Seik#include <dev/usb/usb_generic.h>
66154479Sphk
67130351Seik#if USB_DEBUG
68130351Seikstatic int urio_debug = 0;
69130351Seik
70130351SeikSYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio");
71130351SeikSYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW,
72130351Seik    &urio_debug, 0, "urio debug level");
73130351Seik#endif
74130351Seik
75130351Seik#define	URIO_T_WR     0
76130351Seik#define	URIO_T_RD     1
77130351Seik#define	URIO_T_WR_CS  2
78130351Seik#define	URIO_T_RD_CS  3
79130351Seik#define	URIO_T_MAX    4
80143334Scperciva
81130351Seik#define	URIO_BSIZE	(1<<12)		/* bytes */
82130351Seik#define	URIO_IFQ_MAXLEN      2		/* units */
83130351Seik
84176095Sobrienstruct urio_softc {
85239937Sdelphij	struct usb_fifo_sc sc_fifo;
86239937Sdelphij	struct mtx sc_mtx;
87130351Seik
88130351Seik	struct usb_device *sc_udev;
89130351Seik	struct usb_xfer *sc_xfer[URIO_T_MAX];
90130351Seik
91130351Seik	uint8_t	sc_flags;
92130351Seik#define	URIO_FLAG_READ_STALL    0x01	/* read transfer stalled */
93130351Seik#define	URIO_FLAG_WRITE_STALL   0x02	/* write transfer stalled */
94130351Seik
95130351Seik	uint8_t	sc_name[16];
96130351Seik};
97143334Scperciva
98143334Scperciva/* prototypes */
99143334Scperciva
100130351Seikstatic device_probe_t urio_probe;
101130351Seikstatic device_attach_t urio_attach;
102130351Seikstatic device_detach_t urio_detach;
103130351Seik
104130351Seikstatic usb_callback_t urio_write_callback;
105130351Seikstatic usb_callback_t urio_write_clear_stall_callback;
106130351Seikstatic usb_callback_t urio_read_callback;
107130351Seikstatic usb_callback_t urio_read_clear_stall_callback;
108130351Seik
109130351Seikstatic usb_fifo_close_t urio_close;
110130351Seikstatic usb_fifo_cmd_t urio_start_read;
1113995Spststatic usb_fifo_cmd_t urio_start_write;
1123995Spststatic usb_fifo_cmd_t urio_stop_read;
1133995Spststatic usb_fifo_cmd_t urio_stop_write;
1143995Spststatic usb_fifo_ioctl_t urio_ioctl;
1153995Spststatic usb_fifo_open_t urio_open;
1163995Spst
1173995Spststatic struct usb_fifo_methods urio_fifo_methods = {
1183995Spst	.f_close = &urio_close,
1193995Spst	.f_ioctl = &urio_ioctl,
1206562Sphk	.f_open = &urio_open,
12176988Sru	.f_start_read = &urio_start_read,
1223995Spst	.f_start_write = &urio_start_write,
123176095Sobrien	.f_stop_read = &urio_stop_read,
1246562Sphk	.f_stop_write = &urio_stop_write,
125130351Seik	.basename[0] = "urio",
126176095Sobrien};
127130351Seik
128130351Seikstatic const struct usb_config urio_config[URIO_T_MAX] = {
129176095Sobrien	[URIO_T_WR] = {
130130351Seik		.type = UE_BULK,
131130351Seik		.endpoint = UE_ADDR_ANY,
132130351Seik		.direction = UE_DIR_OUT,
133130351Seik		.bufsize = URIO_BSIZE,
134176095Sobrien		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
135130351Seik		.callback = &urio_write_callback,
136130351Seik	},
137130351Seik
138176095Sobrien	[URIO_T_RD] = {
139130918Seik		.type = UE_BULK,
140130351Seik		.endpoint = UE_ADDR_ANY,
1413995Spst		.direction = UE_DIR_IN,
142121914Sse		.bufsize = URIO_BSIZE,
143229680Seadler		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
144229680Seadler		.callback = &urio_read_callback,
145229680Seadler	},
14676988Sru
147229680Seadler	[URIO_T_WR_CS] = {
148229680Seadler		.type = UE_CONTROL,
149229680Seadler		.endpoint = 0x00,	/* Control pipe */
15076988Sru		.direction = UE_DIR_ANY,
151130351Seik		.bufsize = sizeof(struct usb_device_request),
15276988Sru		.callback = &urio_write_clear_stall_callback,
15376988Sru		.timeout = 1000,	/* 1 second */
15476988Sru		.interval = 50,	/* 50ms */
15576988Sru	},
15676988Sru
15776988Sru	[URIO_T_RD_CS] = {
15876988Sru		.type = UE_CONTROL,
15976988Sru		.endpoint = 0x00,	/* Control pipe */
16088226Sphk		.direction = UE_DIR_ANY,
161130351Seik		.bufsize = sizeof(struct usb_device_request),
16276988Sru		.callback = &urio_read_clear_stall_callback,
16376988Sru		.timeout = 1000,	/* 1 second */
164130351Seik		.interval = 50,	/* 50ms */
16576988Sru	},
16676988Sru};
167130351Seik
16876988Srustatic devclass_t urio_devclass;
16976988Sru
170130351Seikstatic device_method_t urio_methods[] = {
17132074Ssteve	/* Device interface */
17276988Sru	DEVMETHOD(device_probe, urio_probe),
17376988Sru	DEVMETHOD(device_attach, urio_attach),
17476988Sru	DEVMETHOD(device_detach, urio_detach),
17576988Sru	{0, 0}
17676988Sru};
177130351Seik
178121914Ssestatic driver_t urio_driver = {
17976988Sru	.name = "urio",
180121914Sse	.methods = urio_methods,
181121914Sse	.size = sizeof(struct urio_softc),
18254109Sobrien};
183229680Seadler
18454109SobrienDRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, NULL, 0);
185229680SeadlerMODULE_DEPEND(urio, usb, 1, 1, 1);
18652949Sobrien
187229680Seadlerstatic int
188176095Sobrienurio_probe(device_t dev)
189229680Seadler{
190229680Seadler	struct usb_attach_arg *uaa = device_get_ivars(dev);
191229680Seadler
192229680Seadler	if (uaa->usb_mode != USB_MODE_HOST) {
193229680Seadler		return (ENXIO);
194229680Seadler	}
195229680Seadler	if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) &&
196121914Sse	    (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) ||
19776988Sru	    ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) &&
19888226Sphk	    ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) ||
199130351Seik	    (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB)))))
2003995Spst		return (0);
201121914Sse	else
202121914Sse		return (ENXIO);
203229680Seadler}
204229680Seadler
205176095Sobrienstatic int
2066562Sphkurio_attach(device_t dev)
2073995Spst{
2086562Sphk	struct usb_attach_arg *uaa = device_get_ivars(dev);
2096562Sphk	struct urio_softc *sc = device_get_softc(dev);
2103995Spst	int error;
2116562Sphk
212130351Seik	device_set_usb2_desc(dev);
2133995Spst
21448953Sbillf	sc->sc_udev = uaa->device;
215130351Seik
2163995Spst	mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE);
217229680Seadler
21854109Sobrien	snprintf(sc->sc_name, sizeof(sc->sc_name),
219229680Seadler	    "%s", device_get_nameunit(dev));
22054109Sobrien
221229680Seadler	error = usb2_transfer_setup(uaa->device,
22252949Sobrien	    &uaa->info.bIfaceIndex, sc->sc_xfer,
223229680Seadler	    urio_config, URIO_T_MAX, sc, &sc->sc_mtx);
224229680Seadler
225229680Seadler	if (error) {
226229680Seadler		DPRINTF("error=%s\n", usb2_errstr(error));
227229680Seadler		goto detach;
228229680Seadler	}
229229680Seadler
230229680Seadler	error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
2313995Spst	    &urio_fifo_methods, &sc->sc_fifo,
2326562Sphk	    device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex,
2336562Sphk	    UID_ROOT, GID_OPERATOR, 0644);
2343995Spst	if (error) {
2356562Sphk		goto detach;
236130351Seik	}
2373995Spst	return (0);			/* success */
238130351Seik
239110840Ssilbydetach:
240110840Ssilby	urio_detach(dev);
241110840Ssilby	return (ENOMEM);		/* failure */
2426725Sphk}
2436562Sphk
244176095Sobrienstatic void
2453995Spsturio_write_callback(struct usb_xfer *xfer)
246176095Sobrien{
247130351Seik	struct urio_softc *sc = xfer->priv_sc;
24846226Skris	struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX];
2493995Spst	uint32_t actlen;
2506562Sphk
2516562Sphk	switch (USB_GET_STATE(xfer)) {
2526562Sphk	case USB_ST_TRANSFERRED:
2533995Spst	case USB_ST_SETUP:
2546562Sphk		if (sc->sc_flags & URIO_FLAG_WRITE_STALL) {
255182672Skevlo			usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
2563995Spst			return;
2576562Sphk		}
258130351Seik		if (usb2_fifo_get_data(f, xfer->frbuffers, 0,
2596562Sphk		    xfer->max_data_length, &actlen, 0)) {
260130351Seik
261130351Seik			xfer->frlengths[0] = actlen;
2623995Spst			usb2_start_hardware(xfer);
2636562Sphk		}
264182672Skevlo		return;
265110840Ssilby
266110840Ssilby	default:			/* Error */
2673995Spst		if (xfer->error != USB_ERR_CANCELLED) {
2686562Sphk			/* try to clear stall first */
2696562Sphk			sc->sc_flags |= URIO_FLAG_WRITE_STALL;
270110840Ssilby			usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]);
271176095Sobrien		}
272110840Ssilby		return;
2733995Spst	}
2746562Sphk}
2756562Sphk
2763995Spststatic void
277109870Ssilbyurio_write_clear_stall_callback(struct usb_xfer *xfer)
278130351Seik{
279176095Sobrien	struct urio_softc *sc = xfer->priv_sc;
280109870Ssilby	struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_WR];
281109870Ssilby
282109870Ssilby	if (usb2_clear_stall_callback(xfer, xfer_other)) {
283109870Ssilby		DPRINTF("stall cleared\n");
284109870Ssilby		sc->sc_flags &= ~URIO_FLAG_WRITE_STALL;
285109870Ssilby		usb2_transfer_start(xfer_other);
286130351Seik	}
287130351Seik}
288109870Ssilby
289109870Ssilbystatic void
290130351Seikurio_read_callback(struct usb_xfer *xfer)
291109870Ssilby{
292109870Ssilby	struct urio_softc *sc = xfer->priv_sc;
293109870Ssilby	struct usb_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX];
294109870Ssilby
295109870Ssilby	switch (USB_GET_STATE(xfer)) {
296109870Ssilby	case USB_ST_TRANSFERRED:
297109870Ssilby		usb2_fifo_put_data(f, xfer->frbuffers, 0,
298109870Ssilby		    xfer->actlen, 1);
299109870Ssilby
300109870Ssilby	case USB_ST_SETUP:
301130351Seik		if (sc->sc_flags & URIO_FLAG_READ_STALL) {
302130351Seik			usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
303130351Seik			return;
304130351Seik		}
305130351Seik		if (usb2_fifo_put_bytes_max(f) != 0) {
306130351Seik			xfer->frlengths[0] = xfer->max_data_length;
307130351Seik			usb2_start_hardware(xfer);
308130351Seik		}
309130351Seik		return;
310130351Seik
311130351Seik	default:			/* Error */
312143334Scperciva		if (xfer->error != USB_ERR_CANCELLED) {
313143334Scperciva			/* try to clear stall first */
314143334Scperciva			sc->sc_flags |= URIO_FLAG_READ_STALL;
315143334Scperciva			usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]);
316143334Scperciva		}
317143334Scperciva		return;
318143334Scperciva	}
319143334Scperciva}
320143334Scperciva
321143334Scpercivastatic void
322143334Scpercivaurio_read_clear_stall_callback(struct usb_xfer *xfer)
323130351Seik{
324130351Seik	struct urio_softc *sc = xfer->priv_sc;
325130351Seik	struct usb_xfer *xfer_other = sc->sc_xfer[URIO_T_RD];
326130351Seik
327130351Seik	if (usb2_clear_stall_callback(xfer, xfer_other)) {
328130351Seik		DPRINTF("stall cleared\n");
329130351Seik		sc->sc_flags &= ~URIO_FLAG_READ_STALL;
330130351Seik		usb2_transfer_start(xfer_other);
331130351Seik	}
332130351Seik}
333130351Seik
3346562Sphkstatic void
335130351Seikurio_start_read(struct usb_fifo *fifo)
3363995Spst{
337109870Ssilby	struct urio_softc *sc = fifo->priv_sc0;
338130351Seik
33932086Ssteve	usb2_transfer_start(sc->sc_xfer[URIO_T_RD]);
340130351Seik}
341130351Seik
342130351Seikstatic void
343130351Seikurio_stop_read(struct usb_fifo *fifo)
344130351Seik{
345109870Ssilby	struct urio_softc *sc = fifo->priv_sc0;
346109870Ssilby
347109870Ssilby	usb2_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]);
348109870Ssilby	usb2_transfer_stop(sc->sc_xfer[URIO_T_RD]);
3493995Spst}
3503995Spst
3516562Sphkstatic void
3526562Sphkurio_start_write(struct usb_fifo *fifo)
3533995Spst{
3546562Sphk	struct urio_softc *sc = fifo->priv_sc0;
355130351Seik
3563995Spst	usb2_transfer_start(sc->sc_xfer[URIO_T_WR]);
357130351Seik}
35876988Sru
35932074Sstevestatic void
360130351Seikurio_stop_write(struct usb_fifo *fifo)
3613995Spst{
362130351Seik	struct urio_softc *sc = fifo->priv_sc0;
36332074Ssteve
36476988Sru	usb2_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]);
36537421Scharnier	usb2_transfer_stop(sc->sc_xfer[URIO_T_WR]);
366130351Seik}
3676725Sphk
368130351Seikstatic int
3693995Spsturio_open(struct usb_fifo *fifo, int fflags)
37032074Ssteve{
37132074Ssteve	struct urio_softc *sc = fifo->priv_sc0;
372130351Seik
37332074Ssteve	if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) {
37432086Ssteve		return (EACCES);
375235309Seadler	}
37632074Ssteve	if (fflags & FREAD) {
37732074Ssteve		/* clear stall first */
378		mtx_lock(&sc->sc_mtx);
379		sc->sc_flags |= URIO_FLAG_READ_STALL;
380		mtx_unlock(&sc->sc_mtx);
381
382		if (usb2_fifo_alloc_buffer(fifo,
383		    sc->sc_xfer[URIO_T_RD]->max_data_length,
384		    URIO_IFQ_MAXLEN)) {
385			return (ENOMEM);
386		}
387	}
388	if (fflags & FWRITE) {
389		/* clear stall first */
390		sc->sc_flags |= URIO_FLAG_WRITE_STALL;
391
392		if (usb2_fifo_alloc_buffer(fifo,
393		    sc->sc_xfer[URIO_T_WR]->max_data_length,
394		    URIO_IFQ_MAXLEN)) {
395			return (ENOMEM);
396		}
397	}
398	return (0);			/* success */
399}
400
401static void
402urio_close(struct usb_fifo *fifo, int fflags)
403{
404	if (fflags & (FREAD | FWRITE)) {
405		usb2_fifo_free_buffer(fifo);
406	}
407}
408
409static int
410urio_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr,
411    int fflags)
412{
413	struct usb_ctl_request ur;
414	struct RioCommand *rio_cmd;
415	int error;
416
417	switch (cmd) {
418	case RIO_RECV_COMMAND:
419		if (!(fflags & FWRITE)) {
420			error = EPERM;
421			goto done;
422		}
423		bzero(&ur, sizeof(ur));
424		rio_cmd = addr;
425		ur.ucr_request.bmRequestType =
426		    rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
427		break;
428
429	case RIO_SEND_COMMAND:
430		if (!(fflags & FWRITE)) {
431			error = EPERM;
432			goto done;
433		}
434		bzero(&ur, sizeof(ur));
435		rio_cmd = addr;
436		ur.ucr_request.bmRequestType =
437		    rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
438		break;
439
440	default:
441		error = EINVAL;
442		goto done;
443	}
444
445	DPRINTFN(2, "Sending command\n");
446
447	/* Send rio control message */
448	ur.ucr_request.bRequest = rio_cmd->request;
449	USETW(ur.ucr_request.wValue, rio_cmd->value);
450	USETW(ur.ucr_request.wIndex, rio_cmd->index);
451	USETW(ur.ucr_request.wLength, rio_cmd->length);
452	ur.ucr_data = rio_cmd->buffer;
453
454	/* reuse generic USB code */
455	error = ugen_do_request(fifo, &ur);
456
457done:
458	return (error);
459}
460
461static int
462urio_detach(device_t dev)
463{
464	struct urio_softc *sc = device_get_softc(dev);
465
466	DPRINTF("\n");
467
468	usb2_fifo_detach(&sc->sc_fifo);
469
470	usb2_transfer_unsetup(sc->sc_xfer, URIO_T_MAX);
471
472	mtx_destroy(&sc->sc_mtx);
473
474	return (0);
475}
476