Commit e0afb99e authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/linux/linux/BK/bleeding-2.5

into kroah.com:/home/linux/linux/BK/gregkh-2.5
parents 36a04267 827eb892
/*
* USB ViCam WebCam driver
* Copyright (c) 2002 Joe Burks (jburks@wavicle.org)
* Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
* John Tyner (fill in email address)
*
* Supports 3COM HomeConnect PC Digital WebCam
*
......@@ -43,14 +44,6 @@
// #define VICAM_DEBUG
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(a)
#endif
#ifndef bool
#define bool int
#endif
#ifdef VICAM_DEBUG
#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
......@@ -410,19 +403,20 @@ struct vicam_camera {
u8 *raw_image; // raw data captured from the camera
u8 *framebuf; // processed data in RGB24 format
u8 *cntrlbuf; // area used to send control msgs
struct video_device vdev; // v4l video device
struct usb_device *udev; // usb device
struct semaphore busy_lock; // guard against SMP multithreading
bool is_initialized;
int is_initialized;
u8 open_count;
u8 bulkEndpoint;
bool needsDummyRead;
int needsDummyRead;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#if defined(CONFIG_VIDEO_PROC_FS)
struct proc_dir_entry *proc_dir;
#endif
};
......@@ -437,22 +431,16 @@ send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
{
int status;
// for reasons not yet known to me, you can't send USB control messages
// with data in the module (if you are compiled as a module). Whatever
// the reason, copying it to memory allocated as kernel memory then
// doing the usb control message fixes the problem.
unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
memcpy(transfer_buffer, cp, size);
/* cp must be memory that has been allocated by kmalloc */
status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
request,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_DEVICE, value, index,
transfer_buffer, size, HZ);
cp, size, HZ);
kfree(transfer_buffer);
status = min(status, 0);
if (status < 0) {
printk(KERN_INFO "Failed sending control message, error %d.\n",
......@@ -465,29 +453,30 @@ send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
static int
initialize_camera(struct vicam_camera *cam)
{
const struct {
u8 *data;
u32 size;
} firmware[] = {
{ .data = setup1, .size = sizeof(setup1) },
{ .data = setup2, .size = sizeof(setup2) },
{ .data = setup3, .size = sizeof(setup3) },
{ .data = setup4, .size = sizeof(setup4) },
{ .data = setup5, .size = sizeof(setup5) },
{ .data = setup3, .size = sizeof(setup3) },
{ .data = NULL, .size = 0 }
};
struct usb_device *udev = cam->udev;
int status;
int err, i;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0)
return status;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0)
return status;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
return status;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0)
return status;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0)
return status;
if ((status =
send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
return status;
for (i = 0, err = 0; firmware[i].data && !err; i++) {
memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
return 0;
err = send_control_msg(udev, 0xff, 0, 0,
cam->cntrlbuf, firmware[i].size);
}
return err;
}
static int
......@@ -752,7 +741,8 @@ vicam_open(struct inode *inode, struct file *file)
"vicam video_device improperly initialized");
}
down_interruptible(&cam->busy_lock);
if ( down_interruptible(&cam->busy_lock) )
return -EINTR;
if (cam->open_count > 0) {
printk(KERN_INFO
......@@ -774,6 +764,14 @@ vicam_open(struct inode *inode, struct file *file)
return -ENOMEM;
}
cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!cam->cntrlbuf) {
kfree(cam->raw_image);
rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
up(&cam->busy_lock);
return -ENOMEM;
}
// First upload firmware, then turn the camera on
if (!cam->is_initialized) {
......@@ -803,6 +801,7 @@ vicam_close(struct inode *inode, struct file *file)
kfree(cam->raw_image);
rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
kfree(cam->cntrlbuf);
cam->open_count--;
......@@ -831,7 +830,7 @@ inline void writepixel(char *rgb, int Y, int Cr, int Cb)
// Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
// --------------------------------------------------------------------------------
void vicam_decode_color( char *data, char *rgb)
static void vicam_decode_color( char *data, char *rgb)
{
int x,y;
int Cr, Cb;
......@@ -915,7 +914,7 @@ void vicam_decode_color( char *data, char *rgb)
static void
read_frame(struct vicam_camera *cam, int framenum)
{
unsigned char request[16];
unsigned char *request = cam->cntrlbuf;
int realShutter;
int n;
int actual_length;
......@@ -984,7 +983,8 @@ vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos )
DBG("read %d bytes.\n", (int) count);
down_interruptible(&cam->busy_lock);
if ( down_interruptible(&cam->busy_lock) )
return -EINTR;
if (*ppos >= VICAM_MAX_FRAME_SIZE) {
*ppos = 0;
......@@ -1057,24 +1057,17 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
#ifdef CONFIG_PROC_FS
#if defined(CONFIG_VIDEO_PROC_FS)
static struct proc_dir_entry *vicam_proc_root = NULL;
static int
vicam_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
static int vicam_read_helper(char *page, char **start, off_t off,
int count, int *eof, int value)
{
char *out = page;
int len;
struct vicam_camera *cam = (struct vicam_camera *) data;
out +=
sprintf(out, "Vicam-based WebCam Linux Driver.\n");
out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");
out += sprintf(out, "vicam stats:\n");
out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed);
out += sprintf(out, " Gain: %d\n", cam->gain);
out += sprintf(out, "%d",value);
len = out - page;
len -= off;
......@@ -1089,38 +1082,43 @@ vicam_read_proc(char *page, char **start, off_t off,
return len;
}
static int
vicam_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
static int vicam_read_proc_shutter(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
char *in;
char *start;
struct vicam_camera *cam = (struct vicam_camera *) data;
return vicam_read_helper(page,start,off,count,eof,
((struct vicam_camera *)data)->shutter_speed);
}
in = kmalloc(count + 1, GFP_KERNEL);
if (!in)
return -ENOMEM;
static int vicam_read_proc_gain(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
return vicam_read_helper(page,start,off,count,eof,
((struct vicam_camera *)data)->gain);
}
static int vicam_write_proc_shutter(struct file *file, const char *buffer,
unsigned long count, void *data)
{
struct vicam_camera *cam = (struct vicam_camera *)data;
in[count] = 0; // I'm not sure buffer is gauranteed to be null terminated
// so I do this to make sure I have a null in there.
cam->shutter_speed = simple_strtoul(buffer, NULL, 10);
strncpy(in, buffer, count);
return count;
}
start = strstr(in, "gain=");
if (start
&& (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
cam->gain = simple_strtoul(start + 5, NULL, 10);
static int vicam_write_proc_gain(struct file *file, const char *buffer,
unsigned long count, void *data)
{
struct vicam_camera *cam = (struct vicam_camera *)data;
start = strstr(in, "shutter=");
if (start
&& (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
cam->gain = simple_strtoul(buffer, NULL, 10);
kfree(in);
return count;
}
void
static void
vicam_create_proc_root(void)
{
vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
......@@ -1132,19 +1130,17 @@ vicam_create_proc_root(void)
"could not create /proc entry for vicam!");
}
void
static void
vicam_destroy_proc_root(void)
{
if (vicam_proc_root)
remove_proc_entry("video/vicam", 0);
}
void
vicam_create_proc_entry(void *ptr)
static void
vicam_create_proc_entry(struct vicam_camera *cam)
{
struct vicam_camera *cam = (struct vicam_camera *) ptr;
char name[7];
char name[64];
struct proc_dir_entry *ent;
DBG(KERN_INFO "vicam: creating proc entry\n");
......@@ -1158,46 +1154,54 @@ vicam_create_proc_entry(void *ptr)
sprintf(name, "video%d", cam->vdev.minor);
cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
if ( !cam->proc_dir ) return; // We should probably return an error here
ent =
create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
vicam_proc_root);
if (!ent)
return;
create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
cam->proc_dir);
if (ent) {
ent->data = cam;
ent->read_proc = vicam_read_proc_shutter;
ent->write_proc = vicam_write_proc_shutter;
ent->size = 64;
}
ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
cam->proc_dir);
if ( ent ) {
ent->data = cam;
ent->read_proc = vicam_read_proc;
ent->write_proc = vicam_write_proc;
ent->size = 512;
cam->proc_entry = ent;
ent->read_proc = vicam_read_proc_gain;
ent->write_proc = vicam_write_proc_gain;
ent->size = 64;
}
}
void
static void
vicam_destroy_proc_entry(void *ptr)
{
struct vicam_camera *cam = (struct vicam_camera *) ptr;
char name[7];
char name[16];
if (!cam || !cam->proc_entry)
if ( !cam->proc_dir )
return;
sprintf(name, "video%d", cam->vdev.minor);
remove_proc_entry(name, vicam_proc_root);
cam->proc_entry = NULL;
remove_proc_entry("shutter", cam->proc_dir);
remove_proc_entry("gain", cam->proc_dir);
remove_proc_entry(name,vicam_proc_root);
cam->proc_dir = NULL;
}
#else
static inline void vicam_create_proc_root(void) { }
static inline void vicam_destroy_proc_root(void) { }
static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }
static inline void vicam_destroy_proc_entry(void *ptr) { }
#endif
int
vicam_video_init(struct video_device *vdev)
{
// This would normally create the proc entry for this camera
#ifdef CONFIG_PROC_FS
vicam_create_proc_entry(vdev->priv);
#endif
return 0;
}
static struct file_operations vicam_fops = {
.owner = THIS_MODULE,
.open = vicam_open,
......@@ -1296,6 +1300,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
return -EIO;
}
vicam_create_proc_entry(cam);
printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
dev_set_drvdata(&intf->dev, cam);
......@@ -1314,9 +1320,7 @@ vicam_disconnect(struct usb_interface *intf)
video_unregister_device(&cam->vdev);
#ifdef CONFIG_PROC_FS
vicam_destroy_proc_entry(cam);
#endif
kfree(cam);
......@@ -1329,9 +1333,7 @@ static int __init
usb_vicam_init(void)
{
DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
#ifdef CONFIG_PROC_FS
vicam_create_proc_root();
#endif
if (usb_register(&vicam_driver) != 0)
printk(KERN_WARNING "usb_register failed!\n");
return 0;
......@@ -1344,9 +1346,7 @@ usb_vicam_exit(void)
"ViCam-based WebCam driver shutdown\n");
usb_deregister(&vicam_driver);
#ifdef CONFIG_PROC_FS
vicam_destroy_proc_root();
#endif
}
module_init(usb_vicam_init);
......
......@@ -28,7 +28,6 @@
* is out of the interrupt routine.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
......@@ -46,7 +45,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.5.6 (2002/06/23)"
#define DRIVER_VERSION "v0.5.7 (2002/11/18)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
......@@ -119,16 +118,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
unsigned char *buffer;
unsigned char buffer[256];
DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED)
......@@ -161,7 +153,6 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
memcpy(data, buffer, size);
kfree(buffer);
return ret;
}
......@@ -170,14 +161,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
void *data)
{
int ret;
unsigned char *buffer;
unsigned char buffer[256];
DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, data, size);
add_wait_queue(&pegasus->ctrl_wait, &wait);
......@@ -210,7 +196,6 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
schedule();
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret;
}
......@@ -218,17 +203,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
{
int ret;
unsigned char *buffer;
__u16 dat = data;
__u16 tmp = data;
DECLARE_WAITQUEUE(wait, current);
buffer = kmalloc(1, GFP_KERNEL);
if (!buffer) {
err("unable to allocate memory for configuration descriptors");
return 0;
}
memcpy(buffer, &data, 1);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
while (pegasus->flags & ETH_REGS_CHANGED)
......@@ -238,7 +215,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
pegasus->dr.wValue = cpu_to_le16p(&dat);
pegasus->dr.wValue = cpu_to_le16p(&tmp);
pegasus->dr.wIndex = cpu_to_le16p(&indx);
pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1;
......@@ -246,7 +223,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
usb_sndctrlpipe(pegasus->usb, 0),
(char *) &pegasus->dr,
buffer, 1, ctrl_callback, pegasus);
&data, 1, ctrl_callback, pegasus);
add_wait_queue(&pegasus->ctrl_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
......@@ -259,7 +236,6 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
schedule();
out:
remove_wait_queue(&pegasus->ctrl_wait, &wait);
kfree(buffer);
return ret;
}
......@@ -294,7 +270,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
__u16 regdi;
set_register(pegasus, PhyCtrl, 0);
set_registers(pegasus, PhyAddr, sizeof(data), data);
set_registers(pegasus, PhyAddr, sizeof (data), data);
set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
get_registers(pegasus, PhyCtrl, 1, data);
......@@ -311,6 +287,15 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
return 1;
}
static int mdio_read(struct net_device *dev, int phy_id, int loc)
{
pegasus_t *pegasus = (pegasus_t *) dev->priv;
int res;
read_mii_word(pegasus, phy_id, loc, (u16 *) & res);
return res & 0xffff;
}
static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
{
int i;
......@@ -332,6 +317,13 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
return 1;
}
static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
{
pegasus_t *pegasus = (pegasus_t *) dev->priv;
write_mii_word(pegasus, phy_id, loc, val);
}
static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
{
int i;
......@@ -415,8 +407,8 @@ static void set_ethernet_addr(pegasus_t * pegasus)
__u8 node_id[6];
get_node_id(pegasus, node_id);
set_registers(pegasus, EthID, sizeof(node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof(node_id));
set_registers(pegasus, EthID, sizeof (node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
}
static inline int reset_mac(pegasus_t * pegasus)
......@@ -473,7 +465,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
data[1] = 0;
data[2] = (loopback & 1) ? 0x09 : 0x01;
memcpy(pegasus->eth_regs, data, sizeof(data));
memcpy(pegasus->eth_regs, data, sizeof (data));
set_registers(pegasus, EthCtrl0, 3, data);
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
......@@ -486,11 +478,11 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
return 0;
}
static void fill_skb_pool(pegasus_t *pegasus)
static void fill_skb_pool(pegasus_t * pegasus)
{
int i;
for (i=0; i < RX_SKBS; i++) {
for (i = 0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i])
continue;
pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2);
......@@ -505,11 +497,11 @@ static void fill_skb_pool(pegasus_t *pegasus)
}
}
static void free_skb_pool(pegasus_t *pegasus)
static void free_skb_pool(pegasus_t * pegasus)
{
int i;
for (i=0; i < RX_SKBS; i++) {
for (i = 0; i < RX_SKBS; i++) {
if (pegasus->rx_pool[i]) {
dev_kfree_skb(pegasus->rx_pool[i]);
pegasus->rx_pool[i] = NULL;
......@@ -517,12 +509,12 @@ static void free_skb_pool(pegasus_t *pegasus)
}
}
static inline struct sk_buff *pull_skb(pegasus_t *pegasus)
static inline struct sk_buff *pull_skb(pegasus_t * pegasus)
{
int i;
struct sk_buff *skb;
for (i=0; i < RX_SKBS; i++) {
for (i = 0; i < RX_SKBS; i++) {
if (likely(pegasus->rx_pool[i] != NULL)) {
skb = pegasus->rx_pool[i];
pegasus->rx_pool[i] = NULL;
......@@ -563,7 +555,7 @@ static void read_bulk_callback(struct urb *urb)
if (!count)
goto goon;
rx_status = le32_to_cpu(*(int *)(urb->transfer_buffer + count - 4));
rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4));
if (rx_status & 0x000e0000) {
dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
pegasus->stats.rx_errors++;
......@@ -575,13 +567,17 @@ static void read_bulk_callback(struct urb *urb)
pegasus->stats.rx_frame_errors++;
goto goon;
}
if (pegasus->chip == 0x8513) {
pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer);
pkt_len &= 0x0fff;
pegasus->rx_skb->data += 2;
} else {
pkt_len = (rx_status & 0xfff) - 8;
}
if (pegasus->rx_skb == NULL)
printk("%s: rx_skb == NULL\n", __FUNCTION__);
/*
** we are sure at this point pegasus->rx_skb != NULL
** so we go ahead and pass up the packet.
* at this point we are sure pegasus->rx_skb != NULL
* so we go ahead and pass up the packet.
*/
skb_put(pegasus->rx_skb, pkt_len);
pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net);
......@@ -609,7 +605,7 @@ static void read_bulk_callback(struct urb *urb)
return;
tl_sched:
tl_sched:
tasklet_schedule(&pegasus->rx_tl);
}
......@@ -617,7 +613,7 @@ static void rx_fixup(unsigned long data)
{
pegasus_t *pegasus;
pegasus = (pegasus_t *)data;
pegasus = (pegasus_t *) data;
spin_lock_irq(&pegasus->rx_pool_lock);
fill_skb_pool(pegasus);
......@@ -704,10 +700,9 @@ static void intr_callback(struct urb *urb)
}
}
status = usb_submit_urb (urb, SLAB_ATOMIC);
status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status)
err ("%s: can't resubmit interrupt urb, %d",
net->name, status);
err("%s: can't resubmit interrupt urb, %d", net->name, status);
}
static void pegasus_tx_timeout(struct net_device *net)
......@@ -794,7 +789,7 @@ static void set_carrier(struct net_device *net)
}
static void free_all_urbs(pegasus_t *pegasus)
static void free_all_urbs(pegasus_t * pegasus)
{
usb_free_urb(pegasus->intr_urb);
usb_free_urb(pegasus->tx_urb);
......@@ -802,7 +797,7 @@ static void free_all_urbs(pegasus_t *pegasus)
usb_free_urb(pegasus->ctrl_urb);
}
static void unlink_all_urbs(pegasus_t *pegasus)
static void unlink_all_urbs(pegasus_t * pegasus)
{
usb_unlink_urb(pegasus->intr_urb);
usb_unlink_urb(pegasus->tx_urb);
......@@ -810,7 +805,7 @@ static void unlink_all_urbs(pegasus_t *pegasus)
usb_unlink_urb(pegasus->ctrl_urb);
}
static int alloc_urbs(pegasus_t *pegasus)
static int alloc_urbs(pegasus_t * pegasus)
{
pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!pegasus->ctrl_urb) {
......@@ -860,7 +855,7 @@ static int pegasus_open(struct net_device *net)
warn("%s: failed rx_urb %d", __FUNCTION__, res);
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof(pegasus->intr_buff),
pegasus->intr_buff, sizeof (pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
warn("%s: failed intr_urb %d", __FUNCTION__, res);
......@@ -896,7 +891,82 @@ static int pegasus_close(struct net_device *net)
return 0;
}
#ifdef CONFIG_MII
static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr)
{
u32 ethcmd;
pegasus_t *pegasus = dev->priv;
if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
return -EFAULT;
switch (ethcmd) {
/* get driver-specific version/etc. info */
case ETHTOOL_GDRVINFO:{
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strncpy(info.driver, driver_name,
sizeof (info.driver) - 1);
strncpy(info.version, DRIVER_VERSION,
sizeof (info.version) - 1);
if (copy_to_user(useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
/* get settings */
case ETHTOOL_GSET:{
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
mii_ethtool_gset(&pegasus->mii, &ecmd);
if (copy_to_user(useraddr, &ecmd, sizeof (ecmd)))
return -EFAULT;
return 0;
}
/* set settings */
case ETHTOOL_SSET:{
int r;
struct ethtool_cmd ecmd;
if (copy_from_user(&ecmd, useraddr, sizeof (ecmd)))
return -EFAULT;
r = mii_ethtool_sset(&pegasus->mii, &ecmd);
return r;
}
/* restart autonegotiation */
case ETHTOOL_NWAY_RST:{
return mii_nway_restart(&pegasus->mii);
}
/* get link status */
case ETHTOOL_GLINK:{
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = mii_link_ok(&pegasus->mii);
if (copy_to_user(useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
/* get message-level */
case ETHTOOL_GMSGLVL:{
struct ethtool_value edata = { ETHTOOL_GMSGLVL };
/* edata.data = pegasus->msg_enable; FIXME */
if (copy_to_user(useraddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL:{
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof (edata)))
return -EFAULT;
/* sp->msg_enable = edata.data; FIXME */
return 0;
}
}
return -EOPNOTSUPP;
}
#else
static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
{
pegasus_t *pegasus;
......@@ -913,7 +983,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
ETHTOOL_BUSINFO_LEN);
usb_make_path(pegasus->usb, info.bus_info,
sizeof info.bus_info);
if (copy_to_user(uaddr, &info, sizeof(info)))
if (copy_to_user(uaddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
......@@ -950,7 +1020,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
ecmd.duplex = bmcr & BMCR_FULLDPLX ?
DUPLEX_FULL : DUPLEX_HALF;
}
if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
if (copy_to_user(uaddr, &ecmd, sizeof (ecmd)))
return -EFAULT;
return 0;
......@@ -961,7 +1031,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
case ETHTOOL_GLINK:{
struct ethtool_value edata = { ETHTOOL_GLINK };
edata.data = netif_carrier_ok(net);
if (copy_to_user(uaddr, &edata, sizeof(edata)))
if (copy_to_user(uaddr, &edata, sizeof (edata)))
return -EFAULT;
return 0;
}
......@@ -969,7 +1039,7 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
return -EOPNOTSUPP;
}
}
#endif
static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
__u16 *data = (__u16 *) & rq->ifr_data;
......@@ -1045,8 +1115,26 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
static inline void setup_pegasus_II(pegasus_t * pegasus)
{
u16 data = 0xa5;
set_register(pegasus, Reg1d, 0);
set_register(pegasus, Reg7b, 1);
mdelay(100);
set_register(pegasus, Reg7b, 2);
set_register(pegasus, 0x83, data);
get_registers(pegasus, 0x83, 1, &data);
if (data == 0xa5) {
pegasus->chip = 0x8513;
} else {
pegasus->chip = 0;
}
set_register(pegasus, 0x80, 0xc0);
set_register(pegasus, 0x83, 0xff);
set_register(pegasus, 0x84, 0x01);
if (pegasus->features & HAS_HOME_PNA && mii_mode)
set_register(pegasus, Reg81, 6);
else
......@@ -1065,13 +1153,13 @@ static int pegasus_probe(struct usb_interface *intf,
err("usb_set_configuration() failed");
return -ENODEV;
}
if (!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
if (!(pegasus = kmalloc(sizeof (struct pegasus), GFP_KERNEL))) {
err("out of memory allocating device structure");
return -ENOMEM;
}
usb_get_dev(dev);
memset(pegasus, 0, sizeof(struct pegasus));
memset(pegasus, 0, sizeof (struct pegasus));
pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait);
......@@ -1088,7 +1176,7 @@ static int pegasus_probe(struct usb_interface *intf,
}
init_MUTEX(&pegasus->sem);
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long)pegasus);
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
down(&pegasus->sem);
pegasus->usb = dev;
......@@ -1104,6 +1192,11 @@ static int pegasus_probe(struct usb_interface *intf,
net->set_multicast_list = pegasus_set_multicast;
net->get_stats = pegasus_netdev_stats;
net->mtu = PEGASUS_MTU;
pegasus->mii.dev = net;
pegasus->mii.mdio_read = mdio_read;
pegasus->mii.mdio_write = mdio_write;
pegasus->mii.phy_id_mask = 0x1f;
pegasus->mii.reg_num_mask = 0x1f;
spin_lock_init(&pegasus->rx_pool_lock);
pegasus->features = usb_dev_id[dev_index].private;
......@@ -1132,7 +1225,7 @@ static int pegasus_probe(struct usb_interface *intf,
exit:
up(&pegasus->sem);
if (pegasus) {
dev_set_drvdata (&intf->dev, pegasus);
dev_set_drvdata(&intf->dev, pegasus);
return 0;
}
return -EIO;
......@@ -1140,9 +1233,9 @@ static int pegasus_probe(struct usb_interface *intf,
static void pegasus_disconnect(struct usb_interface *intf)
{
struct pegasus *pegasus = dev_get_drvdata (&intf->dev);
struct pegasus *pegasus = dev_get_drvdata(&intf->dev);
dev_set_drvdata (&intf->dev, NULL);
dev_set_drvdata(&intf->dev, NULL);
if (!pegasus) {
warn("unregistering non-existant device");
return;
......
......@@ -85,6 +85,7 @@ typedef struct pegasus {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
struct mii_if_info mii;
unsigned flags;
unsigned features;
int dev_index;
......@@ -97,6 +98,7 @@ typedef struct pegasus {
wait_queue_head_t ctrl_wait;
struct semaphore sem;
spinlock_t rx_pool_lock;
int chip;
unsigned char intr_buff[8];
__u8 tx_buff[PEGASUS_MTU];
__u8 eth_regs[4];
......@@ -131,11 +133,11 @@ struct usb_eth_dev {
#define VENDOR_LANEED 0x056e
#define VENDOR_LINKSYS 0x066b
#define VENDOR_MELCO 0x0411
#define VENDOR_NETGEAR 0x0846
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
#define VENDOR_SIEMENS 0x067c
#define VENDOR_JTEC 0x11ad
#else /* PEGASUS_DEV */
......@@ -169,7 +171,10 @@ PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
VENDOR_ADMTEK, 0x8513,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
VENDOR_ADMTEK, 0x0986,
DEFAULT_GPIO_RESET | HAS_HOME_PNA )
PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
......@@ -192,7 +197,7 @@ PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x000d,
PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
LINKSYS_GPIO_RESET )
......@@ -246,6 +251,8 @@ PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
......@@ -258,8 +265,6 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "FA8101 USB To ETHERNET", VENDOR_JTEC, 0x8101,
DEFAULT_GPIO_RESET | PEGASUS_II )
#endif /* PEGASUS_DEV */
......@@ -14,6 +14,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (11/19/2002) gkh
* removed a few #ifdefs for the generic code and cleaned up the failure
* logic in initialization.
*
* (10/02/2002) gkh
* moved the console code to console.c and out of this file.
*
......@@ -341,7 +345,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.6"
#define DRIVER_VERSION "v1.7"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
#define DRIVER_DESC "USB Serial Driver core"
......@@ -382,7 +386,29 @@ static struct usb_device_id generic_serial_ids[] = {
{.driver_info = 42},
{}
};
#endif
static int generic_register (void)
{
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
return usb_serial_register (&generic_device);
}
static void generic_deregister (void)
{
/* remove our generic driver */
usb_serial_deregister (&generic_device);
}
#else
static inline int generic_register (void) { return 0; }
static inline void generic_deregister (void) { }
#endif /* CONFIG_USB_SERIAL_GENERIC */
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
......@@ -409,7 +435,6 @@ static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_minor (unsigned int minor)
{
return serial_table[minor];
......@@ -839,7 +864,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
length += sprintf (page+length, "%d:", i);
if (serial->type->owner)
length += sprintf (page+length, " module:%s", serial->type->owner->name);
length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
length += sprintf (page+length, " name:\"%s\"", serial->type->name);
length += sprintf (page+length, " vendor:%04x product:%04x", serial->vendor, serial->product);
length += sprintf (page+length, " num_ports:%d", serial->num_ports);
......@@ -1574,40 +1599,49 @@ static struct tty_driver serial_tty_driver = {
static int __init usb_serial_init(void)
{
int i;
int result;
int result = 0;
/* Initalize our global data */
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
/* register the generic driver, if we should */
result = generic_register();
if (result < 0) {
err("%s - registering generic driver failed", __FUNCTION__);
goto exit;
}
/* register the tty driver */
serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&serial_tty_driver)) {
err("%s - failed to register tty driver", __FUNCTION__);
return -1;
result = tty_register_driver (&serial_tty_driver);
if (result) {
err("%s - tty_register_driver failed", __FUNCTION__);
goto exit_generic;
}
/* register the USB driver */
result = usb_register(&usb_serial_driver);
if (result < 0) {
tty_unregister_driver(&serial_tty_driver);
err("usb_register failed for the usb-serial driver. Error number %d", result);
return -1;
err("%s - usb_register failed", __FUNCTION__);
goto exit_tty;
}
#ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
usb_serial_register (&generic_device);
#endif
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
return result;
exit_tty:
tty_unregister_driver(&serial_tty_driver);
exit_generic:
generic_deregister();
exit:
err ("%s - returning with error %d", __FUNCTION__, result);
return result;
}
......@@ -1615,10 +1649,7 @@ static void __exit usb_serial_exit(void)
{
usb_serial_console_exit();
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_serial_deregister (&generic_device);
#endif
generic_deregister();
usb_deregister(&usb_serial_driver);
tty_unregister_driver(&serial_tty_driver);
......
......@@ -115,7 +115,7 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
(struct freecom_xfer_wrap *) extra->buffer;
int result, partial;
int result;
fxfr->Type = FCM_PACKET_INPUT | 0x00;
fxfr->Timeout = 0; /* Short timeout for debugging. */
......@@ -125,14 +125,12 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
US_DEBUGP("Read data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_msg (us, fxfr, opipe,
FCM_PACKET_LENGTH, &partial);
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("Freecom readdata xport failure: r=%d, p=%d\n",
result, partial);
US_DEBUGP ("Freecom readdata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("Done issuing read request: %d %d\n", result, partial);
/* Now transfer all of our blocks. */
US_DEBUGP("Start of read\n");
......@@ -151,7 +149,7 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_xfer_wrap *fxfr =
(struct freecom_xfer_wrap *) extra->buffer;
int result, partial;
int result;
fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
fxfr->Timeout = 0; /* Short timeout for debugging. */
......@@ -161,15 +159,12 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
US_DEBUGP("Write data Freecom! (c=%d)\n", count);
/* Issue the transfer command. */
result = usb_stor_bulk_msg (us, fxfr, opipe,
FCM_PACKET_LENGTH, &partial);
result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
FCM_PACKET_LENGTH, NULL);
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("Freecom writedata xport failure: r=%d, p=%d\n",
result, partial);
US_DEBUGP ("Freecom writedata transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("Done issuing write request: %d %d\n",
result, partial);
/* Now transfer all of our blocks. */
US_DEBUGP("Start of write\n");
......@@ -191,7 +186,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
struct freecom_status *fst;
unsigned int ipipe, opipe; /* We need both pipes. */
int result;
int partial;
unsigned int partial;
int length;
freecom_udata_t extra;
......@@ -215,23 +210,22 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUG(pdump (srb->cmnd, 12));
/* Send it out. */
result = usb_stor_bulk_msg (us, fcb, opipe,
FCM_PACKET_LENGTH, &partial);
result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
FCM_PACKET_LENGTH, NULL);
/* The Freecom device will only fail if there is something wrong in
* USB land. It returns the status in its own registers, which
* come back in the bulk pipe. */
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
US_DEBUGP ("freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* There are times we can optimize out this status read, but it
* doesn't hurt us to always do it now. */
result = usb_stor_bulk_msg (us, fst, ipipe,
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
US_DEBUGP("foo Status result %d %d\n", result, partial);
US_DEBUGP("foo Status result %d %u\n", result, partial);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -256,24 +250,23 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
memset (fcb->Filler, 0, sizeof (fcb->Filler));
/* Send it out. */
result = usb_stor_bulk_msg (us, fcb, opipe,
FCM_PACKET_LENGTH, &partial);
result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
FCM_PACKET_LENGTH, NULL);
/* The Freecom device will only fail if there is something
* wrong in USB land. It returns the status in its own
* registers, which come back in the bulk pipe.
*/
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
US_DEBUGP ("freecom transport error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* get the data */
result = usb_stor_bulk_msg (us, fst, ipipe,
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
US_DEBUGP("bar Status result %d %d\n", result, partial);
US_DEBUGP("bar Status result %d %u\n", result, partial);
if (result > USB_STOR_XFER_SHORT)
return USB_STOR_TRANSPORT_ERROR;
......@@ -328,7 +321,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
return result;
US_DEBUGP("FCM: Waiting for status\n");
result = usb_stor_bulk_msg (us, fst, ipipe,
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
US_DEBUG(pdump ((void *) fst, partial));
......@@ -354,7 +347,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
return result;
US_DEBUGP("FCM: Waiting for status\n");
result = usb_stor_bulk_msg (us, fst, ipipe,
result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
FCM_PACKET_LENGTH, &partial);
if (partial != 4 || result > USB_STOR_XFER_SHORT)
......@@ -385,13 +378,6 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
}
return USB_STOR_TRANSPORT_GOOD;
US_DEBUGP("Freecom: transfer_length = %d\n",
usb_stor_transfer_length (srb));
US_DEBUGP("Freecom: direction = %d\n", srb->sc_data_direction);
return USB_STOR_TRANSPORT_ERROR;
}
int
......
......@@ -668,7 +668,7 @@ int isd200_write_config( struct us_data *us )
#endif
/* let's send the command via the control pipe */
result = usb_stor_control_msg(
result = usb_stor_ctrl_transfer(
us,
us->send_ctrl_pipe,
0x01,
......@@ -709,7 +709,7 @@ int isd200_read_config( struct us_data *us )
/* read the configuration information from ISD200. Use this to */
/* determine what the special ATA CDB bytes are. */
result = usb_stor_control_msg(
result = usb_stor_ctrl_transfer(
us,
us->recv_ctrl_pipe,
0x02,
......
......@@ -479,7 +479,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us);
/* return the actual length of the data transferred if no error*/
/* return the actual length of the data transferred if no error */
if (status >= 0)
status = us->current_urb->actual_length;
return status;
......@@ -543,47 +543,91 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
return 0;
}
/*
* Transfer one control message
* Interpret the results of a URB transfer
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* This function prints appropriate debugging messages, clears halts on
* bulk endpoints, and translates the status to the corresponding
* USB_STOR_XFER_xxx return code.
*/
int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) {
int result;
static int interpret_urb_result(struct us_data *us, unsigned int pipe,
unsigned int length, int result, unsigned int partial) {
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%d\n",
request, requesttype, value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
US_DEBUGP("usb_stor_control_msg returned %d\n", result);
US_DEBUGP("Status code %d; transferred %u/%u\n",
result, partial, length);
/* a stall indicates a protocol error */
/* stalled */
if (result == -EPIPE) {
/* for non-bulk (i.e., control) endpoints, a stall indicates
* a protocol error */
if (!usb_pipebulk(pipe)) {
US_DEBUGP("-- stall on control pipe\n");
return USB_STOR_XFER_ERROR;
}
/* some other serious problem here */
/* for a bulk endpoint, clear the stall */
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried this a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the transfer was cancelled, presumably by an abort */
if (result == -ENODEV) {
US_DEBUGP("-- transfer cancelled\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result < 0) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* was the entire command transferred? */
if (result < size) {
US_DEBUGP("-- transferred only %d bytes\n", result);
/* no error code; did we send all the data? */
if (partial != length) {
US_DEBUGP("-- transferred only %u bytes\n", partial);
return USB_STOR_XFER_SHORT;
}
US_DEBUGP("-- transfer completed successfully\n");
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/*
* Transfer one control message
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
*/
int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) {
int result;
unsigned int partial = 0;
US_DEBUGP("usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%u\n",
request, requesttype, value, index, size);
result = usb_stor_control_msg(us, pipe, request, requesttype,
value, index, data, size);
if (result > 0) { /* Separate out the amount transferred */
partial = result;
result = 0;
}
return interpret_urb_result(us, pipe, size, result, partial);
}
/*
* Transfer one buffer via bulk transfer
*
......@@ -596,50 +640,17 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
* urb status or transfer length.
*/
int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
char *buf, unsigned int length, unsigned int *act_len)
void *buf, unsigned int length, unsigned int *act_len)
{
int result;
int partial;
unsigned int partial;
/* transfer the data */
US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %d bytes\n", length);
US_DEBUGP("usb_stor_bulk_transfer_buf(): xfer %u bytes\n", length);
result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
result, partial, length);
if (act_len)
*act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x,"
" stalled at %d bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* did we send all the data? */
if (partial == length) {
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/* no error code, so we must have transferred some data,
* just not all of it */
US_DEBUGP("-- transferred only %d bytes\n", partial);
return USB_STOR_XFER_SHORT;
return interpret_urb_result(us, pipe, length, result, partial);
}
/*
......@@ -653,10 +664,10 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
unsigned int *act_len)
{
int result;
int partial;
unsigned int partial;
/* initialize the scatter-gather request block */
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %d bytes, "
US_DEBUGP("usb_stor_bulk_transfer_sglist(): xfer %u bytes, "
"%d entries\n", length, num_sg);
result = usb_sg_init(us->current_sg, us->pusb_dev, pipe, 0,
sg, num_sg, length, SLAB_NOIO);
......@@ -685,55 +696,22 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
result = us->current_sg->status;
partial = us->current_sg->bytes;
US_DEBUGP("usb_sg_wait() returned %d xferred %d/%d\n",
result, partial, length);
if (act_len)
*act_len = partial;
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x, "
"stalled at %d bytes\n", pipe, partial);
if (usb_stor_clear_halt(us, pipe) < 0)
return USB_STOR_XFER_ERROR;
return USB_STOR_XFER_STALLED;
}
/* NAK - that means we've retried this a few times already */
if (result == -ETIMEDOUT) {
US_DEBUGP("-- device NAKed\n");
return USB_STOR_XFER_ERROR;
}
/* the catch-all error case */
if (result) {
US_DEBUGP("-- unknown error\n");
return USB_STOR_XFER_ERROR;
}
/* did we send all the data? */
if (partial == length) {
US_DEBUGP("-- transfer complete\n");
return USB_STOR_XFER_GOOD;
}
/* no error code, so we must have transferred some data,
* just not all of it */
US_DEBUGP("-- transferred only %d bytes\n", partial);
return USB_STOR_XFER_SHORT;
return interpret_urb_result(us, pipe, length, result, partial);
}
/*
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
*
* Nore that this uses usb_stor_bulk_transfer_buf() and
* Note that this uses usb_stor_bulk_transfer_buf() and
* usb_stor_bulk_transfer_sglist() to achieve its goals --
* this function simply determines whether we're going to use
* scatter-gather or not, and acts appropriately.
*/
int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
char *buf, unsigned int length_left, int use_sg, int *residual)
void *buf, unsigned int length_left, int use_sg, int *residual)
{
int result;
unsigned int partial;
......@@ -1278,7 +1256,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
(bcb.Lun >> 4), (bcb.Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
(char *) &bcb, US_BULK_CB_WRAP_LEN, NULL);
&bcb, US_BULK_CB_WRAP_LEN, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -1302,7 +1280,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
&bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) {
......@@ -1310,7 +1288,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
(char *) &bcs, US_BULK_CS_WRAP_LEN, NULL);
&bcs, US_BULK_CS_WRAP_LEN, NULL);
}
/* if we still have a failure at this point, we're in trouble */
......
......@@ -117,6 +117,7 @@ struct bulk_cs_wrap {
/*
* usb_stor_bulk_transfer_xxx() return codes, in order of severity
*/
#define USB_STOR_XFER_GOOD 0 /* good transfer */
#define USB_STOR_XFER_SHORT 1 /* transfered less than expected */
#define USB_STOR_XFER_STALLED 2 /* endpoint stalled */
......@@ -129,7 +130,14 @@ struct bulk_cs_wrap {
#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */
#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */
#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */
/*
* We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
* return codes. But now the transport and low-level transfer routines
* treat an abort as just another error (-ENOENT for a cancelled URB).
* It is up to the invoke_transport() function to test for aborts and
* distinguish them from genuine communication errors.
*/
/*
* CBI accept device specific command
......@@ -162,12 +170,12 @@ extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
char *buf, unsigned int length, unsigned int *act_len);
void *buf, unsigned int length, unsigned int *act_len);
extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
struct scatterlist *sg, int num_sg, unsigned int length,
unsigned int *act_len);
extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
char *buf, unsigned int length, int use_sg, int *residual);
void *buf, unsigned int length, int use_sg, int *residual);
static __inline__ int usb_stor_bulk_transfer_srb(struct us_data *us,
unsigned int pipe, Scsi_Cmnd *srb, unsigned int length) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment