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, ®, 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, ®, 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, ®, 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, ®, 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