Initial import from the website's tarball, on the 18th of october 2004
[islsm.git] / usb_transport.c
blob0ebdc57a32e37bf6b72caca70b32d24086cf08dc
1 /*
2 * Prism54 USB driver
3 */
5 #include <linux/config.h>
6 #include <linux/kernel.h>
7 #include <linux/errno.h>
8 #include <linux/init.h>
9 #include <linux/slab.h>
10 #include <linux/module.h>
11 #include <linux/smp_lock.h>
12 #include <linux/completion.h>
13 #include <linux/netdevice.h>
14 #include <linux/etherdevice.h>
15 #include <linux/usb.h>
16 #include <linux/pci.h>
17 #include <linux/firmware.h>
18 #include <asm/uaccess.h>
19 #include "prism54_usb.h"
20 #include "isl_38xx.h"
22 void p54u_mdelay(int ms)
24 int t = (ms * HZ + 500) / 1000;
26 if(!t && ms)
27 t = 1;
29 set_current_state(TASK_UNINTERRUPTIBLE);
30 while(t) {
31 //printk("t: %i\n", t);
32 t = schedule_timeout(t);
35 return;
39 void p54u_data_debug(struct net_device *netdev, unsigned int ep, void *_data, int len)
41 struct p54u *p54u = netdev_priv(netdev);
42 struct usb_device *usbdev = p54u->usbdev;
43 unsigned char *data = _data;
44 int k, l, in;
45 unsigned long int time = jiffies;
47 in = ep & USB_DIR_IN;
48 if(debug > 1) {
49 for(k = 0; k < len; k+= 16) {
50 if(k == 0) {
51 printk(KERN_CRIT "[%s >%-6lld<%-6lld+%-6ld] %02x %s 00000000:", in?"IN ":"OUT", 0LL, 0LL, time, ep, in?"<-":"->");
52 } else {
53 printk(KERN_CRIT " -> %08x:", k);
55 for (l = 0; (l < 16) && (k + l < len); ++l) {
56 printk(" %02x", ((unsigned char *)data)[k + l]);
58 printk("\n");
63 int p54u_bulk_msg(struct net_device *netdev, unsigned int ep, void *_data, int len)
65 struct p54u *p54u = netdev_priv(netdev);
66 struct usb_device *usbdev = p54u->usbdev;
67 unsigned char *data = _data;
68 size_t alen;
69 int pipe, err, k, l;
71 p54u_data_debug(netdev, ep, data, len);
73 pipe = usb_sndbulkpipe(usbdev, ep);
74 err = usb_bulk_msg(usbdev, pipe, data, len, &alen, 2 * HZ);
75 if(err)
76 p54u_info("bulk submit failed: %i\n", err);
78 return err;
82 u32 p54u_reg_rw(struct net_device *netdev, int write, int ep, int port, u32 addr, u32 val)
84 struct p54u *p54u = netdev_priv(netdev);
85 struct usb_device *usbdev = p54u->usbdev;
86 struct p54u_reg reg;
87 unsigned int pipe;
88 size_t len,retlen;
89 int err, i, epd;
90 u64 t, t1, t2;
92 reg.port = cpu_to_le16(port);
93 reg.addr = cpu_to_le32(addr);
94 reg.val = ((port & P54U_PORT_U32) == P54U_PORT_U32) ? cpu_to_le32(val) : cpu_to_le32(val&0xffff);
95 len = write ? P54U_REG_WSIZE : P54U_REG_RSIZE;
96 pipe = usb_sndbulkpipe(usbdev, ep & USB_ENDPOINT_NUMBER_MASK);
98 t1 = p54u_time();
99 err = usb_bulk_msg(usbdev, pipe, &reg, len, &retlen, HZ);
100 t2 = p54u_time();
101 t = t2 - t1;
103 p54u_data_debug(netdev, ep, &reg, len);
105 if(err) {
106 p54u_err("%s %02x %04x %08x %08x: failed: %i", write ? "Write": "Read", ep, port, addr, val, err);
107 //p54u->err = err;
108 if(write && (ep == P54U_PIPE_DEV ) && (len != retlen)) {
109 /* something bad happened, but we know how to cope with this case. We should do it for reads, too */
110 p54u_err("expected to write %i but wrote %i on dev pipe, resetting",len,retlen);
111 /* clear stall */
112 usb_clear_halt(usbdev,pipe);
113 /* resubmit only once */
114 err = usb_bulk_msg(usbdev, pipe, &reg, len, &retlen, HZ);
115 if(err) {
116 p54u_err("%s %02x %04x %08x %08x: failed: %i", write ? "Write": "Read", ep, port, addr, val, err);
117 p54u->err = err;
120 else {
121 p54u->err = err;
123 return 0;
126 if(write) {
127 // udelay(ISL38XX_WRITEIO_DELAY);
128 return 0;
131 pipe = usb_rcvbulkpipe(usbdev, ep & USB_ENDPOINT_NUMBER_MASK);
132 len = sizeof(reg.val);
134 t1 = p54u_time();
135 err = usb_bulk_msg(usbdev, pipe, &reg.val, len, &len, HZ);
136 t2 = p54u_time();
137 t = t2 - t1;
139 if(err) {
140 p54u_err("Register read %02x %04x %08x %08x: failed: %i", ep, port, addr, val, err);
141 p54u->err = err;
142 return 0;
145 p54u_data_debug(netdev, ep | USB_DIR_IN, &reg.val, len);
147 return ((port & P54U_PORT_U32) == P54U_PORT_U32) ? le32_to_cpu(reg.val) : (le32_to_cpu(reg.val)&0xffff);
150 static void p54u_wait_ctrl(struct urb *urb, struct pt_regs *regs) {
151 struct completion *comp = (struct completion *) urb->context;
152 complete(comp);
153 return;
156 int p54u_annouced_msg(struct net_device *netdev, unsigned int pipe, void *data, int data_len)
158 struct p54u *p54u = netdev_priv(netdev);
159 struct usb_device *usbdev = p54u->usbdev;
160 struct p54u_reg *reg = 0;
161 struct urb *urb = 0;
162 unsigned int ctrlpipe;
163 struct completion done;
164 void *remap_buf = 0;
166 size_t retlen;
167 int err, i;
168 int val = 0;
169 int remapped = 0;
171 init_completion(&done);
173 reg = (struct p54u_reg *) kmalloc(sizeof(struct p54u_reg),GFP_KERNEL);
174 if (!reg)
175 return -ENOMEM;
177 urb = usb_alloc_urb(0,GFP_KERNEL);
178 if (!urb)
180 kfree(reg);
181 return -ENOMEM;
184 ctrlpipe = usb_sndbulkpipe(usbdev, P54U_PIPE_DEV & USB_ENDPOINT_NUMBER_MASK);
186 usb_fill_bulk_urb(urb, usbdev, ctrlpipe, (char *) reg, P54U_REG_WSIZE,
187 p54u_wait_ctrl, &done);
189 if (pipe == P54U_PIPE_DATA)
191 val = ISL38XX_DEV_INT_DATA;
193 else if (pipe == P54U_PIPE_MGMT)
195 val = ISL38XX_DEV_INT_MGMT;
198 reg->port = cpu_to_le16(P54U_PORT_DEV_U32);
199 reg->addr = cpu_to_le32(P54U_DEV_BASE | ISL38XX_DEV_INT_REG);
200 reg->val = ((P54U_PORT_DEV_U32 & P54U_PORT_U32) == P54U_PORT_U32) ? cpu_to_le32(val) : cpu_to_le32(val&0xffff);
202 /* remap data buffer if non-dmable */
203 // if (!virt_addr_valid(remap_buf)) {
205 remapped = 1;
206 remap_buf = kmalloc(data_len, GFP_KERNEL);
207 if (!remap_buf)
208 return -ENOMEM;
209 memcpy(remap_buf, data, data_len);
211 /* Send first one asynchronously and wait for last one */
212 p54u->err = usb_submit_urb(urb, GFP_KERNEL);
213 if (p54u->err == 0)
215 p54u_data_debug(netdev, P54U_PIPE_DEV, reg, P54U_REG_WSIZE );
216 p54u->err = p54u_bulk_msg(netdev, pipe, remap_buf,data_len);
217 wait_for_completion(&done);
220 if (remapped)
221 kfree(remap_buf);
222 usb_free_urb(urb);
223 kfree(reg);
225 return p54u->err;
229 static void timeout_kill(unsigned long data) {
230 struct p54u_pipe *pipe = (struct p54u_pipe *) data;
231 struct completion *comp = &pipe->comp;
232 // p54u->err=-ETIMEDOUT; we can put the value back in the pipe
233 complete(comp);
234 printk("timeout waiting");
235 return;
238 static int p54u_wait_timeout(struct p54u_pipe *pipe, unsigned int delay)
240 struct timer_list timer;
242 init_timer(&timer);
243 timer.expires = jiffies + HZ*delay;
244 timer.data = (unsigned long)(pipe);
245 timer.function = timeout_kill;
247 add_timer(&timer);
248 wait_for_completion(&pipe->comp);
249 del_timer_sync(&timer);
251 return 0;
254 int p54u_wait_int(struct net_device *netdev)
256 struct p54u *p54u = netdev_priv(netdev);
257 struct usb_device *usbdev = p54u->usbdev;
259 p54u_wait_timeout(&p54u->int_rx,1);
261 return p54u->pending;
264 int p54u_wait_mgmt_response(struct net_device *netdev)
266 struct p54u *p54u = netdev_priv(netdev);
267 struct usb_device *usbdev = p54u->usbdev;
269 p54u_wait_timeout(&p54u->mgmt_rx,1);
271 return p54u->pending;
274 int p54u_wait_data(struct net_device *netdev)
276 struct p54u *p54u = netdev_priv(netdev);
277 struct usb_device *usbdev = p54u->usbdev;
279 p54u_wait_timeout(&p54u->data_rx,1);
281 return p54u->pending;
284 void p54u_int_ack(void *data)
286 struct net_device *netdev = (struct net_device *) data;
287 struct p54u *p54u = netdev_priv(netdev);
288 u32 pending = p54u->pending;
289 u32 reg;
291 /* disable interrupt in ISL */
292 p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0);
294 do {
295 /* ack the interrupts */
296 reg = p54u_dev_readl(netdev, ISL38XX_INT_IDENT_REG);
297 p54u_info("isl int vector: %08x\n", reg);
298 if (reg & ~(0x80000000))
299 p54u_dev_writel(netdev, ISL38XX_INT_ACK_REG, reg);
301 while(reg & ~(0x80000000));
303 /* clear the interrupt at net2280 level
304 the net2280 is in host mode */
305 p54u_brg_writel(netdev, NET2280_IRQSTAT1, NET2280_PCI_INTA_INTERRUPT);
307 /* reenable interrupts in ISL */
308 p54u_dev_writel(netdev, ISL38XX_INT_EN_REG, 0x00004004);
310 /* resubmit URB, only if we're not stopping */
311 if (p54u->state != P54U_SHUTDOWN)
313 p54u->err = usb_submit_urb(p54u->int_rx.urb[0], GFP_KERNEL);
314 if(p54u->err) {
315 p54u_dbg("%s: Error submit int 0: %i\n", netdev->name, p54u->err);
321 void p54u_int_rx_cb(struct urb *urb, struct pt_regs *p)
323 struct net_device *netdev = urb->context;
324 struct p54u *p54u = netdev_priv(netdev);
325 struct usb_device *usbdev = p54u->usbdev;
326 int err, pending;
327 u32 reg;
328 u64 t;
330 if (urb->status != 0)
332 p54u_dbg("interrupt handler abnormal termination");
333 /* This is bound to happen upon urb handback */
334 return;
337 pending = *(int *)urb->transfer_buffer;
338 p54u_data_debug(netdev, 0x8f, urb->transfer_buffer, urb->actual_length);
339 p54u->pending = le32_to_cpu(pending);
340 if(p54u->pending & NET2280_PCI_INTA_INTERRUPT)
341 p54u_dbg("interrupt from prism chip");
343 if(p54u->pending & ~NET2280_PCI_INTA_INTERRUPT)
344 p54u_dbg("interrupt from unknown source");
346 // only complete on return to zero
347 if(p54u->pending == 0)
349 p54u_dbg("interrupt returning to inactive, scheduling work");
350 schedule_work(&p54u->int_ack);
351 complete(&p54u->int_rx.comp);
352 } else {
353 p54u_dbg("interrupts pending, scheduling work");
354 schedule_work(&p54u->int_ack);
357 // in the end only complete when == 0;
359 return;
362 void p54u_data_rx_cb(struct urb *urb, struct pt_regs *p)
364 struct net_device *netdev = urb->context;
365 struct p54u *p54u = netdev_priv(netdev);
366 struct usb_device *usbdev = p54u->usbdev;
367 int err;
369 if (urb->status != 0)
371 p54u_dbg("data rx abnormal termination");
372 return;
375 atomic_dec(&p54u->data_rx.busy);
376 complete(&p54u->data_rx.comp);
378 p54u_dbg("data RX");
379 /* this will resubmit the urb */
380 schedule_work(&p54u->data_bh);
381 return;
384 void p54u_data_rx(void *data)
386 struct net_device *netdev = (struct net_device *) data;
387 struct p54u *p54u = netdev_priv(netdev);
389 /* for now will be the only thing we do with it : display */
391 p54u_data_debug(netdev, 0x81, p54u->data_rx.buf[0], p54u->data_rx.urb[0]->actual_length);
392 p54u_data_rx_submit(netdev);
395 void p54u_mgmt_rx_cb(struct urb *urb, struct pt_regs *p)
397 struct net_device *netdev = urb->context;
398 struct p54u *p54u = netdev_priv(netdev);
399 struct usb_device *usbdev = p54u->usbdev;
401 if (urb->status != 0)
403 p54u_dbg("mgmt rx abnormal termination");
404 return;
407 atomic_dec(&p54u->mgmt_rx.busy);
408 complete(&p54u->mgmt_rx.comp);
409 p54u_data_debug(netdev, 0x82, urb->transfer_buffer, urb->actual_length);
410 return;
413 int p54u_mgmt_rx_submit(struct net_device *netdev)
415 int err = 0;
416 struct p54u *p54u = netdev_priv(netdev);
417 if (p54u->state != P54U_SHUTDOWN)
419 err = usb_submit_urb(p54u->mgmt_rx.urb[0], GFP_KERNEL);
420 if(err) {
421 p54u_info("mgmt submit failed %i\n", err);
423 else {
424 atomic_inc(&p54u->mgmt_rx.busy);
425 p54u_dbg("%s: Submit mgmt ok.\n", netdev->name);
427 return err;
429 return -1;
432 int p54u_data_rx_submit(struct net_device *netdev)
434 int err = 0;
435 struct p54u *p54u = netdev_priv(netdev);
437 if (p54u->state != P54U_SHUTDOWN)
440 err = usb_submit_urb(p54u->data_rx.urb[0], GFP_KERNEL);
441 if(err) {
442 p54u_info("data submit failed %i\n", err);
444 else {
445 atomic_inc(&p54u->data_rx.busy);
446 p54u_dbg("%s: Submit data ok.\n", netdev->name);
448 return err;
450 return -1;