xref: /OK3568_Linux_fs/kernel/drivers/usb/misc/uss720.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*****************************************************************************/
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  *	uss720.c  --  USS720 USB Parport Cable.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *	Copyright (C) 1999, 2005, 2010
8*4882a593Smuzhiyun  *	    Thomas Sailer (t.sailer@alumni.ethz.ch)
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *  Based on parport_pc.c
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *  History:
13*4882a593Smuzhiyun  *   0.1  04.08.1999  Created
14*4882a593Smuzhiyun  *   0.2  07.08.1999  Some fixes mainly suggested by Tim Waugh
15*4882a593Smuzhiyun  *		      Interrupt handling currently disabled because
16*4882a593Smuzhiyun  *		      usb_request_irq crashes somewhere within ohci.c
17*4882a593Smuzhiyun  *		      for no apparent reason (that is for me, anyway)
18*4882a593Smuzhiyun  *		      ECP currently untested
19*4882a593Smuzhiyun  *   0.3  10.08.1999  fixing merge errors
20*4882a593Smuzhiyun  *   0.4  13.08.1999  Added Vendor/Product ID of Brad Hard's cable
21*4882a593Smuzhiyun  *   0.5  20.09.1999  usb_control_msg wrapper used
22*4882a593Smuzhiyun  *        Nov01.2000  usb_device_table support by Adam J. Richter
23*4882a593Smuzhiyun  *        08.04.2001  Identify version on module load.  gb
24*4882a593Smuzhiyun  *   0.6  02.09.2005  Fix "scheduling in interrupt" problem by making save/restore
25*4882a593Smuzhiyun  *                    context asynchronous
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  */
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*****************************************************************************/
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <linux/module.h>
32*4882a593Smuzhiyun #include <linux/socket.h>
33*4882a593Smuzhiyun #include <linux/parport.h>
34*4882a593Smuzhiyun #include <linux/init.h>
35*4882a593Smuzhiyun #include <linux/usb.h>
36*4882a593Smuzhiyun #include <linux/delay.h>
37*4882a593Smuzhiyun #include <linux/completion.h>
38*4882a593Smuzhiyun #include <linux/kref.h>
39*4882a593Smuzhiyun #include <linux/slab.h>
40*4882a593Smuzhiyun #include <linux/sched/signal.h>
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #define DRIVER_AUTHOR "Thomas M. Sailer, t.sailer@alumni.ethz.ch"
43*4882a593Smuzhiyun #define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun struct parport_uss720_private {
48*4882a593Smuzhiyun 	struct usb_device *usbdev;
49*4882a593Smuzhiyun 	struct parport *pp;
50*4882a593Smuzhiyun 	struct kref ref_count;
51*4882a593Smuzhiyun 	__u8 reg[7];  /* USB registers */
52*4882a593Smuzhiyun 	struct list_head asynclist;
53*4882a593Smuzhiyun 	spinlock_t asynclock;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun struct uss720_async_request {
57*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
58*4882a593Smuzhiyun 	struct kref ref_count;
59*4882a593Smuzhiyun 	struct list_head asynclist;
60*4882a593Smuzhiyun 	struct completion compl;
61*4882a593Smuzhiyun 	struct urb *urb;
62*4882a593Smuzhiyun 	struct usb_ctrlrequest *dr;
63*4882a593Smuzhiyun 	__u8 reg[7];
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
67*4882a593Smuzhiyun 
destroy_priv(struct kref * kref)68*4882a593Smuzhiyun static void destroy_priv(struct kref *kref)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	struct parport_uss720_private *priv = container_of(kref, struct parport_uss720_private, ref_count);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	dev_dbg(&priv->usbdev->dev, "destroying priv datastructure\n");
73*4882a593Smuzhiyun 	usb_put_dev(priv->usbdev);
74*4882a593Smuzhiyun 	priv->usbdev = NULL;
75*4882a593Smuzhiyun 	kfree(priv);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
destroy_async(struct kref * kref)78*4882a593Smuzhiyun static void destroy_async(struct kref *kref)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	struct uss720_async_request *rq = container_of(kref, struct uss720_async_request, ref_count);
81*4882a593Smuzhiyun 	struct parport_uss720_private *priv = rq->priv;
82*4882a593Smuzhiyun 	unsigned long flags;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (likely(rq->urb))
85*4882a593Smuzhiyun 		usb_free_urb(rq->urb);
86*4882a593Smuzhiyun 	kfree(rq->dr);
87*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->asynclock, flags);
88*4882a593Smuzhiyun 	list_del_init(&rq->asynclist);
89*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->asynclock, flags);
90*4882a593Smuzhiyun 	kfree(rq);
91*4882a593Smuzhiyun 	kref_put(&priv->ref_count, destroy_priv);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
95*4882a593Smuzhiyun 
async_complete(struct urb * urb)96*4882a593Smuzhiyun static void async_complete(struct urb *urb)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	struct uss720_async_request *rq;
99*4882a593Smuzhiyun 	struct parport *pp;
100*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
101*4882a593Smuzhiyun 	int status = urb->status;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	rq = urb->context;
104*4882a593Smuzhiyun 	priv = rq->priv;
105*4882a593Smuzhiyun 	pp = priv->pp;
106*4882a593Smuzhiyun 	if (status) {
107*4882a593Smuzhiyun 		dev_err(&urb->dev->dev, "async_complete: urb error %d\n",
108*4882a593Smuzhiyun 			status);
109*4882a593Smuzhiyun 	} else if (rq->dr->bRequest == 3) {
110*4882a593Smuzhiyun 		memcpy(priv->reg, rq->reg, sizeof(priv->reg));
111*4882a593Smuzhiyun #if 0
112*4882a593Smuzhiyun 		dev_dbg(&priv->usbdev->dev, "async_complete regs %7ph\n",
113*4882a593Smuzhiyun 			priv->reg);
114*4882a593Smuzhiyun #endif
115*4882a593Smuzhiyun 		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
116*4882a593Smuzhiyun 		if (rq->reg[2] & rq->reg[1] & 0x10 && pp)
117*4882a593Smuzhiyun 			parport_generic_irq(pp);
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 	complete(&rq->compl);
120*4882a593Smuzhiyun 	kref_put(&rq->ref_count, destroy_async);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
submit_async_request(struct parport_uss720_private * priv,__u8 request,__u8 requesttype,__u16 value,__u16 index,gfp_t mem_flags)123*4882a593Smuzhiyun static struct uss720_async_request *submit_async_request(struct parport_uss720_private *priv,
124*4882a593Smuzhiyun 							 __u8 request, __u8 requesttype, __u16 value, __u16 index,
125*4882a593Smuzhiyun 							 gfp_t mem_flags)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	struct usb_device *usbdev;
128*4882a593Smuzhiyun 	struct uss720_async_request *rq;
129*4882a593Smuzhiyun 	unsigned long flags;
130*4882a593Smuzhiyun 	int ret;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	if (!priv)
133*4882a593Smuzhiyun 		return NULL;
134*4882a593Smuzhiyun 	usbdev = priv->usbdev;
135*4882a593Smuzhiyun 	if (!usbdev)
136*4882a593Smuzhiyun 		return NULL;
137*4882a593Smuzhiyun 	rq = kzalloc(sizeof(struct uss720_async_request), mem_flags);
138*4882a593Smuzhiyun 	if (!rq)
139*4882a593Smuzhiyun 		return NULL;
140*4882a593Smuzhiyun 	kref_init(&rq->ref_count);
141*4882a593Smuzhiyun 	INIT_LIST_HEAD(&rq->asynclist);
142*4882a593Smuzhiyun 	init_completion(&rq->compl);
143*4882a593Smuzhiyun 	kref_get(&priv->ref_count);
144*4882a593Smuzhiyun 	rq->priv = priv;
145*4882a593Smuzhiyun 	rq->urb = usb_alloc_urb(0, mem_flags);
146*4882a593Smuzhiyun 	if (!rq->urb) {
147*4882a593Smuzhiyun 		kref_put(&rq->ref_count, destroy_async);
148*4882a593Smuzhiyun 		return NULL;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 	rq->dr = kmalloc(sizeof(*rq->dr), mem_flags);
151*4882a593Smuzhiyun 	if (!rq->dr) {
152*4882a593Smuzhiyun 		kref_put(&rq->ref_count, destroy_async);
153*4882a593Smuzhiyun 		return NULL;
154*4882a593Smuzhiyun 	}
155*4882a593Smuzhiyun 	rq->dr->bRequestType = requesttype;
156*4882a593Smuzhiyun 	rq->dr->bRequest = request;
157*4882a593Smuzhiyun 	rq->dr->wValue = cpu_to_le16(value);
158*4882a593Smuzhiyun 	rq->dr->wIndex = cpu_to_le16(index);
159*4882a593Smuzhiyun 	rq->dr->wLength = cpu_to_le16((request == 3) ? sizeof(rq->reg) : 0);
160*4882a593Smuzhiyun 	usb_fill_control_urb(rq->urb, usbdev, (requesttype & 0x80) ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0),
161*4882a593Smuzhiyun 			     (unsigned char *)rq->dr,
162*4882a593Smuzhiyun 			     (request == 3) ? rq->reg : NULL, (request == 3) ? sizeof(rq->reg) : 0, async_complete, rq);
163*4882a593Smuzhiyun 	/* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
164*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->asynclock, flags);
165*4882a593Smuzhiyun 	list_add_tail(&rq->asynclist, &priv->asynclist);
166*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->asynclock, flags);
167*4882a593Smuzhiyun 	kref_get(&rq->ref_count);
168*4882a593Smuzhiyun 	ret = usb_submit_urb(rq->urb, mem_flags);
169*4882a593Smuzhiyun 	if (!ret)
170*4882a593Smuzhiyun 		return rq;
171*4882a593Smuzhiyun 	destroy_async(&rq->ref_count);
172*4882a593Smuzhiyun 	dev_err(&usbdev->dev, "submit_async_request submit_urb failed with %d\n", ret);
173*4882a593Smuzhiyun 	return NULL;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
kill_all_async_requests_priv(struct parport_uss720_private * priv)176*4882a593Smuzhiyun static unsigned int kill_all_async_requests_priv(struct parport_uss720_private *priv)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct uss720_async_request *rq;
179*4882a593Smuzhiyun 	unsigned long flags;
180*4882a593Smuzhiyun 	unsigned int ret = 0;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	spin_lock_irqsave(&priv->asynclock, flags);
183*4882a593Smuzhiyun 	list_for_each_entry(rq, &priv->asynclist, asynclist) {
184*4882a593Smuzhiyun 		usb_unlink_urb(rq->urb);
185*4882a593Smuzhiyun 		ret++;
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 	spin_unlock_irqrestore(&priv->asynclock, flags);
188*4882a593Smuzhiyun 	return ret;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
192*4882a593Smuzhiyun 
get_1284_register(struct parport * pp,unsigned char reg,unsigned char * val,gfp_t mem_flags)193*4882a593Smuzhiyun static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val, gfp_t mem_flags)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
196*4882a593Smuzhiyun 	struct uss720_async_request *rq;
197*4882a593Smuzhiyun 	static const unsigned char regindex[9] = {
198*4882a593Smuzhiyun 		4, 0, 1, 5, 5, 0, 2, 3, 6
199*4882a593Smuzhiyun 	};
200*4882a593Smuzhiyun 	int ret;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	if (!pp)
203*4882a593Smuzhiyun 		return -EIO;
204*4882a593Smuzhiyun 	priv = pp->private_data;
205*4882a593Smuzhiyun 	rq = submit_async_request(priv, 3, 0xc0, ((unsigned int)reg) << 8, 0, mem_flags);
206*4882a593Smuzhiyun 	if (!rq) {
207*4882a593Smuzhiyun 		dev_err(&priv->usbdev->dev, "get_1284_register(%u) failed",
208*4882a593Smuzhiyun 			(unsigned int)reg);
209*4882a593Smuzhiyun 		return -EIO;
210*4882a593Smuzhiyun 	}
211*4882a593Smuzhiyun 	if (!val) {
212*4882a593Smuzhiyun 		kref_put(&rq->ref_count, destroy_async);
213*4882a593Smuzhiyun 		return 0;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun 	if (wait_for_completion_timeout(&rq->compl, HZ)) {
216*4882a593Smuzhiyun 		ret = rq->urb->status;
217*4882a593Smuzhiyun 		*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
218*4882a593Smuzhiyun 		if (ret)
219*4882a593Smuzhiyun 			printk(KERN_WARNING "get_1284_register: "
220*4882a593Smuzhiyun 			       "usb error %d\n", ret);
221*4882a593Smuzhiyun 		kref_put(&rq->ref_count, destroy_async);
222*4882a593Smuzhiyun 		return ret;
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 	printk(KERN_WARNING "get_1284_register timeout\n");
225*4882a593Smuzhiyun 	kill_all_async_requests_priv(priv);
226*4882a593Smuzhiyun 	return -EIO;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
set_1284_register(struct parport * pp,unsigned char reg,unsigned char val,gfp_t mem_flags)229*4882a593Smuzhiyun static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val, gfp_t mem_flags)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
232*4882a593Smuzhiyun 	struct uss720_async_request *rq;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (!pp)
235*4882a593Smuzhiyun 		return -EIO;
236*4882a593Smuzhiyun 	priv = pp->private_data;
237*4882a593Smuzhiyun 	rq = submit_async_request(priv, 4, 0x40, (((unsigned int)reg) << 8) | val, 0, mem_flags);
238*4882a593Smuzhiyun 	if (!rq) {
239*4882a593Smuzhiyun 		dev_err(&priv->usbdev->dev, "set_1284_register(%u,%u) failed",
240*4882a593Smuzhiyun 			(unsigned int)reg, (unsigned int)val);
241*4882a593Smuzhiyun 		return -EIO;
242*4882a593Smuzhiyun 	}
243*4882a593Smuzhiyun 	kref_put(&rq->ref_count, destroy_async);
244*4882a593Smuzhiyun 	return 0;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun /* ECR modes */
250*4882a593Smuzhiyun #define ECR_SPP 00
251*4882a593Smuzhiyun #define ECR_PS2 01
252*4882a593Smuzhiyun #define ECR_PPF 02
253*4882a593Smuzhiyun #define ECR_ECP 03
254*4882a593Smuzhiyun #define ECR_EPP 04
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /* Safely change the mode bits in the ECR */
change_mode(struct parport * pp,int m)257*4882a593Smuzhiyun static int change_mode(struct parport *pp, int m)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
260*4882a593Smuzhiyun 	int mode;
261*4882a593Smuzhiyun 	__u8 reg;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
264*4882a593Smuzhiyun 		return -EIO;
265*4882a593Smuzhiyun 	/* Bits <7:5> contain the mode. */
266*4882a593Smuzhiyun 	mode = (priv->reg[2] >> 5) & 0x7;
267*4882a593Smuzhiyun 	if (mode == m)
268*4882a593Smuzhiyun 		return 0;
269*4882a593Smuzhiyun 	/* We have to go through mode 000 or 001 */
270*4882a593Smuzhiyun 	if (mode > ECR_PS2 && m > ECR_PS2)
271*4882a593Smuzhiyun 		if (change_mode(pp, ECR_PS2))
272*4882a593Smuzhiyun 			return -EIO;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) {
275*4882a593Smuzhiyun 		/* This mode resets the FIFO, so we may
276*4882a593Smuzhiyun 		 * have to wait for it to drain first. */
277*4882a593Smuzhiyun 		unsigned long expire = jiffies + pp->physport->cad->timeout;
278*4882a593Smuzhiyun 		switch (mode) {
279*4882a593Smuzhiyun 		case ECR_PPF: /* Parallel Port FIFO mode */
280*4882a593Smuzhiyun 		case ECR_ECP: /* ECP Parallel Port mode */
281*4882a593Smuzhiyun 			/* Poll slowly. */
282*4882a593Smuzhiyun 			for (;;) {
283*4882a593Smuzhiyun 				if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
284*4882a593Smuzhiyun 					return -EIO;
285*4882a593Smuzhiyun 				if (priv->reg[2] & 0x01)
286*4882a593Smuzhiyun 					break;
287*4882a593Smuzhiyun 				if (time_after_eq (jiffies, expire))
288*4882a593Smuzhiyun 					/* The FIFO is stuck. */
289*4882a593Smuzhiyun 					return -EBUSY;
290*4882a593Smuzhiyun 				msleep_interruptible(10);
291*4882a593Smuzhiyun 				if (signal_pending (current))
292*4882a593Smuzhiyun 					break;
293*4882a593Smuzhiyun 			}
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 	/* Set the mode. */
297*4882a593Smuzhiyun 	if (set_1284_register(pp, 6, m << 5, GFP_KERNEL))
298*4882a593Smuzhiyun 		return -EIO;
299*4882a593Smuzhiyun 	if (get_1284_register(pp, 6, &reg, GFP_KERNEL))
300*4882a593Smuzhiyun 		return -EIO;
301*4882a593Smuzhiyun 	return 0;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun /*
305*4882a593Smuzhiyun  * Clear TIMEOUT BIT in EPP MODE
306*4882a593Smuzhiyun  */
clear_epp_timeout(struct parport * pp)307*4882a593Smuzhiyun static int clear_epp_timeout(struct parport *pp)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	unsigned char stat;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if (get_1284_register(pp, 1, &stat, GFP_KERNEL))
312*4882a593Smuzhiyun 		return 1;
313*4882a593Smuzhiyun 	return stat & 1;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun /*
317*4882a593Smuzhiyun  * Access functions.
318*4882a593Smuzhiyun  */
319*4882a593Smuzhiyun #if 0
320*4882a593Smuzhiyun static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct parport *pp = (struct parport *)dev_id;
323*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (usbstatus != 0 || len < 4 || !buffer)
326*4882a593Smuzhiyun 		return 1;
327*4882a593Smuzhiyun 	memcpy(priv->reg, buffer, 4);
328*4882a593Smuzhiyun 	/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
329*4882a593Smuzhiyun 	if (priv->reg[2] & priv->reg[1] & 0x10)
330*4882a593Smuzhiyun 		parport_generic_irq(pp);
331*4882a593Smuzhiyun 	return 1;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun #endif
334*4882a593Smuzhiyun 
parport_uss720_write_data(struct parport * pp,unsigned char d)335*4882a593Smuzhiyun static void parport_uss720_write_data(struct parport *pp, unsigned char d)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	set_1284_register(pp, 0, d, GFP_KERNEL);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
parport_uss720_read_data(struct parport * pp)340*4882a593Smuzhiyun static unsigned char parport_uss720_read_data(struct parport *pp)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	unsigned char ret;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	if (get_1284_register(pp, 0, &ret, GFP_KERNEL))
345*4882a593Smuzhiyun 		return 0;
346*4882a593Smuzhiyun 	return ret;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
parport_uss720_write_control(struct parport * pp,unsigned char d)349*4882a593Smuzhiyun static void parport_uss720_write_control(struct parport *pp, unsigned char d)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	d = (d & 0xf) | (priv->reg[1] & 0xf0);
354*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_KERNEL))
355*4882a593Smuzhiyun 		return;
356*4882a593Smuzhiyun 	priv->reg[1] = d;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
parport_uss720_read_control(struct parport * pp)359*4882a593Smuzhiyun static unsigned char parport_uss720_read_control(struct parport *pp)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
362*4882a593Smuzhiyun 	return priv->reg[1] & 0xf; /* Use soft copy */
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
parport_uss720_frob_control(struct parport * pp,unsigned char mask,unsigned char val)365*4882a593Smuzhiyun static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
368*4882a593Smuzhiyun 	unsigned char d;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	mask &= 0x0f;
371*4882a593Smuzhiyun 	val &= 0x0f;
372*4882a593Smuzhiyun 	d = (priv->reg[1] & (~mask)) ^ val;
373*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_ATOMIC))
374*4882a593Smuzhiyun 		return 0;
375*4882a593Smuzhiyun 	priv->reg[1] = d;
376*4882a593Smuzhiyun 	return d & 0xf;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
parport_uss720_read_status(struct parport * pp)379*4882a593Smuzhiyun static unsigned char parport_uss720_read_status(struct parport *pp)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	unsigned char ret;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (get_1284_register(pp, 1, &ret, GFP_ATOMIC))
384*4882a593Smuzhiyun 		return 0;
385*4882a593Smuzhiyun 	return ret & 0xf8;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
parport_uss720_disable_irq(struct parport * pp)388*4882a593Smuzhiyun static void parport_uss720_disable_irq(struct parport *pp)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
391*4882a593Smuzhiyun 	unsigned char d;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	d = priv->reg[1] & ~0x10;
394*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_KERNEL))
395*4882a593Smuzhiyun 		return;
396*4882a593Smuzhiyun 	priv->reg[1] = d;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
parport_uss720_enable_irq(struct parport * pp)399*4882a593Smuzhiyun static void parport_uss720_enable_irq(struct parport *pp)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
402*4882a593Smuzhiyun 	unsigned char d;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	d = priv->reg[1] | 0x10;
405*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_KERNEL))
406*4882a593Smuzhiyun 		return;
407*4882a593Smuzhiyun 	priv->reg[1] = d;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
parport_uss720_data_forward(struct parport * pp)410*4882a593Smuzhiyun static void parport_uss720_data_forward (struct parport *pp)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
413*4882a593Smuzhiyun 	unsigned char d;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	d = priv->reg[1] & ~0x20;
416*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_KERNEL))
417*4882a593Smuzhiyun 		return;
418*4882a593Smuzhiyun 	priv->reg[1] = d;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun 
parport_uss720_data_reverse(struct parport * pp)421*4882a593Smuzhiyun static void parport_uss720_data_reverse (struct parport *pp)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
424*4882a593Smuzhiyun 	unsigned char d;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	d = priv->reg[1] | 0x20;
427*4882a593Smuzhiyun 	if (set_1284_register(pp, 2, d, GFP_KERNEL))
428*4882a593Smuzhiyun 		return;
429*4882a593Smuzhiyun 	priv->reg[1] = d;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
parport_uss720_init_state(struct pardevice * dev,struct parport_state * s)432*4882a593Smuzhiyun static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
435*4882a593Smuzhiyun 	s->u.pc.ecr = 0x24;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
parport_uss720_save_state(struct parport * pp,struct parport_state * s)438*4882a593Smuzhiyun static void parport_uss720_save_state(struct parport *pp, struct parport_state *s)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun #if 0
443*4882a593Smuzhiyun 	if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
444*4882a593Smuzhiyun 		return;
445*4882a593Smuzhiyun #endif
446*4882a593Smuzhiyun 	s->u.pc.ctr = priv->reg[1];
447*4882a593Smuzhiyun 	s->u.pc.ecr = priv->reg[2];
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
parport_uss720_restore_state(struct parport * pp,struct parport_state * s)450*4882a593Smuzhiyun static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	set_1284_register(pp, 2, s->u.pc.ctr, GFP_ATOMIC);
455*4882a593Smuzhiyun 	set_1284_register(pp, 6, s->u.pc.ecr, GFP_ATOMIC);
456*4882a593Smuzhiyun 	get_1284_register(pp, 2, NULL, GFP_ATOMIC);
457*4882a593Smuzhiyun 	priv->reg[1] = s->u.pc.ctr;
458*4882a593Smuzhiyun 	priv->reg[2] = s->u.pc.ecr;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
parport_uss720_epp_read_data(struct parport * pp,void * buf,size_t length,int flags)461*4882a593Smuzhiyun static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
464*4882a593Smuzhiyun 	size_t got = 0;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	if (change_mode(pp, ECR_EPP))
467*4882a593Smuzhiyun 		return 0;
468*4882a593Smuzhiyun 	for (; got < length; got++) {
469*4882a593Smuzhiyun 		if (get_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
470*4882a593Smuzhiyun 			break;
471*4882a593Smuzhiyun 		buf++;
472*4882a593Smuzhiyun 		if (priv->reg[0] & 0x01) {
473*4882a593Smuzhiyun 			clear_epp_timeout(pp);
474*4882a593Smuzhiyun 			break;
475*4882a593Smuzhiyun 		}
476*4882a593Smuzhiyun 	}
477*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
478*4882a593Smuzhiyun 	return got;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
parport_uss720_epp_write_data(struct parport * pp,const void * buf,size_t length,int flags)481*4882a593Smuzhiyun static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun #if 0
484*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
485*4882a593Smuzhiyun 	size_t written = 0;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	if (change_mode(pp, ECR_EPP))
488*4882a593Smuzhiyun 		return 0;
489*4882a593Smuzhiyun 	for (; written < length; written++) {
490*4882a593Smuzhiyun 		if (set_1284_register(pp, 4, (char *)buf, GFP_KERNEL))
491*4882a593Smuzhiyun 			break;
492*4882a593Smuzhiyun 		((char*)buf)++;
493*4882a593Smuzhiyun 		if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
494*4882a593Smuzhiyun 			break;
495*4882a593Smuzhiyun 		if (priv->reg[0] & 0x01) {
496*4882a593Smuzhiyun 			clear_epp_timeout(pp);
497*4882a593Smuzhiyun 			break;
498*4882a593Smuzhiyun 		}
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
501*4882a593Smuzhiyun 	return written;
502*4882a593Smuzhiyun #else
503*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
504*4882a593Smuzhiyun 	struct usb_device *usbdev = priv->usbdev;
505*4882a593Smuzhiyun 	int rlen;
506*4882a593Smuzhiyun 	int i;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	if (!usbdev)
509*4882a593Smuzhiyun 		return 0;
510*4882a593Smuzhiyun 	if (change_mode(pp, ECR_EPP))
511*4882a593Smuzhiyun 		return 0;
512*4882a593Smuzhiyun 	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, 20000);
513*4882a593Smuzhiyun 	if (i)
514*4882a593Smuzhiyun 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %zu rlen %u\n", buf, length, rlen);
515*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
516*4882a593Smuzhiyun 	return rlen;
517*4882a593Smuzhiyun #endif
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
parport_uss720_epp_read_addr(struct parport * pp,void * buf,size_t length,int flags)520*4882a593Smuzhiyun static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
523*4882a593Smuzhiyun 	size_t got = 0;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	if (change_mode(pp, ECR_EPP))
526*4882a593Smuzhiyun 		return 0;
527*4882a593Smuzhiyun 	for (; got < length; got++) {
528*4882a593Smuzhiyun 		if (get_1284_register(pp, 3, (char *)buf, GFP_KERNEL))
529*4882a593Smuzhiyun 			break;
530*4882a593Smuzhiyun 		buf++;
531*4882a593Smuzhiyun 		if (priv->reg[0] & 0x01) {
532*4882a593Smuzhiyun 			clear_epp_timeout(pp);
533*4882a593Smuzhiyun 			break;
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 	}
536*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
537*4882a593Smuzhiyun 	return got;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun 
parport_uss720_epp_write_addr(struct parport * pp,const void * buf,size_t length,int flags)540*4882a593Smuzhiyun static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
543*4882a593Smuzhiyun 	size_t written = 0;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	if (change_mode(pp, ECR_EPP))
546*4882a593Smuzhiyun 		return 0;
547*4882a593Smuzhiyun 	for (; written < length; written++) {
548*4882a593Smuzhiyun 		if (set_1284_register(pp, 3, *(char *)buf, GFP_KERNEL))
549*4882a593Smuzhiyun 			break;
550*4882a593Smuzhiyun 		buf++;
551*4882a593Smuzhiyun 		if (get_1284_register(pp, 1, NULL, GFP_KERNEL))
552*4882a593Smuzhiyun 			break;
553*4882a593Smuzhiyun 		if (priv->reg[0] & 0x01) {
554*4882a593Smuzhiyun 			clear_epp_timeout(pp);
555*4882a593Smuzhiyun 			break;
556*4882a593Smuzhiyun 		}
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
559*4882a593Smuzhiyun 	return written;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
parport_uss720_ecp_write_data(struct parport * pp,const void * buffer,size_t len,int flags)562*4882a593Smuzhiyun static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
565*4882a593Smuzhiyun 	struct usb_device *usbdev = priv->usbdev;
566*4882a593Smuzhiyun 	int rlen;
567*4882a593Smuzhiyun 	int i;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	if (!usbdev)
570*4882a593Smuzhiyun 		return 0;
571*4882a593Smuzhiyun 	if (change_mode(pp, ECR_ECP))
572*4882a593Smuzhiyun 		return 0;
573*4882a593Smuzhiyun 	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
574*4882a593Smuzhiyun 	if (i)
575*4882a593Smuzhiyun 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %zu rlen %u\n", buffer, len, rlen);
576*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
577*4882a593Smuzhiyun 	return rlen;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun 
parport_uss720_ecp_read_data(struct parport * pp,void * buffer,size_t len,int flags)580*4882a593Smuzhiyun static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
583*4882a593Smuzhiyun 	struct usb_device *usbdev = priv->usbdev;
584*4882a593Smuzhiyun 	int rlen;
585*4882a593Smuzhiyun 	int i;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	if (!usbdev)
588*4882a593Smuzhiyun 		return 0;
589*4882a593Smuzhiyun 	if (change_mode(pp, ECR_ECP))
590*4882a593Smuzhiyun 		return 0;
591*4882a593Smuzhiyun 	i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, 20000);
592*4882a593Smuzhiyun 	if (i)
593*4882a593Smuzhiyun 		printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %zu rlen %u\n", buffer, len, rlen);
594*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
595*4882a593Smuzhiyun 	return rlen;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun 
parport_uss720_ecp_write_addr(struct parport * pp,const void * buffer,size_t len,int flags)598*4882a593Smuzhiyun static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	size_t written = 0;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	if (change_mode(pp, ECR_ECP))
603*4882a593Smuzhiyun 		return 0;
604*4882a593Smuzhiyun 	for (; written < len; written++) {
605*4882a593Smuzhiyun 		if (set_1284_register(pp, 5, *(char *)buffer, GFP_KERNEL))
606*4882a593Smuzhiyun 			break;
607*4882a593Smuzhiyun 		buffer++;
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
610*4882a593Smuzhiyun 	return written;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun 
parport_uss720_write_compat(struct parport * pp,const void * buffer,size_t len,int flags)613*4882a593Smuzhiyun static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags)
614*4882a593Smuzhiyun {
615*4882a593Smuzhiyun 	struct parport_uss720_private *priv = pp->private_data;
616*4882a593Smuzhiyun 	struct usb_device *usbdev = priv->usbdev;
617*4882a593Smuzhiyun 	int rlen;
618*4882a593Smuzhiyun 	int i;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	if (!usbdev)
621*4882a593Smuzhiyun 		return 0;
622*4882a593Smuzhiyun 	if (change_mode(pp, ECR_PPF))
623*4882a593Smuzhiyun 		return 0;
624*4882a593Smuzhiyun 	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
625*4882a593Smuzhiyun 	if (i)
626*4882a593Smuzhiyun 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %zu rlen %u\n", buffer, len, rlen);
627*4882a593Smuzhiyun 	change_mode(pp, ECR_PS2);
628*4882a593Smuzhiyun 	return rlen;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun static struct parport_operations parport_uss720_ops =
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	.owner =		THIS_MODULE,
636*4882a593Smuzhiyun 	.write_data =		parport_uss720_write_data,
637*4882a593Smuzhiyun 	.read_data =		parport_uss720_read_data,
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	.write_control =	parport_uss720_write_control,
640*4882a593Smuzhiyun 	.read_control =		parport_uss720_read_control,
641*4882a593Smuzhiyun 	.frob_control =		parport_uss720_frob_control,
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	.read_status =		parport_uss720_read_status,
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	.enable_irq =		parport_uss720_enable_irq,
646*4882a593Smuzhiyun 	.disable_irq =		parport_uss720_disable_irq,
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	.data_forward =		parport_uss720_data_forward,
649*4882a593Smuzhiyun 	.data_reverse =		parport_uss720_data_reverse,
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	.init_state =		parport_uss720_init_state,
652*4882a593Smuzhiyun 	.save_state =		parport_uss720_save_state,
653*4882a593Smuzhiyun 	.restore_state =	parport_uss720_restore_state,
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	.epp_write_data =	parport_uss720_epp_write_data,
656*4882a593Smuzhiyun 	.epp_read_data =	parport_uss720_epp_read_data,
657*4882a593Smuzhiyun 	.epp_write_addr =	parport_uss720_epp_write_addr,
658*4882a593Smuzhiyun 	.epp_read_addr =	parport_uss720_epp_read_addr,
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	.ecp_write_data =	parport_uss720_ecp_write_data,
661*4882a593Smuzhiyun 	.ecp_read_data =	parport_uss720_ecp_read_data,
662*4882a593Smuzhiyun 	.ecp_write_addr =	parport_uss720_ecp_write_addr,
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	.compat_write_data =	parport_uss720_write_compat,
665*4882a593Smuzhiyun 	.nibble_read_data =	parport_ieee1284_read_nibble,
666*4882a593Smuzhiyun 	.byte_read_data =	parport_ieee1284_read_byte,
667*4882a593Smuzhiyun };
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
670*4882a593Smuzhiyun 
uss720_probe(struct usb_interface * intf,const struct usb_device_id * id)671*4882a593Smuzhiyun static int uss720_probe(struct usb_interface *intf,
672*4882a593Smuzhiyun 			const struct usb_device_id *id)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun 	struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf));
675*4882a593Smuzhiyun 	struct usb_host_interface *interface;
676*4882a593Smuzhiyun 	struct usb_endpoint_descriptor *epd;
677*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
678*4882a593Smuzhiyun 	struct parport *pp;
679*4882a593Smuzhiyun 	unsigned char reg;
680*4882a593Smuzhiyun 	int i;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "probe: vendor id 0x%x, device id 0x%x\n",
683*4882a593Smuzhiyun 		le16_to_cpu(usbdev->descriptor.idVendor),
684*4882a593Smuzhiyun 		le16_to_cpu(usbdev->descriptor.idProduct));
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	/* our known interfaces have 3 alternate settings */
687*4882a593Smuzhiyun 	if (intf->num_altsetting != 3) {
688*4882a593Smuzhiyun 		usb_put_dev(usbdev);
689*4882a593Smuzhiyun 		return -ENODEV;
690*4882a593Smuzhiyun 	}
691*4882a593Smuzhiyun 	i = usb_set_interface(usbdev, intf->altsetting->desc.bInterfaceNumber, 2);
692*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "set interface result %d\n", i);
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	interface = intf->cur_altsetting;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	if (interface->desc.bNumEndpoints < 3) {
697*4882a593Smuzhiyun 		usb_put_dev(usbdev);
698*4882a593Smuzhiyun 		return -ENODEV;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	/*
702*4882a593Smuzhiyun 	 * Allocate parport interface
703*4882a593Smuzhiyun 	 */
704*4882a593Smuzhiyun 	priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL);
705*4882a593Smuzhiyun 	if (!priv) {
706*4882a593Smuzhiyun 		usb_put_dev(usbdev);
707*4882a593Smuzhiyun 		return -ENOMEM;
708*4882a593Smuzhiyun 	}
709*4882a593Smuzhiyun 	priv->pp = NULL;
710*4882a593Smuzhiyun 	priv->usbdev = usbdev;
711*4882a593Smuzhiyun 	kref_init(&priv->ref_count);
712*4882a593Smuzhiyun 	spin_lock_init(&priv->asynclock);
713*4882a593Smuzhiyun 	INIT_LIST_HEAD(&priv->asynclist);
714*4882a593Smuzhiyun 	pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops);
715*4882a593Smuzhiyun 	if (!pp) {
716*4882a593Smuzhiyun 		printk(KERN_WARNING "uss720: could not register parport\n");
717*4882a593Smuzhiyun 		goto probe_abort;
718*4882a593Smuzhiyun 	}
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	priv->pp = pp;
721*4882a593Smuzhiyun 	pp->private_data = priv;
722*4882a593Smuzhiyun 	pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
725*4882a593Smuzhiyun 	set_1284_register(pp, 7, 0x00, GFP_KERNEL);
726*4882a593Smuzhiyun 	set_1284_register(pp, 6, 0x30, GFP_KERNEL);  /* PS/2 mode */
727*4882a593Smuzhiyun 	set_1284_register(pp, 2, 0x0c, GFP_KERNEL);
728*4882a593Smuzhiyun 	/* debugging */
729*4882a593Smuzhiyun 	get_1284_register(pp, 0, &reg, GFP_KERNEL);
730*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	i = usb_find_last_int_in_endpoint(interface, &epd);
733*4882a593Smuzhiyun 	if (!i) {
734*4882a593Smuzhiyun 		dev_dbg(&intf->dev, "epaddr %d interval %d\n",
735*4882a593Smuzhiyun 				epd->bEndpointAddress, epd->bInterval);
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 	parport_announce_port(pp);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	usb_set_intfdata(intf, pp);
740*4882a593Smuzhiyun 	return 0;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun probe_abort:
743*4882a593Smuzhiyun 	kill_all_async_requests_priv(priv);
744*4882a593Smuzhiyun 	kref_put(&priv->ref_count, destroy_priv);
745*4882a593Smuzhiyun 	return -ENODEV;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun 
uss720_disconnect(struct usb_interface * intf)748*4882a593Smuzhiyun static void uss720_disconnect(struct usb_interface *intf)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun 	struct parport *pp = usb_get_intfdata(intf);
751*4882a593Smuzhiyun 	struct parport_uss720_private *priv;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "disconnect\n");
754*4882a593Smuzhiyun 	usb_set_intfdata(intf, NULL);
755*4882a593Smuzhiyun 	if (pp) {
756*4882a593Smuzhiyun 		priv = pp->private_data;
757*4882a593Smuzhiyun 		priv->pp = NULL;
758*4882a593Smuzhiyun 		dev_dbg(&intf->dev, "parport_remove_port\n");
759*4882a593Smuzhiyun 		parport_remove_port(pp);
760*4882a593Smuzhiyun 		parport_put_port(pp);
761*4882a593Smuzhiyun 		kill_all_async_requests_priv(priv);
762*4882a593Smuzhiyun 		kref_put(&priv->ref_count, destroy_priv);
763*4882a593Smuzhiyun 	}
764*4882a593Smuzhiyun 	dev_dbg(&intf->dev, "disconnect done\n");
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun /* table of cables that work through this driver */
768*4882a593Smuzhiyun static const struct usb_device_id uss720_table[] = {
769*4882a593Smuzhiyun 	{ USB_DEVICE(0x047e, 0x1001) },
770*4882a593Smuzhiyun 	{ USB_DEVICE(0x04b8, 0x0002) },
771*4882a593Smuzhiyun 	{ USB_DEVICE(0x04b8, 0x0003) },
772*4882a593Smuzhiyun 	{ USB_DEVICE(0x050d, 0x0002) },
773*4882a593Smuzhiyun 	{ USB_DEVICE(0x050d, 0x1202) },
774*4882a593Smuzhiyun 	{ USB_DEVICE(0x0557, 0x2001) },
775*4882a593Smuzhiyun 	{ USB_DEVICE(0x05ab, 0x0002) },
776*4882a593Smuzhiyun 	{ USB_DEVICE(0x06c6, 0x0100) },
777*4882a593Smuzhiyun 	{ USB_DEVICE(0x0729, 0x1284) },
778*4882a593Smuzhiyun 	{ USB_DEVICE(0x1293, 0x0002) },
779*4882a593Smuzhiyun 	{ }						/* Terminating entry */
780*4882a593Smuzhiyun };
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun MODULE_DEVICE_TABLE (usb, uss720_table);
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun static struct usb_driver uss720_driver = {
786*4882a593Smuzhiyun 	.name =		"uss720",
787*4882a593Smuzhiyun 	.probe =	uss720_probe,
788*4882a593Smuzhiyun 	.disconnect =	uss720_disconnect,
789*4882a593Smuzhiyun 	.id_table =	uss720_table,
790*4882a593Smuzhiyun };
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun MODULE_AUTHOR(DRIVER_AUTHOR);
795*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
796*4882a593Smuzhiyun MODULE_LICENSE("GPL");
797*4882a593Smuzhiyun 
uss720_init(void)798*4882a593Smuzhiyun static int __init uss720_init(void)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun 	int retval;
801*4882a593Smuzhiyun 	retval = usb_register(&uss720_driver);
802*4882a593Smuzhiyun 	if (retval)
803*4882a593Smuzhiyun 		goto out;
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
806*4882a593Smuzhiyun 	printk(KERN_INFO KBUILD_MODNAME ": NOTE: this is a special purpose "
807*4882a593Smuzhiyun 	       "driver to allow nonstandard\n");
808*4882a593Smuzhiyun 	printk(KERN_INFO KBUILD_MODNAME ": protocols (eg. bitbang) over "
809*4882a593Smuzhiyun 	       "USS720 usb to parallel cables\n");
810*4882a593Smuzhiyun 	printk(KERN_INFO KBUILD_MODNAME ": If you just want to connect to a "
811*4882a593Smuzhiyun 	       "printer, use usblp instead\n");
812*4882a593Smuzhiyun out:
813*4882a593Smuzhiyun 	return retval;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun 
uss720_cleanup(void)816*4882a593Smuzhiyun static void __exit uss720_cleanup(void)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun 	usb_deregister(&uss720_driver);
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun module_init(uss720_init);
822*4882a593Smuzhiyun module_exit(uss720_cleanup);
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
825