patch-2.3.43 linux/drivers/usb/dabusb.c
Next file: linux/drivers/usb/dabusb.h
Previous file: linux/drivers/usb/cpia.c
Back to the patch index
Back to the overall index
- Lines: 592
- Date:
Wed Feb 9 15:20:13 2000
- Orig file:
v2.3.42/linux/drivers/usb/dabusb.c
- Orig date:
Fri Jan 28 15:09:08 2000
diff -u --recursive --new-file v2.3.42/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
@@ -21,7 +21,7 @@
*
*
*
- * $Id: dabusb.c,v 1.30 1999/12/17 17:50:58 fliegl Exp $
+ * $Id: dabusb.c,v 1.45 2000/01/31 10:23:44 fliegl Exp $
*
*/
@@ -38,26 +38,22 @@
#include <asm/atomic.h>
#include <linux/delay.h>
-#undef DEBUG
-#undef DEBUG_ALL
-
#include "usb.h"
#include "dabusb.h"
#include "dabfirmware.h"
+
/* --------------------------------------------------------------------- */
#define NRDABUSB 4
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#define __init
-#define __exit
-#endif
-
/*-------------------------------------------------------------------*/
+
static dabusb_t dabusb[NRDABUSB];
static int buffers = 256;
+
/*-------------------------------------------------------------------*/
+
static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
{
unsigned long flags;
@@ -79,7 +75,7 @@
return ret;
}
/*-------------------------------------------------------------------*/
-#ifdef DEBUG
+#ifdef DEBUG
static void dump_urb (purb_t purb)
{
dbg("urb :%p", purb);
@@ -108,10 +104,12 @@
pbuff_t b;
dbg("dabusb_cancel_queue");
+
spin_lock_irqsave (&s->lock, flags);
for (p = q->next; p != q; p = p->next) {
b = list_entry (p, buff_t, buff_list);
+
#ifdef DEBUG
dump_urb(b->purb);
#endif
@@ -130,26 +128,34 @@
dbg("dabusb_free_queue");
for (p = q->next; p != q;) {
b = list_entry (p, buff_t, buff_list);
-#ifdef DEBUG
+
+#ifdef DEBUG
dump_urb(b->purb);
#endif
if (b->purb->transfer_buffer)
kfree (b->purb->transfer_buffer);
- if (b->purb)
- kfree (b->purb);
+ usb_free_urb(b->purb);
tmp = p->next;
list_del (p);
kfree (b);
p = tmp;
}
+
return 0;
}
/*-------------------------------------------------------------------*/
static int dabusb_free_buffers (pdabusb_t s)
{
+ unsigned long flags;
dbg("dabusb_free_buffers");
+
+ spin_lock_irqsave(&s->lock, flags);
+
dabusb_free_queue (&s->free_buff_list);
dabusb_free_queue (&s->rec_buff_list);
+
+ spin_unlock_irqrestore(&s->lock, flags);
+
s->got_mem = 0;
return 0;
}
@@ -163,14 +169,14 @@
int dst = 0;
void *buf = purb->transfer_buffer;
-#ifdef DEBUG_ALL
dbg("dabusb_iso_complete");
-#endif
- if (purb->status != USB_ST_URB_KILLED) {
+
+ // process if URB was not killed
+ if (purb->status != -ENOENT) {
unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
for (i = 0; i < purb->number_of_packets; i++)
- if (purb->iso_frame_desc[i].status == USB_ST_NOERROR) {
+ if (!purb->iso_frame_desc[i].status) {
len = purb->iso_frame_desc[i].actual_length;
if (len <= pipesize) {
memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
@@ -179,6 +185,8 @@
else
err("dabusb_iso_complete: invalid len %d", len);
}
+ else
+ warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
if (dst != purb->actual_length)
err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
}
@@ -199,10 +207,9 @@
int packets = _ISOPIPESIZE / pipesize;
int transfer_buffer_length = packets * pipesize;
int i;
- int len = sizeof (urb_t) + packets * sizeof (iso_packet_descriptor_t);
- dbg("dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d",
- len, pipesize, packets, transfer_buffer_length);
+ dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
+ pipesize, packets, transfer_buffer_length);
while (buffers < (s->total_buffer_size << 10)) {
b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
@@ -212,13 +219,13 @@
}
memset (b, sizeof (buff_t), 0);
b->s = s;
- b->purb = (purb_t) kmalloc (len, GFP_KERNEL);
+ b->purb = usb_alloc_urb(packets);
if (!b->purb) {
- err("kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL");
+ err("usb_alloc_urb == NULL");
kfree (b);
goto err;
}
- memset (b->purb, 0, len);
+
b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
if (!b->purb->transfer_buffer) {
kfree (b->purb);
@@ -247,124 +254,55 @@
return 0;
-err:
+ err:
dabusb_free_buffers (s);
return -ENOMEM;
}
/*-------------------------------------------------------------------*/
-static int dabusb_reset_pipe (struct usb_device *usbdev, unsigned int ep)
-{
- dbg("dabusb_reset_pipe");
- if ((ep & ~0x80) >= 16)
- return -EINVAL;
-
- usb_settoggle (usbdev, ep & 0xf, !(ep & 0x80), 0);
-
- return 0;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_submit_urb (pdabusb_t s, purb_t purb)
-{
- int ret;
- bulk_completion_context_t context;
-
- init_waitqueue_head (&context.wait);
- purb->context = &context;
-
-#ifdef DEBUG_ALL
- dump_urb(purb);
-#endif
-
- ret = usb_submit_urb (purb);
- if (ret < 0) {
- dbg("dabusb_bulk: usb_submit_urb returned %d", ret);
- return -EINVAL;
- }
- interruptible_sleep_on_timeout (&context.wait, HZ);
- if (purb->status == USB_ST_URB_PENDING) {
- err("dabusb_usb_submit_urb: %p timed out", purb);
- usb_unlink_urb (purb);
- dabusb_reset_pipe(purb->dev, purb->pipe);
- return -ETIMEDOUT;
- }
- return purb->status;
-}
-/* --------------------------------------------------------------------- */
-static void dabusb_bulk_complete (purb_t purb)
-{
- pbulk_completion_context_t context = purb->context;
-
-#ifdef DEBUG_ALL
- dbg("dabusb_bulk_complete");
- dump_urb(purb);
-#endif
- wake_up (&context->wait);
-}
-
-/* --------------------------------------------------------------------- */
static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
{
int ret;
- urb_t urb;
unsigned int pipe;
+ int actual_length;
-#ifdef DEBUG_ALL
dbg("dabusb_bulk");
-#endif
if (!pb->pipe)
pipe = usb_rcvbulkpipe (s->usbdev, 2);
else
pipe = usb_sndbulkpipe (s->usbdev, 2);
- memset (&urb, 0, sizeof (urb_t));
- FILL_BULK_URB ((&urb), s->usbdev, pipe, pb->data, pb->size, dabusb_bulk_complete, NULL);
+ ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 1000);
+ if(ret<0) {
+ err("dabusb: usb_bulk_msg failed(%d)",ret);
+ }
+
+ if( ret == -EPIPE ) {
+ warn("CLEAR_FEATURE request to remove STALL condition.");
+ if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
+ err("request failed");
+ }
- ret = dabusb_submit_urb (s, &urb);
- pb->size = urb.actual_length;
+ pb->size = actual_length;
return ret;
}
/* --------------------------------------------------------------------- */
static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
{
int ret;
- urb_t urb;
- unsigned int pipe;
- unsigned char *setup = kmalloc (8, GFP_KERNEL);
- unsigned char *transfer_buffer;
+ unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL);
- if (!setup) {
- err("dabusb_writemem: kmalloc(8) failed.");
- return -ENOMEM;
- }
- transfer_buffer = kmalloc (len, GFP_KERNEL);
if (!transfer_buffer) {
err("dabusb_writemem: kmalloc(%d) failed.", len);
- kfree (setup);
return -ENOMEM;
}
- setup[0] = 0x40;
- setup[1] = 0xa0;
- setup[2] = pos & 0xff;
- setup[3] = pos >> 8;
- setup[4] = 0;
- setup[5] = 0;
- setup[6] = len & 0xff;
- setup[7] = len >> 8;
memcpy (transfer_buffer, data, len);
- pipe = usb_sndctrlpipe (s->usbdev, 0);
+ ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
- memset (&urb, 0, sizeof (urb_t));
- FILL_CONTROL_URB ((&urb), s->usbdev, pipe, setup, transfer_buffer, len, dabusb_bulk_complete, NULL);
-
- ret = dabusb_submit_urb (s, &urb);
- kfree (setup);
kfree (transfer_buffer);
- if (ret < 0)
- return ret;
- return urb.status;
+ return ret;
}
/* --------------------------------------------------------------------- */
static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
@@ -379,21 +317,23 @@
PINTEL_HEX_RECORD ptr = firmware;
dbg("Enter dabusb_loadmem (internal)");
-
+
ret = dabusb_8051_reset (s, 1);
while (ptr->Type == 0) {
-#ifdef DEBUG_ALL
- err("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
-#endif
+
+ dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
+
ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
if (ret < 0) {
- err("dabusb_writemem failed (%04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
+ err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
break;
}
ptr++;
}
ret = dabusb_8051_reset (s, 0);
+
dbg("dabusb_loadmem: exit");
+
return ret;
}
/* --------------------------------------------------------------------- */
@@ -406,6 +346,7 @@
b->data[3] = 0;
dbg("dabusb_fpga_clear");
+
return dabusb_bulk (s, b);
}
/* --------------------------------------------------------------------- */
@@ -418,6 +359,7 @@
b->data[3] = 0;
dbg("dabusb_fpga_init");
+
return dabusb_bulk (s, b);
}
/* --------------------------------------------------------------------- */
@@ -429,6 +371,7 @@
unsigned char *buf = bitstream;
dbg("Enter dabusb_fpga_download (internal)");
+
if (!b) {
err("kmalloc(sizeof(bulk_transfer_t))==NULL");
return -ENOMEM;
@@ -438,7 +381,9 @@
ret = dabusb_fpga_clear (s, b);
mdelay (10);
blen = buf[73] + (buf[72] << 8);
+
dbg("Bitstream len: %i", blen);
+
b->data[0] = 0x2b;
b->data[1] = 0;
b->data[2] = 0;
@@ -460,6 +405,7 @@
kfree (b);
dbg("exit dabusb_fpga_download");
+
return ret;
}
@@ -484,12 +430,12 @@
static int dabusb_startrek (pdabusb_t s)
{
if (!s->got_mem && s->state != _started) {
+
dbg("dabusb_startrek");
if (dabusb_alloc_buffers (s) < 0)
return -ENOMEM;
dabusb_stop (s);
- dabusb_reset_pipe (s->usbdev, _DABUSB_ISOPIPE);
s->state = _started;
s->readptr = 0;
}
@@ -497,11 +443,11 @@
if (!list_empty (&s->free_buff_list)) {
pbuff_t end;
int ret;
+
+ while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
- while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
-#ifdef DEBUG_ALL
dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
-#endif
+
end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
ret = usb_submit_urb (end->purb);
@@ -509,29 +455,28 @@
err("usb_submit_urb returned:%d", ret);
if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
err("startrek: dabusb_add_buf_tail failed");
+ break;
}
else
atomic_inc (&s->pending_io);
}
-#ifdef DEBUG_ALL
dbg("pending_io: %d",s->pending_io.counter);
-#endif
}
+
return 0;
}
static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
{
pdabusb_t s = (pdabusb_t) file->private_data;
+ unsigned long flags;
unsigned ret = 0;
int rem;
int cnt;
pbuff_t b;
purb_t purb = NULL;
-#ifdef DEBUG_ALL
dbg("dabusb_read");
-#endif
if (*ppos)
return -ESPIPE;
@@ -545,14 +490,23 @@
while (count > 0) {
dabusb_startrek (s);
+
+ spin_lock_irqsave (&s->lock, flags);
+
if (list_empty (&s->rec_buff_list)) {
+
+ spin_unlock_irqrestore(&s->lock, flags);
+
err("error: rec_buf_list is empty");
goto err;
}
+
b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
purb = b->purb;
- if (purb->status == USB_ST_URB_PENDING) {
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ if (purb->status == -EINPROGRESS) {
if (file->f_flags & O_NONBLOCK) // return nonblocking
{
if (!ret)
@@ -567,10 +521,15 @@
ret = -ERESTARTSYS;
goto err;
}
+
+ spin_lock_irqsave (&s->lock, flags);
+
if (list_empty (&s->rec_buff_list)) {
+ spin_unlock_irqrestore(&s->lock, flags);
err("error: still no buffer available.");
goto err;
}
+ spin_unlock_irqrestore(&s->lock, flags);
s->readptr = 0;
}
if (s->remove_pending) {
@@ -585,9 +544,7 @@
else
cnt = count;
-#ifdef DEBUG_ALL
dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
-#endif
if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
err("read: copy_to_user failed");
@@ -608,7 +565,7 @@
s->readptr = 0;
}
}
-err: //up(&s->mutex);
+ err: //up(&s->mutex);
return ret;
}
@@ -641,14 +598,14 @@
}
down (&s->mutex);
}
- s->opened = 1;
- up (&s->mutex);
-
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
- err("dabusb: set_interface failed");
+ err("set_interface failed");
MOD_DEC_USE_COUNT;
return -EINVAL;
}
+ s->opened = 1;
+ up (&s->mutex);
+
file->f_pos = 0;
file->private_data = s;
@@ -668,7 +625,7 @@
if (!s->remove_pending) {
if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
- err("dabusb: set_interface failed");
+ err("set_interface failed");
}
else
wake_up (&s->remove_ok);
@@ -684,9 +641,8 @@
pbulk_transfer_t pbulk;
int ret = 0;
int version = DABUSB_VERSION;
- DECLARE_WAITQUEUE (wait, current);
-// dbg("dabusb_ioctl");
+ dbg("dabusb_ioctl");
if (s->remove_pending)
return -EIO;
@@ -737,19 +693,11 @@
static struct file_operations dabusb_fops =
{
- dabusb_llseek,
- dabusb_read,
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- dabusb_ioctl,
- NULL, /* mmap */
- dabusb_open,
- NULL, /* flush */
- dabusb_release,
- NULL, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
+ llseek: dabusb_llseek,
+ read: dabusb_read,
+ ioctl: dabusb_ioctl,
+ open: dabusb_open,
+ release: dabusb_release,
};
static int dabusb_find_struct (void)
@@ -799,8 +747,10 @@
err("set_configuration failed");
goto reject;
}
- if (usbdev->descriptor.idProduct == 0x2131)
+ if (usbdev->descriptor.idProduct == 0x2131) {
dabusb_loadmem (s, NULL);
+ goto reject;
+ }
else {
dabusb_fpga_download (s, NULL);
@@ -814,7 +764,7 @@
MOD_INC_USE_COUNT;
return s;
-reject:
+ reject:
up (&s->mutex);
s->usbdev = NULL;
return NULL;
@@ -869,12 +819,14 @@
usb_register (&dabusb_driver);
dbg("dabusb_init: driver registered");
+
return 0;
}
void __exit dabusb_cleanup (void)
{
dbg("dabusb_cleanup");
+
usb_deregister (&dabusb_driver);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)