Commit 74541720 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 50c61669 5cf5fc3d
...@@ -38,6 +38,14 @@ ...@@ -38,6 +38,14 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void hcd_pci_release(struct usb_bus *bus)
{
struct usb_hcd *hcd = bus->hcpriv;
if (hcd)
hcd->driver->hcd_free(hcd);
}
/* configure so an HC device and id are always provided */ /* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */ /* always called with process context; sleeping is OK */
...@@ -172,6 +180,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) ...@@ -172,6 +180,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_bus_init (&hcd->self); usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations; hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd; hcd->self.hcpriv = (void *) hcd;
hcd->self.release = &hcd_pci_release;
INIT_LIST_HEAD (&hcd->dev_list); INIT_LIST_HEAD (&hcd->dev_list);
...@@ -234,13 +243,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -234,13 +243,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
} }
usb_deregister_bus (&hcd->self); usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1) {
dev_warn (hcd->controller,
"dangling refs (%d) to bus %d!\n",
atomic_read (&hcd->self.refcnt) - 1,
hcd->self.busnum);
}
hcd->driver->hcd_free (hcd);
} }
EXPORT_SYMBOL (usb_hcd_pci_remove); EXPORT_SYMBOL (usb_hcd_pci_remove);
......
...@@ -557,20 +557,52 @@ void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -557,20 +557,52 @@ void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* exported only within usbcore */ /* exported only within usbcore */
void usb_bus_get (struct usb_bus *bus) struct usb_bus *usb_bus_get (struct usb_bus *bus)
{ {
atomic_inc (&bus->refcnt); struct class_device *tmp;
if (!bus)
return NULL;
tmp = class_device_get(&bus->class_dev);
if (tmp)
return to_usb_bus(tmp);
else
return NULL;
} }
/* exported only within usbcore */ /* exported only within usbcore */
void usb_bus_put (struct usb_bus *bus) void usb_bus_put (struct usb_bus *bus)
{ {
if (atomic_dec_and_test (&bus->refcnt)) if (bus)
kfree (bus); class_device_put(&bus->class_dev);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void usb_host_release(struct class_device *class_dev)
{
struct usb_bus *bus = to_usb_bus(class_dev);
if (bus->release)
bus->release(bus);
}
static struct class usb_host_class = {
.name = "usb_host",
.release = &usb_host_release,
};
void usb_host_init(void)
{
class_register(&usb_host_class);
}
void usb_host_cleanup(void)
{
class_unregister(&usb_host_class);
}
/** /**
* usb_bus_init - shared initialization code * usb_bus_init - shared initialization code
* @bus: the bus structure being initialized * @bus: the bus structure being initialized
...@@ -592,8 +624,6 @@ void usb_bus_init (struct usb_bus *bus) ...@@ -592,8 +624,6 @@ void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_isoc_reqs = 0; bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list); INIT_LIST_HEAD (&bus->bus_list);
atomic_set (&bus->refcnt, 1);
} }
EXPORT_SYMBOL (usb_bus_init); EXPORT_SYMBOL (usb_bus_init);
...@@ -607,7 +637,7 @@ EXPORT_SYMBOL (usb_bus_init); ...@@ -607,7 +637,7 @@ EXPORT_SYMBOL (usb_bus_init);
* *
* If no memory is available, NULL is returned. * If no memory is available, NULL is returned.
* *
* The caller should call usb_free_bus() when it is finished with the structure. * The caller should call usb_put_bus() when it is finished with the structure.
*/ */
struct usb_bus *usb_alloc_bus (struct usb_operations *op) struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{ {
...@@ -616,32 +646,13 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op) ...@@ -616,32 +646,13 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
bus = kmalloc (sizeof *bus, GFP_KERNEL); bus = kmalloc (sizeof *bus, GFP_KERNEL);
if (!bus) if (!bus)
return NULL; return NULL;
memset(bus, 0, sizeof(struct usb_bus));
usb_bus_init (bus); usb_bus_init (bus);
bus->op = op; bus->op = op;
return bus; return bus;
} }
EXPORT_SYMBOL (usb_alloc_bus); EXPORT_SYMBOL (usb_alloc_bus);
/**
* usb_free_bus - frees the memory used by a bus structure
* @bus: pointer to the bus to free
*
* To be invoked by a HCD, only as the last step of decoupling from
* hardware. It is an error to call this if the reference count is
* anything but one. That would indicate that some system component
* did not correctly shut down, and thought the hardware was still
* accessible.
*/
void usb_free_bus (struct usb_bus *bus)
{
if (!bus)
return;
if (atomic_read (&bus->refcnt) != 1)
err ("usb_free_bus #%d, count != 1", bus->busnum);
usb_bus_put (bus);
}
EXPORT_SYMBOL (usb_free_bus);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
...@@ -652,9 +663,10 @@ EXPORT_SYMBOL (usb_free_bus); ...@@ -652,9 +663,10 @@ EXPORT_SYMBOL (usb_free_bus);
* Assigns a bus number, and links the controller into usbcore data * Assigns a bus number, and links the controller into usbcore data
* structures so that it can be seen by scanning the bus list. * structures so that it can be seen by scanning the bus list.
*/ */
void usb_register_bus(struct usb_bus *bus) int usb_register_bus(struct usb_bus *bus)
{ {
int busnum; int busnum;
int retval;
down (&usb_bus_list_lock); down (&usb_bus_list_lock);
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
...@@ -664,15 +676,24 @@ void usb_register_bus(struct usb_bus *bus) ...@@ -664,15 +676,24 @@ void usb_register_bus(struct usb_bus *bus)
} else } else
warn ("too many buses"); warn ("too many buses");
usb_bus_get (bus); snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);
bus->class_dev.class = &usb_host_class;
bus->class_dev.dev = bus->controller;
retval = class_device_register(&bus->class_dev);
if (retval) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
return retval;
}
/* Add it to the list of buses */ /* Add it to the local list of buses */
list_add (&bus->bus_list, &usb_bus_list); list_add (&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock); up (&usb_bus_list_lock);
usbfs_add_bus (bus); usbfs_add_bus (bus);
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
} }
EXPORT_SYMBOL (usb_register_bus); EXPORT_SYMBOL (usb_register_bus);
...@@ -701,7 +722,7 @@ void usb_deregister_bus (struct usb_bus *bus) ...@@ -701,7 +722,7 @@ void usb_deregister_bus (struct usb_bus *bus)
clear_bit (bus->busnum, busmap.busmap); clear_bit (bus->busnum, busmap.busmap);
usb_bus_put (bus); class_device_unregister(&bus->class_dev);
} }
EXPORT_SYMBOL (usb_deregister_bus); EXPORT_SYMBOL (usb_deregister_bus);
......
...@@ -347,9 +347,8 @@ extern long usb_calc_bus_time (int speed, int is_input, ...@@ -347,9 +347,8 @@ extern long usb_calc_bus_time (int speed, int is_input,
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
extern struct usb_bus *usb_alloc_bus (struct usb_operations *); extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
extern void usb_free_bus (struct usb_bus *);
extern void usb_register_bus (struct usb_bus *); extern int usb_register_bus (struct usb_bus *);
extern void usb_deregister_bus (struct usb_bus *); extern void usb_deregister_bus (struct usb_bus *);
extern int usb_register_root_hub (struct usb_device *usb_dev, extern int usb_register_root_hub (struct usb_device *usb_dev,
...@@ -369,7 +368,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd) ...@@ -369,7 +368,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
extern struct list_head usb_bus_list; extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock; extern struct semaphore usb_bus_list_lock;
extern void usb_bus_get (struct usb_bus *bus); extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
extern void usb_bus_put (struct usb_bus *bus); extern void usb_bus_put (struct usb_bus *bus);
extern int usb_find_interface_driver (struct usb_device *dev, extern int usb_find_interface_driver (struct usb_device *dev,
......
...@@ -54,6 +54,8 @@ extern int usb_hub_init(void); ...@@ -54,6 +54,8 @@ extern int usb_hub_init(void);
extern void usb_hub_cleanup(void); extern void usb_hub_cleanup(void);
extern int usb_major_init(void); extern int usb_major_init(void);
extern void usb_major_cleanup(void); extern void usb_major_cleanup(void);
extern int usb_host_init(void);
extern void usb_host_cleanup(void);
int nousb; /* Disable USB when built into kernel image */ int nousb; /* Disable USB when built into kernel image */
...@@ -652,11 +654,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) ...@@ -652,11 +654,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset(dev, 0, sizeof(*dev)); memset(dev, 0, sizeof(*dev));
bus = usb_bus_get(bus);
if (!bus) {
kfree(dev);
return NULL;
}
device_initialize(&dev->dev); device_initialize(&dev->dev);
dev->state = USB_STATE_ATTACHED; dev->state = USB_STATE_ATTACHED;
usb_bus_get(bus);
if (!parent) if (!parent)
dev->devpath [0] = '0'; dev->devpath [0] = '0';
dev->bus = bus; dev->bus = bus;
...@@ -1531,6 +1537,7 @@ static int __init usb_init(void) ...@@ -1531,6 +1537,7 @@ static int __init usb_init(void)
} }
bus_register(&usb_bus_type); bus_register(&usb_bus_type);
usb_host_init();
usb_major_init(); usb_major_init();
usbfs_init(); usbfs_init();
usb_hub_init(); usb_hub_init();
...@@ -1553,6 +1560,7 @@ static void __exit usb_exit(void) ...@@ -1553,6 +1560,7 @@ static void __exit usb_exit(void)
usb_major_cleanup(); usb_major_cleanup();
usbfs_cleanup(); usbfs_cleanup();
usb_hub_cleanup(); usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type); bus_unregister(&usb_bus_type);
} }
......
...@@ -392,9 +392,10 @@ static void qh_lines ( ...@@ -392,9 +392,10 @@ static void qh_lines (
} }
static ssize_t static ssize_t
show_async (struct device *dev, char *buf) show_async (struct class_device *class_dev, char *buf)
{ {
struct pci_dev *pdev; struct usb_bus *bus;
struct usb_hcd *hcd;
struct ehci_hcd *ehci; struct ehci_hcd *ehci;
unsigned long flags; unsigned long flags;
unsigned temp, size; unsigned temp, size;
...@@ -403,8 +404,9 @@ show_async (struct device *dev, char *buf) ...@@ -403,8 +404,9 @@ show_async (struct device *dev, char *buf)
*buf = 0; *buf = 0;
pdev = container_of (dev, struct pci_dev, dev); bus = to_usb_bus(class_dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf; next = buf;
size = PAGE_SIZE; size = PAGE_SIZE;
...@@ -427,14 +429,15 @@ show_async (struct device *dev, char *buf) ...@@ -427,14 +429,15 @@ show_async (struct device *dev, char *buf)
return strlen (buf); return strlen (buf);
} }
static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
#define DBG_SCHED_LIMIT 64 #define DBG_SCHED_LIMIT 64
static ssize_t static ssize_t
show_periodic (struct device *dev, char *buf) show_periodic (struct class_device *class_dev, char *buf)
{ {
struct pci_dev *pdev; struct usb_bus *bus;
struct usb_hcd *hcd;
struct ehci_hcd *ehci; struct ehci_hcd *ehci;
unsigned long flags; unsigned long flags;
union ehci_shadow p, *seen; union ehci_shadow p, *seen;
...@@ -446,8 +449,9 @@ show_periodic (struct device *dev, char *buf) ...@@ -446,8 +449,9 @@ show_periodic (struct device *dev, char *buf)
return 0; return 0;
seen_count = 0; seen_count = 0;
pdev = container_of (dev, struct pci_dev, dev); bus = to_usb_bus(class_dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf; next = buf;
size = PAGE_SIZE; size = PAGE_SIZE;
...@@ -535,14 +539,15 @@ show_periodic (struct device *dev, char *buf) ...@@ -535,14 +539,15 @@ show_periodic (struct device *dev, char *buf)
return PAGE_SIZE - size; return PAGE_SIZE - size;
} }
static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
#undef DBG_SCHED_LIMIT #undef DBG_SCHED_LIMIT
static ssize_t static ssize_t
show_registers (struct device *dev, char *buf) show_registers (struct class_device *class_dev, char *buf)
{ {
struct pci_dev *pdev; struct usb_bus *bus;
struct usb_hcd *hcd;
struct ehci_hcd *ehci; struct ehci_hcd *ehci;
unsigned long flags; unsigned long flags;
unsigned temp, size, i; unsigned temp, size, i;
...@@ -550,9 +555,9 @@ show_registers (struct device *dev, char *buf) ...@@ -550,9 +555,9 @@ show_registers (struct device *dev, char *buf)
static char fmt [] = "%*s\n"; static char fmt [] = "%*s\n";
static char label [] = ""; static char label [] = "";
pdev = container_of (dev, struct pci_dev, dev); bus = to_usb_bus(class_dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd); hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf; next = buf;
size = PAGE_SIZE; size = PAGE_SIZE;
...@@ -562,7 +567,7 @@ show_registers (struct device *dev, char *buf) ...@@ -562,7 +567,7 @@ show_registers (struct device *dev, char *buf)
i = readw (&ehci->caps->hci_version); i = readw (&ehci->caps->hci_version);
temp = snprintf (next, size, temp = snprintf (next, size,
"%s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n", "%s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n",
pdev->dev.name, hcd->pdev->dev.name,
i >> 8, i & 0x0ff, ehci->hcd.state); i >> 8, i & 0x0ff, ehci->hcd.state);
size -= temp; size -= temp;
next += temp; next += temp;
...@@ -636,20 +641,20 @@ show_registers (struct device *dev, char *buf) ...@@ -636,20 +641,20 @@ show_registers (struct device *dev, char *buf)
return PAGE_SIZE - size; return PAGE_SIZE - size;
} }
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ehci_hcd *bus) static inline void create_debug_files (struct ehci_hcd *bus)
{ {
device_create_file (&bus->hcd.pdev->dev, &dev_attr_async); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_registers); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
} }
static inline void remove_debug_files (struct ehci_hcd *bus) static inline void remove_debug_files (struct ehci_hcd *bus)
{ {
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
} }
#endif /* STUB_DEBUG_FILES */ #endif /* STUB_DEBUG_FILES */
......
...@@ -1205,7 +1205,7 @@ static void hc_release_hci (hci_t * hci) ...@@ -1205,7 +1205,7 @@ static void hc_release_hci (hci_t * hci)
} }
usb_deregister_bus (hci->bus); usb_deregister_bus (hci->bus);
usb_free_bus (hci->bus); usb_put_bus (hci->bus);
list_del_init (&hci->hci_hcd_list); list_del_init (&hci->hci_hcd_list);
......
...@@ -466,13 +466,17 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -466,13 +466,17 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
} }
static ssize_t static ssize_t
show_async (struct device *dev, char *buf) show_async (struct class_device *class_dev, char *buf)
{ {
struct usb_bus *bus;
struct usb_hcd *hcd;
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
size_t temp; size_t temp;
unsigned long flags; unsigned long flags;
ohci = dev_to_ohci(dev); bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
/* display control and bulk lists together, for simplicity */ /* display control and bulk lists together, for simplicity */
spin_lock_irqsave (&ohci->lock, flags); spin_lock_irqsave (&ohci->lock, flags);
...@@ -482,14 +486,16 @@ show_async (struct device *dev, char *buf) ...@@ -482,14 +486,16 @@ show_async (struct device *dev, char *buf)
return temp; return temp;
} }
static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
#define DBG_SCHED_LIMIT 64 #define DBG_SCHED_LIMIT 64
static ssize_t static ssize_t
show_periodic (struct device *dev, char *buf) show_periodic (struct class_device *class_dev, char *buf)
{ {
struct usb_bus *bus;
struct usb_hcd *hcd;
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
struct ed **seen, *ed; struct ed **seen, *ed;
unsigned long flags; unsigned long flags;
...@@ -501,7 +507,9 @@ show_periodic (struct device *dev, char *buf) ...@@ -501,7 +507,9 @@ show_periodic (struct device *dev, char *buf)
return 0; return 0;
seen_count = 0; seen_count = 0;
ohci = dev_to_ohci(dev); bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
next = buf; next = buf;
size = PAGE_SIZE; size = PAGE_SIZE;
...@@ -573,14 +581,16 @@ show_periodic (struct device *dev, char *buf) ...@@ -573,14 +581,16 @@ show_periodic (struct device *dev, char *buf)
return PAGE_SIZE - size; return PAGE_SIZE - size;
} }
static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
#undef DBG_SCHED_LIMIT #undef DBG_SCHED_LIMIT
static ssize_t static ssize_t
show_registers (struct device *dev, char *buf) show_registers (struct class_device *class_dev, char *buf)
{ {
struct usb_bus *bus;
struct usb_hcd *hcd;
struct ohci_hcd *ohci; struct ohci_hcd *ohci;
struct ohci_regs *regs; struct ohci_regs *regs;
unsigned long flags; unsigned long flags;
...@@ -588,7 +598,9 @@ show_registers (struct device *dev, char *buf) ...@@ -588,7 +598,9 @@ show_registers (struct device *dev, char *buf)
char *next; char *next;
u32 rdata; u32 rdata;
ohci = dev_to_ohci(dev); bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
regs = ohci->regs; regs = ohci->regs;
next = buf; next = buf;
size = PAGE_SIZE; size = PAGE_SIZE;
...@@ -642,22 +654,22 @@ show_registers (struct device *dev, char *buf) ...@@ -642,22 +654,22 @@ show_registers (struct device *dev, char *buf)
return PAGE_SIZE - size; return PAGE_SIZE - size;
} }
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ohci_hcd *bus) static inline void create_debug_files (struct ohci_hcd *bus)
{ {
device_create_file (bus->hcd.controller, &dev_attr_async); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
device_create_file (bus->hcd.controller, &dev_attr_periodic); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
device_create_file (bus->hcd.controller, &dev_attr_registers); class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
ohci_dbg (bus, "created debug files\n"); ohci_dbg (bus, "created debug files\n");
} }
static inline void remove_debug_files (struct ohci_hcd *bus) static inline void remove_debug_files (struct ohci_hcd *bus)
{ {
device_remove_file (bus->hcd.controller, &dev_attr_async); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
device_remove_file (bus->hcd.controller, &dev_attr_periodic); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
device_remove_file (bus->hcd.controller, &dev_attr_registers); class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
} }
#endif #endif
......
...@@ -1208,6 +1208,13 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1208,6 +1208,13 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
uhci_packetout(td_token(td))); uhci_packetout(td_token(td)));
err: err:
/*
* Enable this chunk of code if you want to see some more debugging.
* But be careful, it has the tendancy to starve out khubd and prevent
* disconnects from happening successfully if you have a slow debug
* log interface (like a serial console.
*/
#if 0
if ((debug == 1 && ret != -EPIPE) || debug > 1) { if ((debug == 1 && ret != -EPIPE) || debug > 1) {
/* Some debugging code */ /* Some debugging code */
dbg("uhci_result_common() failed with status %x", status); dbg("uhci_result_common() failed with status %x", status);
...@@ -1219,7 +1226,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1219,7 +1226,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
lprintk(errbuf); lprintk(errbuf);
} }
} }
#endif
return ret; return ret;
} }
......
...@@ -1701,6 +1701,15 @@ static const struct driver_info zaurus_slb500_info = { ...@@ -1701,6 +1701,15 @@ static const struct driver_info zaurus_slb500_info = {
.in = 1, .out = 2, .in = 1, .out = 2,
}; };
static const struct driver_info zaurus_slc700_info = {
.description = "Sharp Zaurus SL-C700",
.flags = FLAG_FRAMING_Z,
.check_connect = always_connected,
.tx_fixup = zaurus_tx_fixup,
.in = 1, .out = 2,
};
// SL-5600 and C-700 are PXA based; should resemble A300 // SL-5600 and C-700 are PXA based; should resemble A300
...@@ -2751,6 +2760,15 @@ static const struct usb_device_id products [] = { ...@@ -2751,6 +2760,15 @@ static const struct usb_device_id products [] = {
.bInterfaceSubClass = 0x0a, .bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00, .bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_slb500_info, .driver_info = (unsigned long) &zaurus_slb500_info,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8007,
.bInterfaceClass = 0x02,
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_slc700_info,
}, },
#endif #endif
......
...@@ -166,7 +166,11 @@ static int device_reset( Scsi_Cmnd *srb ) ...@@ -166,7 +166,11 @@ static int device_reset( Scsi_Cmnd *srb )
/* lock the device pointers and do the reset */ /* lock the device pointers and do the reset */
down(&(us->dev_semaphore)); down(&(us->dev_semaphore));
result = us->transport_reset(us); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
result = FAILED;
US_DEBUGP("No reset during disconnect\n");
} else
result = us->transport_reset(us);
up(&(us->dev_semaphore)); up(&(us->dev_semaphore));
/* lock access to the state and clear it */ /* lock access to the state and clear it */
...@@ -202,7 +206,7 @@ static int bus_reset( Scsi_Cmnd *srb ) ...@@ -202,7 +206,7 @@ static int bus_reset( Scsi_Cmnd *srb )
down(&(us->dev_semaphore)); down(&(us->dev_semaphore));
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
result = -EIO; result = -EIO;
US_DEBUGP("Attempt to reset during disconnect\n"); US_DEBUGP("No reset during disconnect\n");
} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) { } else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
result = -EBUSY; result = -EBUSY;
US_DEBUGP("Refusing to reset a multi-interface device\n"); US_DEBUGP("Refusing to reset a multi-interface device\n");
......
...@@ -147,9 +147,19 @@ static int usb_stor_msg_common(struct us_data *us, int timeout) ...@@ -147,9 +147,19 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
us->current_urb->context = &urb_done; us->current_urb->context = &urb_done;
us->current_urb->actual_length = 0; us->current_urb->actual_length = 0;
us->current_urb->error_count = 0; us->current_urb->error_count = 0;
us->current_urb->transfer_flags = URB_ASYNC_UNLINK;
us->current_urb->status = 0; us->current_urb->status = 0;
/* we assume that if transfer_buffer isn't us->iobuf then it
* hasn't been mapped for DMA. Yes, this is clunky, but it's
* easier than always having the caller tell us whether the
* transfer buffer has already been mapped. */
us->current_urb->transfer_flags =
URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
if (us->current_urb->transfer_buffer == us->iobuf)
us->current_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
us->current_urb->transfer_dma = us->iobuf_dma;
us->current_urb->setup_dma = us->cr_dma;
/* submit the URB */ /* submit the URB */
status = usb_submit_urb(us->current_urb, GFP_NOIO); status = usb_submit_urb(us->current_urb, GFP_NOIO);
if (status) { if (status) {
...@@ -207,15 +217,15 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -207,15 +217,15 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
value, index, size); value, index, size);
/* fill in the devrequest structure */ /* fill in the devrequest structure */
us->dr->bRequestType = requesttype; us->cr->bRequestType = requesttype;
us->dr->bRequest = request; us->cr->bRequest = request;
us->dr->wValue = cpu_to_le16(value); us->cr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index); us->cr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size); us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */ /* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size, (unsigned char*) us->cr, data, size,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us, timeout); status = usb_stor_msg_common(us, timeout);
...@@ -346,15 +356,15 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, ...@@ -346,15 +356,15 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
value, index, size); value, index, size);
/* fill in the devrequest structure */ /* fill in the devrequest structure */
us->dr->bRequestType = requesttype; us->cr->bRequestType = requesttype;
us->dr->bRequest = request; us->cr->bRequest = request;
us->dr->wValue = cpu_to_le16(value); us->cr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index); us->cr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size); us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */ /* fill and submit the URB */
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size, (unsigned char*) us->cr, data, size,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us, 0); result = usb_stor_msg_common(us, 0);
...@@ -786,9 +796,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -786,9 +796,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
} }
/* STATUS STAGE */ /* STATUS STAGE */
result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata)); result = usb_stor_intr_transfer(us, us->iobuf, 2);
US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
us->irqdata[0], us->irqdata[1]); us->iobuf[0], us->iobuf[1]);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
...@@ -804,7 +814,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -804,7 +814,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[0] == INQUIRY) srb->cmnd[0] == INQUIRY)
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
else { else {
if (us->irqdata[0]) if (us->iobuf[0])
return USB_STOR_TRANSPORT_FAILED; return USB_STOR_TRANSPORT_FAILED;
else else
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
...@@ -815,13 +825,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -815,13 +825,13 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
* The first byte should always be a 0x0 * The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error * The second byte & 0x0F should be 0x0 for good, otherwise error
*/ */
if (us->irqdata[0]) { if (us->iobuf[0]) {
US_DEBUGP("CBI IRQ data showed reserved bType %d\n", US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
us->irqdata[0]); us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
switch (us->irqdata[1] & 0x0F) { switch (us->iobuf[1] & 0x0F) {
case 0x00: case 0x00:
return USB_STOR_TRANSPORT_GOOD; return USB_STOR_TRANSPORT_GOOD;
case 0x01: case 0x01:
...@@ -889,7 +899,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -889,7 +899,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Determine what the maximum LUN supported is */ /* Determine what the maximum LUN supported is */
int usb_stor_Bulk_max_lun(struct us_data *us) int usb_stor_Bulk_max_lun(struct us_data *us)
{ {
unsigned char data;
int result; int result;
/* issue the command */ /* issue the command */
...@@ -897,14 +906,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -897,14 +906,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
US_BULK_GET_MAX_LUN, US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS | USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE, USB_RECIP_INTERFACE,
0, us->ifnum, &data, sizeof(data), HZ); 0, us->ifnum, us->iobuf, 1, HZ);
US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
result, data); result, us->iobuf[0]);
/* if we have a successful request, return the result */ /* if we have a successful request, return the result */
if (result == 1) if (result == 1)
return data; return us->iobuf[0];
/* return the default -- no LUNs */ /* return the default -- no LUNs */
return 0; return 0;
...@@ -912,33 +921,34 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -912,33 +921,34 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
{ {
struct bulk_cb_wrap bcb; struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap bcs; struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
unsigned int transfer_length = srb->request_bufflen; unsigned int transfer_length = srb->request_bufflen;
int result; int result;
int fake_sense = 0; int fake_sense = 0;
/* set up the command wrapper */ /* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(transfer_length); bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0; bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number; bcb->Tag = srb->serial_number;
bcb.Lun = srb->device->lun; bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG) if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->device->id << 4; bcb->Lun |= srb->device->id << 4;
bcb.Length = srb->cmd_len; bcb->Length = srb->cmd_len;
/* copy the command payload */ /* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB)); memset(bcb->CDB, 0, sizeof(bcb->CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length); memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* send it to out endpoint */ /* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n", US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
le32_to_cpu(bcb.Signature), bcb.Tag, le32_to_cpu(bcb->Signature), bcb->Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F), (bcb->Lun >> 4), (bcb->Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length); le32_to_cpu(bcb->DataTransferLength),
bcb->Flags, bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
&bcb, US_BULK_CB_WRAP_LEN, NULL); bcb, US_BULK_CB_WRAP_LEN, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result); US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD) if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
...@@ -972,7 +982,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -972,7 +982,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */ /* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n"); US_DEBUGP("Attempting to get CSW...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
&bcs, US_BULK_CS_WRAP_LEN, NULL); bcs, US_BULK_CS_WRAP_LEN, NULL);
/* did the attempt to read the CSW fail? */ /* did the attempt to read the CSW fail? */
if (result == USB_STOR_XFER_STALLED) { if (result == USB_STOR_XFER_STALLED) {
...@@ -980,7 +990,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -980,7 +990,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get the status again */ /* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n"); US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
&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 */ /* if we still have a failure at this point, we're in trouble */
...@@ -990,17 +1000,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -990,17 +1000,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check bulk status */ /* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag, le32_to_cpu(bcs->Signature), bcs->Tag,
bcs.Residue, bcs.Status); bcs->Residue, bcs->Status);
if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
bcs.Tag != bcb.Tag || bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs.Status > US_BULK_STAT_PHASE) { bcs->Tag != srb->serial_number ||
bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n"); US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR; return USB_STOR_TRANSPORT_ERROR;
} }
/* based on the status code, we report good or bad */ /* based on the status code, we report good or bad */
switch (bcs.Status) { switch (bcs->Status) {
case US_BULK_STAT_OK: case US_BULK_STAT_OK:
/* device babbled -- return fake sense data */ /* device babbled -- return fake sense data */
if (fake_sense) { if (fake_sense) {
...@@ -1065,6 +1076,10 @@ static int usb_stor_reset_common(struct us_data *us, ...@@ -1065,6 +1076,10 @@ static int usb_stor_reset_common(struct us_data *us,
schedule_timeout(HZ*6); schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
down(&us->dev_semaphore); down(&us->dev_semaphore);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("Reset interrupted by disconnect\n");
return FAILED;
}
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe); result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
...@@ -1083,18 +1098,18 @@ static int usb_stor_reset_common(struct us_data *us, ...@@ -1083,18 +1098,18 @@ static int usb_stor_reset_common(struct us_data *us,
/* This issues a CB[I] Reset to the device in question /* This issues a CB[I] Reset to the device in question
*/ */
#define CB_RESET_CMD_SIZE 12
int usb_stor_CB_reset(struct us_data *us) int usb_stor_CB_reset(struct us_data *us)
{ {
unsigned char cmd[12]; US_DEBUGP("%s called\n", __FUNCTION__);
US_DEBUGP("CB_reset() called\n");
memset(cmd, 0xFF, sizeof(cmd)); memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
cmd[0] = SEND_DIAGNOSTIC; us->iobuf[0] = SEND_DIAGNOSTIC;
cmd[1] = 4; us->iobuf[1] = 4;
return usb_stor_reset_common(us, US_CBI_ADSC, return usb_stor_reset_common(us, US_CBI_ADSC,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, cmd, sizeof(cmd)); 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
} }
/* This issues a Bulk-only Reset to the device in question, including /* This issues a Bulk-only Reset to the device in question, including
...@@ -1102,7 +1117,7 @@ int usb_stor_CB_reset(struct us_data *us) ...@@ -1102,7 +1117,7 @@ int usb_stor_CB_reset(struct us_data *us)
*/ */
int usb_stor_Bulk_reset(struct us_data *us) int usb_stor_Bulk_reset(struct us_data *us)
{ {
US_DEBUGP("Bulk reset requested\n"); US_DEBUGP("%s called\n", __FUNCTION__);
return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, return usb_stor_reset_common(us, US_BULK_RESET_REQUEST,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
......
...@@ -252,6 +252,14 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, ...@@ -252,6 +252,14 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
US_SC_UFI, US_PR_CB, NULL, US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ), US_FL_SINGLE_LUN ),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
"Sony",
"Portable USB Harddrive V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony", "Sony",
"Memorystick MSAC-US1", "Memorystick MSAC-US1",
...@@ -271,6 +279,12 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999, ...@@ -271,6 +279,12 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
US_SC_UFI, US_PR_CB, NULL, US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ), US_FL_SINGLE_LUN ),
UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999,
"Sony",
"Memorystick MSC-U03",
US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
/* Submitted by Nathan Babb <nathan@lexi.com> */ /* Submitted by Nathan Babb <nathan@lexi.com> */
UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999, UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999,
"Sony", "Sony",
...@@ -295,26 +309,6 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, ...@@ -295,26 +309,6 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
"USB Hard Disk", "USB Hard Disk",
US_SC_RBC, US_PR_CB, NULL, 0 ), US_SC_RBC, US_PR_CB, NULL, 0 ),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
"Pentax",
"Optio 2/3/400",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200 #ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
"In-System", "In-System",
...@@ -339,12 +333,6 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, ...@@ -339,12 +333,6 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
"USB Storage Adapter V2", "USB Storage Adapter V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization, US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ), 0 ),
UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
"Sony",
"Portable USB Harddrive V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif #endif
#ifdef CONFIG_USB_STORAGE_JUMPSHOT #ifdef CONFIG_USB_STORAGE_JUMPSHOT
...@@ -385,12 +373,6 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x0001, ...@@ -385,12 +373,6 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x05e3, 0x0700, 0x0000, 0x9999,
"Unknown",
"GL641USB based CF Card reader",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY | US_FL_MODE_XLATE),
/* Reported by Hanno Boeck <hanno@gmx.de> /* Reported by Hanno Boeck <hanno@gmx.de>
* Taken from the Lycoris Kernel */ * Taken from the Lycoris Kernel */
UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
...@@ -431,7 +413,8 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, ...@@ -431,7 +413,8 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
"Sandisk", "Sandisk",
"ImageMate SDDR-31", "ImageMate SDDR-31",
US_SC_SCSI, US_PR_BULK, NULL, 0 ), US_SC_SCSI, US_PR_BULK, NULL,
US_FL_IGNORE_SER ),
UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
"Sandisk", "Sandisk",
...@@ -520,13 +503,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, ...@@ -520,13 +503,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab CF+SM Reader", "Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL, US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ), US_FL_MODE_XLATE ),
/* Submitted by Olaf Hering <olh@suse.de> */
UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
"Datafab Systems, Inc.",
"USB to CF + SM Combo (LC1)",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ),
#endif #endif
#ifdef CONFIG_USB_STORAGE_SDDR55 #ifdef CONFIG_USB_STORAGE_SDDR55
...@@ -538,6 +514,15 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, ...@@ -538,6 +514,15 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
#endif #endif
#ifdef CONFIG_USB_STORAGE_DATAFAB
/* Submitted by Olaf Hering <olh@suse.de> */
UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
"Datafab Systems, Inc.",
"USB to CF + SM Combo (LC1)",
US_SC_SCSI, US_PR_DATAFAB, NULL,
US_FL_MODE_XLATE ),
#endif
/* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100
* Only revision 1.13 tested (same for all of the above devices, * Only revision 1.13 tested (same for all of the above devices,
* based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY.
...@@ -563,6 +548,22 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, ...@@ -563,6 +548,22 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
US_SC_8070, US_PR_CB, NULL, US_SC_8070, US_PR_CB, NULL,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
"Digimax 410",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
/* Aiptek PocketCAM 3Mega
* Nicolas DUPEUX <nicolas@dupeux.net>
*/
UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
"AIPTEK",
"PocketCAM 3Mega",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE ),
/* aeb */ /* aeb */
UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
"Feiya", "Feiya",
...@@ -570,13 +571,6 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, ...@@ -570,13 +571,6 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
US_SC_SCSI, US_PR_BULK, NULL, US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_CAPACITY ), US_FL_FIX_CAPACITY ),
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
"Digimax 410",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY),
UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001, UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
"Minds@Work", "Minds@Work",
"Digital Wallet", "Digital Wallet",
...@@ -589,22 +583,26 @@ UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, ...@@ -589,22 +583,26 @@ UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
US_SC_SCSI, US_PR_BULK, NULL, US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ), US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100, /* This Pentax still camera is not conformant
"IBM", * to the USB storage specification: -
"IBM USB Memory Key", * - It does not like the INQUIRY command. So we must handle this command
US_SC_SCSI, US_PR_BULK, NULL, * of the SCSI layer ourselves.
US_FL_FIX_INQUIRY ), * Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
/* Pentax Optio S digital camera */
* adapted from http://www2.goldfisch.at/knowledge/233 UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
* (Peter Pilsl <pilsl@goldfisch.at>) "Pentax",
* by Christoph Weidemann <cweidema@indiana.edu> */ "Optio 2/3/400",
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL,
"Pentax", US_FL_FIX_INQUIRY ),
"Optio S",
US_SC_8070, US_PR_CB, NULL,
US_FL_MODE_XLATE|US_FL_FIX_INQUIRY),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CBI, NULL,
US_FL_FIX_INQUIRY ),
#ifdef CONFIG_USB_STORAGE_ISD200 #ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI", "ATI",
...@@ -613,13 +611,6 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, ...@@ -613,13 +611,6 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
0 ), 0 ),
#endif #endif
/* EasyDisk support. Submitted by Stanislav Karchebny <berk@madfire.net> */
UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001,
"Global Channel Solutions",
"EasyDisk EDxxxx",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10. * Tested on hardware version 1.10.
* Entry is needed only for the initializer function override. * Entry is needed only for the initializer function override.
...@@ -648,13 +639,3 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, ...@@ -648,13 +639,3 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_SC_SCSI, US_PR_SDDR55, NULL, US_SC_SCSI, US_PR_SDDR55, NULL,
US_FL_SINGLE_LUN), US_FL_SINGLE_LUN),
#endif #endif
/* Aiptek PocketCAM 3Mega
* Nicolas DUPEUX <nicolas@dupeux.net>
*/
UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
"AIPTEK",
"PocketCAM 3Mega",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_MODE_XLATE ),
...@@ -338,10 +338,16 @@ static int usb_stor_control_thread(void * __us) ...@@ -338,10 +338,16 @@ static int usb_stor_control_thread(void * __us)
/* lock the device pointers */ /* lock the device pointers */
down(&(us->dev_semaphore)); down(&(us->dev_semaphore));
/* don't do anything if we are disconnecting */
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
US_DEBUGP("No command during disconnect\n");
us->srb->result = DID_BAD_TARGET << 16;
}
/* reject the command if the direction indicator /* reject the command if the direction indicator
* is UNKNOWN * is UNKNOWN
*/ */
if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) { else if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
US_DEBUGP("UNKNOWN data direction\n"); US_DEBUGP("UNKNOWN data direction\n");
us->srb->result = DID_ERROR << 16; us->srb->result = DID_ERROR << 16;
} }
...@@ -421,12 +427,44 @@ static int usb_stor_control_thread(void * __us) ...@@ -421,12 +427,44 @@ static int usb_stor_control_thread(void * __us)
* Device probing and disconnecting * Device probing and disconnecting
***********************************************************************/ ***********************************************************************/
/* Associate our private data with the USB device */
static int associate_dev(struct us_data *us, struct usb_interface *intf)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->altsetting->desc.bInterfaceNumber;
/* Store our private data in the interface and increment the
* device's reference count */
usb_set_intfdata(intf, us);
usb_get_dev(us->pusb_dev);
/* Allocate the device-related DMA-mapped buffers */
us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
GFP_KERNEL, &us->cr_dma);
if (!us->cr) {
US_DEBUGP("usb_ctrlrequest allocation failed\n");
return -ENOMEM;
}
us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE,
GFP_KERNEL, &us->iobuf_dma);
if (!us->iobuf) {
US_DEBUGP("I/O buffer allocation failed\n");
return -ENOMEM;
}
return 0;
}
/* Get the unusual_devs entries and the string descriptors */ /* Get the unusual_devs entries and the string descriptors */
static void get_device_info(struct us_data *us, int id_index) static void get_device_info(struct us_data *us, int id_index)
{ {
struct usb_device *dev = us->pusb_dev; struct usb_device *dev = us->pusb_dev;
struct usb_host_interface *altsetting = struct usb_interface_descriptor *idesc =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting]; &us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
struct usb_device_id *id = &storage_usb_ids[id_index]; struct usb_device_id *id = &storage_usb_ids[id_index];
...@@ -438,10 +476,10 @@ static void get_device_info(struct us_data *us, int id_index) ...@@ -438,10 +476,10 @@ static void get_device_info(struct us_data *us, int id_index)
/* Store the entries */ /* Store the entries */
us->unusual_dev = unusual_dev; us->unusual_dev = unusual_dev;
us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ? us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
altsetting->desc.bInterfaceSubClass : idesc->bInterfaceSubClass :
unusual_dev->useProtocol; unusual_dev->useProtocol;
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
altsetting->desc.bInterfaceProtocol : idesc->bInterfaceProtocol :
unusual_dev->useTransport; unusual_dev->useTransport;
us->flags = unusual_dev->flags; us->flags = unusual_dev->flags;
...@@ -455,20 +493,26 @@ static void get_device_info(struct us_data *us, int id_index) ...@@ -455,20 +493,26 @@ static void get_device_info(struct us_data *us, int id_index)
"an unneeded SubClass entry", "an unneeded SubClass entry",
"an unneeded Protocol entry", "an unneeded Protocol entry",
"unneeded SubClass and Protocol entries"}; "unneeded SubClass and Protocol entries"};
struct usb_device_descriptor *ddesc = &dev->descriptor;
int msg = -1; int msg = -1;
if (unusual_dev->useProtocol != US_SC_DEVICE && if (unusual_dev->useProtocol != US_SC_DEVICE &&
us->subclass == altsetting->desc.bInterfaceSubClass) us->subclass == idesc->bInterfaceSubClass)
msg += 1; msg += 1;
if (unusual_dev->useTransport != US_PR_DEVICE && if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == altsetting->desc.bInterfaceProtocol) us->protocol == idesc->bInterfaceProtocol)
msg += 2; msg += 2;
if (msg >= 0) if (msg >= 0)
printk(KERN_NOTICE USB_STORAGE "This device " printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x) has %s in unusual_devs.h\n" "(%04x,%04x,%04x S %02x P %02x)"
" has %s in unusual_devs.h\n"
" Please send a copy of this message to " " Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n", "<linux-usb-devel@lists.sourceforge.net>\n",
id->idVendor, id->idProduct, msgs[msg]); ddesc->idVendor, ddesc->idProduct,
ddesc->bcdDevice,
idesc->bInterfaceSubClass,
idesc->bInterfaceProtocol,
msgs[msg]);
} }
/* Read the device's string descriptors */ /* Read the device's string descriptors */
...@@ -485,15 +529,15 @@ static void get_device_info(struct us_data *us, int id_index) ...@@ -485,15 +529,15 @@ static void get_device_info(struct us_data *us, int id_index)
/* Use the unusual_dev strings if the device didn't provide them */ /* Use the unusual_dev strings if the device didn't provide them */
if (strlen(us->vendor) == 0) { if (strlen(us->vendor) == 0) {
if (unusual_dev->vendorName) if (unusual_dev->vendorName)
strncpy(us->vendor, unusual_dev->vendorName, strlcpy(us->vendor, unusual_dev->vendorName,
sizeof(us->vendor) - 1); sizeof(us->vendor));
else else
strcpy(us->vendor, "Unknown"); strcpy(us->vendor, "Unknown");
} }
if (strlen(us->product) == 0) { if (strlen(us->product) == 0) {
if (unusual_dev->productName) if (unusual_dev->productName)
strncpy(us->product, unusual_dev->productName, strlcpy(us->product, unusual_dev->productName,
sizeof(us->product) - 1); sizeof(us->product));
else else
strcpy(us->product, "Unknown"); strcpy(us->product, "Unknown");
} }
...@@ -714,18 +758,9 @@ static int usb_stor_acquire_resources(struct us_data *us) ...@@ -714,18 +758,9 @@ static int usb_stor_acquire_resources(struct us_data *us)
{ {
int p; int p;
/* Allocate the USB control blocks */
US_DEBUGP("Allocating usb_ctrlrequest\n");
us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL);
if (!us->dr) {
US_DEBUGP("allocation failed\n");
return -ENOMEM;
}
US_DEBUGP("Allocating URB\n");
us->current_urb = usb_alloc_urb(0, GFP_KERNEL); us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!us->current_urb) { if (!us->current_urb) {
US_DEBUGP("allocation failed\n"); US_DEBUGP("URB allocation failed\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -778,8 +813,24 @@ static void dissociate_dev(struct us_data *us) ...@@ -778,8 +813,24 @@ static void dissociate_dev(struct us_data *us)
{ {
US_DEBUGP("-- %s\n", __FUNCTION__); US_DEBUGP("-- %s\n", __FUNCTION__);
down(&us->dev_semaphore); down(&us->dev_semaphore);
/* Free the device-related DMA-mapped buffers */
if (us->cr) {
usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
us->cr_dma);
us->cr = NULL;
}
if (us->iobuf) {
usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
us->iobuf_dma);
us->iobuf = NULL;
}
/* Remove our private data from the interface and decrement the
* device's reference count */
usb_set_intfdata(us->pusb_intf, NULL); usb_set_intfdata(us->pusb_intf, NULL);
usb_put_dev(us->pusb_dev); usb_put_dev(us->pusb_dev);
us->pusb_dev = NULL; us->pusb_dev = NULL;
us->pusb_intf = NULL; us->pusb_intf = NULL;
up(&us->dev_semaphore); up(&us->dev_semaphore);
...@@ -818,16 +869,11 @@ void usb_stor_release_resources(struct us_data *us) ...@@ -818,16 +869,11 @@ void usb_stor_release_resources(struct us_data *us)
us->extra_destructor(us->extra); us->extra_destructor(us->extra);
} }
/* Destroy the extra data */ /* Free the extra data and the URB */
if (us->extra) { if (us->extra)
kfree(us->extra); kfree(us->extra);
}
/* Free the USB control blocks */
if (us->current_urb) if (us->current_urb)
usb_free_urb(us->current_urb); usb_free_urb(us->current_urb);
if (us->dr)
kfree(us->dr);
/* Free the structure itself */ /* Free the structure itself */
kfree(us); kfree(us);
...@@ -857,15 +903,10 @@ static int storage_probe(struct usb_interface *intf, ...@@ -857,15 +903,10 @@ static int storage_probe(struct usb_interface *intf,
init_MUTEX_LOCKED(&(us->sema)); init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify)); init_completion(&(us->notify));
/* Fill in the device-related fields */ /* Associate the us_data structure with the USB device */
us->pusb_dev = interface_to_usbdev(intf); result = associate_dev(us, intf);
us->pusb_intf = intf; if (result)
us->ifnum = intf->altsetting->desc.bInterfaceNumber; goto BadDevice;
/* Store our private data in the interface and increment the
* device's reference count */
usb_set_intfdata(intf, us);
usb_get_dev(us->pusb_dev);
/* /*
* Get the unusual_devs entries and the descriptors * Get the unusual_devs entries and the descriptors
......
...@@ -71,6 +71,7 @@ struct us_unusual_dev { ...@@ -71,6 +71,7 @@ struct us_unusual_dev {
#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for #define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for
Win/MacOS compatibility */ Win/MacOS compatibility */
#define US_FL_IGNORE_SER 0 /* [no longer used] */
#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
...@@ -92,6 +93,15 @@ struct us_unusual_dev { ...@@ -92,6 +93,15 @@ struct us_unusual_dev {
#define USB_STOR_STRING_LEN 32 #define USB_STOR_STRING_LEN 32
/*
* We provide a DMA-mapped I/O buffer for use with small USB transfers.
* It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
* 31-byte buffer. But Freecom needs a 64-byte buffer, so that's the
* size we'll allocate.
*/
#define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */
typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
typedef int (*trans_reset)(struct us_data*); typedef int (*trans_reset)(struct us_data*);
typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
...@@ -106,6 +116,7 @@ struct us_data { ...@@ -106,6 +116,7 @@ struct us_data {
struct semaphore dev_semaphore; /* protect pusb_dev */ struct semaphore dev_semaphore; /* protect pusb_dev */
struct usb_device *pusb_dev; /* this usb_device */ struct usb_device *pusb_dev; /* this usb_device */
struct usb_interface *pusb_intf; /* this interface */ struct usb_interface *pusb_intf; /* this interface */
struct us_unusual_dev *unusual_dev; /* device-filter entry */
unsigned long flags; /* from filter initially */ unsigned long flags; /* from filter initially */
unsigned int send_bulk_pipe; /* cached pipe values */ unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe; unsigned int recv_bulk_pipe;
...@@ -139,20 +150,19 @@ struct us_data { ...@@ -139,20 +150,19 @@ struct us_data {
int pid; /* control thread */ int pid; /* control thread */
int sm_state; /* what we are doing */ int sm_state; /* what we are doing */
/* interrupt communications data */
unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */ /* control and bulk communications data */
struct urb *current_urb; /* non-int USB requests */ struct urb *current_urb; /* USB requests */
struct usb_ctrlrequest *dr; /* control requests */ struct usb_ctrlrequest *cr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather USB */ struct usb_sg_request current_sg; /* scatter-gather req. */
unsigned char *iobuf; /* I/O buffer */
/* the semaphore for sleeping the control thread */ dma_addr_t cr_dma; /* buffer DMA addresses */
struct semaphore sema; /* to sleep thread on */ dma_addr_t iobuf_dma;
/* mutual exclusion structures */ /* mutual exclusion structures */
struct semaphore sema; /* to sleep thread on */
struct completion notify; /* thread begin/end */ struct completion notify; /* thread begin/end */
struct us_unusual_dev *unusual_dev; /* If unusual device */
/* subdriver information */
void *extra; /* Any extra data */ void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */ extra_data_destructor extra_destructor;/* extra data destructor */
}; };
......
...@@ -112,6 +112,7 @@ struct usb_skel { ...@@ -112,6 +112,7 @@ struct usb_skel {
struct completion write_finished; /* wait for the write to finish */ struct completion write_finished; /* wait for the write to finish */
int open; /* if the port is open or not */ int open; /* if the port is open or not */
int present; /* if the device is not disconnected */
struct semaphore sem; /* locks this structure */ struct semaphore sem; /* locks this structure */
}; };
...@@ -296,7 +297,7 @@ static int skel_release (struct inode *inode, struct file *file) ...@@ -296,7 +297,7 @@ static int skel_release (struct inode *inode, struct file *file)
dev->open = 0; dev->open = 0;
if (dev->udev == NULL) { if (!dev->present) {
/* the device was unplugged before the file was released */ /* the device was unplugged before the file was released */
up (&dev->sem); up (&dev->sem);
skel_delete (dev); skel_delete (dev);
...@@ -326,7 +327,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t ...@@ -326,7 +327,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
down (&dev->sem); down (&dev->sem);
/* verify that the device wasn't unplugged */ /* verify that the device wasn't unplugged */
if (dev->udev == NULL) { if (!dev->present) {
up (&dev->sem); up (&dev->sem);
return -ENODEV; return -ENODEV;
} }
...@@ -382,7 +383,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count, ...@@ -382,7 +383,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
down (&dev->sem); down (&dev->sem);
/* verify that the device wasn't unplugged */ /* verify that the device wasn't unplugged */
if (dev->udev == NULL) { if (!dev->present) {
retval = -ENODEV; retval = -ENODEV;
goto exit; goto exit;
} }
...@@ -452,7 +453,7 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, ...@@ -452,7 +453,7 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
down (&dev->sem); down (&dev->sem);
/* verify that the device wasn't unplugged */ /* verify that the device wasn't unplugged */
if (dev->udev == NULL) { if (!dev->present) {
up (&dev->sem); up (&dev->sem);
return -ENODEV; return -ENODEV;
} }
...@@ -507,8 +508,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -507,8 +508,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
size_t buffer_size; size_t buffer_size;
int i; int i;
int retval; int retval;
char name[14];
/* See if the device offered us matches what we can accept */ /* See if the device offered us matches what we can accept */
if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) || if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
...@@ -580,7 +579,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -580,7 +579,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
*/ */
buffer_size = endpoint->wMaxPacketSize; buffer_size = endpoint->wMaxPacketSize;
dev->bulk_out_size = buffer_size; dev->bulk_out_size = buffer_size;
dev->write_urb->transfer_flags = (URB_NO_DMA_MAP | dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
URB_ASYNC_UNLINK); URB_ASYNC_UNLINK);
dev->bulk_out_buffer = usb_buffer_alloc (udev, dev->bulk_out_buffer = usb_buffer_alloc (udev,
buffer_size, GFP_KERNEL, buffer_size, GFP_KERNEL,
...@@ -601,6 +600,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i ...@@ -601,6 +600,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
goto error; goto error;
} }
/* allow device read, write and ioctl */
dev->present = 1;
/* let the user know what node this device is now attached to */ /* let the user know what node this device is now attached to */
info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
...@@ -663,10 +665,12 @@ static void skel_disconnect(struct usb_interface *interface) ...@@ -663,10 +665,12 @@ static void skel_disconnect(struct usb_interface *interface)
wait_for_completion (&dev->write_finished); wait_for_completion (&dev->write_finished);
} }
dev->udev = NULL; /* prevent device read, write and ioctl */
dev->present = 0;
up (&dev->sem); up (&dev->sem);
/* if the device is not opened, then we clean up right now */ /* if the device is opened, skel_release will clean this up */
if (!dev->open) if (!dev->open)
skel_delete (dev); skel_delete (dev);
......
...@@ -207,8 +207,10 @@ struct usb_bus { ...@@ -207,8 +207,10 @@ struct usb_bus {
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */ struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */
atomic_t refcnt; struct class_device class_dev; /* class device for this bus */
void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */
}; };
#define to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
......
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