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 @@
/*-------------------------------------------------------------------------*/
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 */
/* 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)
usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->self.release = &hcd_pci_release;
INIT_LIST_HEAD (&hcd->dev_list);
......@@ -234,13 +243,6 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
}
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);
......
......@@ -557,20 +557,52 @@ void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/
/* 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 */
void usb_bus_put (struct usb_bus *bus)
{
if (atomic_dec_and_test (&bus->refcnt))
kfree (bus);
if (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
* @bus: the bus structure being initialized
......@@ -592,8 +624,6 @@ void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list);
atomic_set (&bus->refcnt, 1);
}
EXPORT_SYMBOL (usb_bus_init);
......@@ -607,7 +637,7 @@ EXPORT_SYMBOL (usb_bus_init);
*
* 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)
{
......@@ -616,32 +646,13 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
bus = kmalloc (sizeof *bus, GFP_KERNEL);
if (!bus)
return NULL;
memset(bus, 0, sizeof(struct usb_bus));
usb_bus_init (bus);
bus->op = op;
return 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);
* Assigns a bus number, and links the controller into usbcore data
* 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 retval;
down (&usb_bus_list_lock);
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
......@@ -664,15 +676,24 @@ void usb_register_bus(struct usb_bus *bus)
} else
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);
up (&usb_bus_list_lock);
usbfs_add_bus (bus);
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
}
EXPORT_SYMBOL (usb_register_bus);
......@@ -701,7 +722,7 @@ void usb_deregister_bus (struct usb_bus *bus)
clear_bit (bus->busnum, busmap.busmap);
usb_bus_put (bus);
class_device_unregister(&bus->class_dev);
}
EXPORT_SYMBOL (usb_deregister_bus);
......
......@@ -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 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 int usb_register_root_hub (struct usb_device *usb_dev,
......@@ -369,7 +368,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
extern struct list_head usb_bus_list;
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 int usb_find_interface_driver (struct usb_device *dev,
......
......@@ -54,6 +54,8 @@ extern int usb_hub_init(void);
extern void usb_hub_cleanup(void);
extern int usb_major_init(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 */
......@@ -652,11 +654,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset(dev, 0, sizeof(*dev));
bus = usb_bus_get(bus);
if (!bus) {
kfree(dev);
return NULL;
}
device_initialize(&dev->dev);
dev->state = USB_STATE_ATTACHED;
usb_bus_get(bus);
if (!parent)
dev->devpath [0] = '0';
dev->bus = bus;
......@@ -1531,6 +1537,7 @@ static int __init usb_init(void)
}
bus_register(&usb_bus_type);
usb_host_init();
usb_major_init();
usbfs_init();
usb_hub_init();
......@@ -1553,6 +1560,7 @@ static void __exit usb_exit(void)
usb_major_cleanup();
usbfs_cleanup();
usb_hub_cleanup();
usb_host_cleanup();
bus_unregister(&usb_bus_type);
}
......
......@@ -392,9 +392,10 @@ static void qh_lines (
}
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;
unsigned long flags;
unsigned temp, size;
......@@ -403,8 +404,9 @@ show_async (struct device *dev, char *buf)
*buf = 0;
pdev = container_of (dev, struct pci_dev, dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
size = PAGE_SIZE;
......@@ -427,14 +429,15 @@ show_async (struct device *dev, char *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
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;
unsigned long flags;
union ehci_shadow p, *seen;
......@@ -446,8 +449,9 @@ show_periodic (struct device *dev, char *buf)
return 0;
seen_count = 0;
pdev = container_of (dev, struct pci_dev, dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
size = PAGE_SIZE;
......@@ -535,14 +539,15 @@ show_periodic (struct device *dev, char *buf)
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
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;
unsigned long flags;
unsigned temp, size, i;
......@@ -550,9 +555,9 @@ show_registers (struct device *dev, char *buf)
static char fmt [] = "%*s\n";
static char label [] = "";
pdev = container_of (dev, struct pci_dev, dev);
ehci = container_of (pci_get_drvdata (pdev), struct ehci_hcd, hcd);
bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
size = PAGE_SIZE;
......@@ -562,7 +567,7 @@ show_registers (struct device *dev, char *buf)
i = readw (&ehci->caps->hci_version);
temp = snprintf (next, size,
"%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);
size -= temp;
next += temp;
......@@ -636,20 +641,20 @@ show_registers (struct device *dev, char *buf)
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)
{
device_create_file (&bus->hcd.pdev->dev, &dev_attr_async);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
device_create_file (&bus->hcd.pdev->dev, &dev_attr_registers);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
}
static inline void remove_debug_files (struct ehci_hcd *bus)
{
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic);
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
}
#endif /* STUB_DEBUG_FILES */
......
......@@ -1205,7 +1205,7 @@ static void hc_release_hci (hci_t * hci)
}
usb_deregister_bus (hci->bus);
usb_free_bus (hci->bus);
usb_put_bus (hci->bus);
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)
}
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;
size_t temp;
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 */
spin_lock_irqsave (&ohci->lock, flags);
......@@ -482,14 +486,16 @@ show_async (struct device *dev, char *buf)
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
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 ed **seen, *ed;
unsigned long flags;
......@@ -501,7 +507,9 @@ show_periodic (struct device *dev, char *buf)
return 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;
size = PAGE_SIZE;
......@@ -573,14 +581,16 @@ show_periodic (struct device *dev, char *buf)
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
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_regs *regs;
unsigned long flags;
......@@ -588,7 +598,9 @@ show_registers (struct device *dev, char *buf)
char *next;
u32 rdata;
ohci = dev_to_ohci(dev);
bus = to_usb_bus(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
regs = ohci->regs;
next = buf;
size = PAGE_SIZE;
......@@ -642,22 +654,22 @@ show_registers (struct device *dev, char *buf)
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)
{
device_create_file (bus->hcd.controller, &dev_attr_async);
device_create_file (bus->hcd.controller, &dev_attr_periodic);
device_create_file (bus->hcd.controller, &dev_attr_registers);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
ohci_dbg (bus, "created debug files\n");
}
static inline void remove_debug_files (struct ohci_hcd *bus)
{
device_remove_file (bus->hcd.controller, &dev_attr_async);
device_remove_file (bus->hcd.controller, &dev_attr_periodic);
device_remove_file (bus->hcd.controller, &dev_attr_registers);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
}
#endif
......
......@@ -1208,6 +1208,13 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
uhci_packetout(td_token(td)));
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) {
/* Some debugging code */
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)
lprintk(errbuf);
}
}
#endif
return ret;
}
......
......@@ -1701,6 +1701,15 @@ static const struct driver_info zaurus_slb500_info = {
.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
......@@ -2751,6 +2760,15 @@ static const struct usb_device_id products [] = {
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.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
......
......@@ -166,7 +166,11 @@ static int device_reset( Scsi_Cmnd *srb )
/* lock the device pointers and do the reset */
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));
/* lock access to the state and clear it */
......@@ -202,7 +206,7 @@ static int bus_reset( Scsi_Cmnd *srb )
down(&(us->dev_semaphore));
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
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) {
result = -EBUSY;
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)
us->current_urb->context = &urb_done;
us->current_urb->actual_length = 0;
us->current_urb->error_count = 0;
us->current_urb->transfer_flags = URB_ASYNC_UNLINK;
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 */
status = usb_submit_urb(us->current_urb, GFP_NOIO);
if (status) {
......@@ -207,15 +217,15 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
value, index, size);
/* fill in the devrequest structure */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
us->dr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
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);
status = usb_stor_msg_common(us, timeout);
......@@ -346,15 +356,15 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
value, index, size);
/* fill in the devrequest structure */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
us->dr->wValue = cpu_to_le16(value);
us->dr->wIndex = cpu_to_le16(index);
us->dr->wLength = cpu_to_le16(size);
us->cr->bRequestType = requesttype;
us->cr->bRequest = request;
us->cr->wValue = cpu_to_le16(value);
us->cr->wIndex = cpu_to_le16(index);
us->cr->wLength = cpu_to_le16(size);
/* fill and submit the URB */
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);
result = usb_stor_msg_common(us, 0);
......@@ -786,9 +796,9 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* 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->irqdata[0], us->irqdata[1]);
us->iobuf[0], us->iobuf[1]);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
......@@ -804,7 +814,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->cmnd[0] == INQUIRY)
return USB_STOR_TRANSPORT_GOOD;
else {
if (us->irqdata[0])
if (us->iobuf[0])
return USB_STOR_TRANSPORT_FAILED;
else
return USB_STOR_TRANSPORT_GOOD;
......@@ -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 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->irqdata[0]);
us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR;
}
switch (us->irqdata[1] & 0x0F) {
switch (us->iobuf[1] & 0x0F) {
case 0x00:
return USB_STOR_TRANSPORT_GOOD;
case 0x01:
......@@ -889,7 +899,6 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* Determine what the maximum LUN supported is */
int usb_stor_Bulk_max_lun(struct us_data *us)
{
unsigned char data;
int result;
/* issue the command */
......@@ -897,14 +906,14 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
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",
result, data);
result, us->iobuf[0]);
/* if we have a successful request, return the result */
if (result == 1)
return data;
return us->iobuf[0];
/* return the default -- no LUNs */
return 0;
......@@ -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)
{
struct bulk_cb_wrap bcb;
struct bulk_cs_wrap bcs;
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
unsigned int transfer_length = srb->request_bufflen;
int result;
int fake_sense = 0;
/* set up the command wrapper */
bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb.DataTransferLength = cpu_to_le32(transfer_length);
bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->device->lun;
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
bcb->Tag = srb->serial_number;
bcb->Lun = srb->device->lun;
if (us->flags & US_FL_SCM_MULT_TARG)
bcb.Lun |= srb->device->id << 4;
bcb.Length = srb->cmd_len;
bcb->Lun |= srb->device->id << 4;
bcb->Length = srb->cmd_len;
/* copy the command payload */
memset(bcb.CDB, 0, sizeof(bcb.CDB));
memcpy(bcb.CDB, srb->cmnd, bcb.Length);
memset(bcb->CDB, 0, sizeof(bcb->CDB));
memcpy(bcb->CDB, srb->cmnd, bcb->Length);
/* 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",
le32_to_cpu(bcb.Signature), bcb.Tag,
(bcb.Lun >> 4), (bcb.Lun & 0x0F),
le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
le32_to_cpu(bcb->Signature), bcb->Tag,
(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,
&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;
......@@ -972,7 +982,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,
&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) {
......@@ -980,7 +990,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,
&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 */
......@@ -990,17 +1000,18 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check bulk status */
US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
le32_to_cpu(bcs.Signature), bcs.Tag,
bcs.Residue, bcs.Status);
if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs.Tag != bcb.Tag ||
bcs.Status > US_BULK_STAT_PHASE) {
le32_to_cpu(bcs->Signature), bcs->Tag,
bcs->Residue, bcs->Status);
if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
bcs->Tag != srb->serial_number ||
bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
/* based on the status code, we report good or bad */
switch (bcs.Status) {
switch (bcs->Status) {
case US_BULK_STAT_OK:
/* device babbled -- return fake sense data */
if (fake_sense) {
......@@ -1065,6 +1076,10 @@ static int usb_stor_reset_common(struct us_data *us,
schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING);
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");
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
......@@ -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
*/
#define CB_RESET_CMD_SIZE 12
int usb_stor_CB_reset(struct us_data *us)
{
unsigned char cmd[12];
US_DEBUGP("CB_reset() called\n");
US_DEBUGP("%s called\n", __FUNCTION__);
memset(cmd, 0xFF, sizeof(cmd));
cmd[0] = SEND_DIAGNOSTIC;
cmd[1] = 4;
memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
us->iobuf[0] = SEND_DIAGNOSTIC;
us->iobuf[1] = 4;
return usb_stor_reset_common(us, US_CBI_ADSC,
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
......@@ -1102,7 +1117,7 @@ int usb_stor_CB_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,
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
......
......@@ -252,6 +252,14 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
US_SC_UFI, US_PR_CB, NULL,
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,
"Sony",
"Memorystick MSAC-US1",
......@@ -271,6 +279,12 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
US_SC_UFI, US_PR_CB, NULL,
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> */
UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999,
"Sony",
......@@ -295,26 +309,6 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
"USB Hard Disk",
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
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110,
"In-System",
......@@ -339,12 +333,6 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
"USB Storage Adapter V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
"Sony",
"Portable USB Harddrive V2",
US_SC_ISD200, US_PR_BULK, isd200_Initialization,
0 ),
#endif
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
......@@ -385,12 +373,6 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
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>
* Taken from the Lycoris Kernel */
UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
......@@ -431,7 +413,8 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
"Sandisk",
"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,
"Sandisk",
......@@ -520,13 +503,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
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
#ifdef CONFIG_USB_STORAGE_SDDR55
......@@ -538,6 +514,15 @@ UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999,
US_FL_FIX_INQUIRY ),
#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
* 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.
......@@ -563,6 +548,22 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
US_SC_8070, US_PR_CB, NULL,
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 */
UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
"Feiya",
......@@ -570,13 +571,6 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
US_SC_SCSI, US_PR_BULK, NULL,
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,
"Minds@Work",
"Digital Wallet",
......@@ -589,22 +583,26 @@ UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x0a16, 0x8888, 0x0100, 0x0100,
"IBM",
"IBM USB Memory Key",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* Pentax Optio S digital camera
* adapted from http://www2.goldfisch.at/knowledge/233
* (Peter Pilsl <pilsl@goldfisch.at>)
* by Christoph Weidemann <cweidema@indiana.edu> */
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
"Pentax",
"Optio S",
US_SC_8070, US_PR_CB, NULL,
US_FL_MODE_XLATE|US_FL_FIX_INQUIRY),
/* 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
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
......@@ -613,13 +611,6 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
0 ),
#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>
* Tested on hardware version 1.10.
* Entry is needed only for the initializer function override.
......@@ -648,13 +639,3 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_SC_SCSI, US_PR_SDDR55, NULL,
US_FL_SINGLE_LUN),
#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)
/* lock the device pointers */
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
* 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->srb->result = DID_ERROR << 16;
}
......@@ -421,12 +427,44 @@ static int usb_stor_control_thread(void * __us)
* 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 */
static void get_device_info(struct us_data *us, int id_index)
{
struct usb_device *dev = us->pusb_dev;
struct usb_host_interface *altsetting =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting];
struct usb_interface_descriptor *idesc =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[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)
/* Store the entries */
us->unusual_dev = unusual_dev;
us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
altsetting->desc.bInterfaceSubClass :
idesc->bInterfaceSubClass :
unusual_dev->useProtocol;
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
altsetting->desc.bInterfaceProtocol :
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
us->flags = unusual_dev->flags;
......@@ -455,20 +493,26 @@ static void get_device_info(struct us_data *us, int id_index)
"an unneeded SubClass entry",
"an unneeded Protocol entry",
"unneeded SubClass and Protocol entries"};
struct usb_device_descriptor *ddesc = &dev->descriptor;
int msg = -1;
if (unusual_dev->useProtocol != US_SC_DEVICE &&
us->subclass == altsetting->desc.bInterfaceSubClass)
us->subclass == idesc->bInterfaceSubClass)
msg += 1;
if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == altsetting->desc.bInterfaceProtocol)
us->protocol == idesc->bInterfaceProtocol)
msg += 2;
if (msg >= 0)
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 "
"<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 */
......@@ -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 */
if (strlen(us->vendor) == 0) {
if (unusual_dev->vendorName)
strncpy(us->vendor, unusual_dev->vendorName,
sizeof(us->vendor) - 1);
strlcpy(us->vendor, unusual_dev->vendorName,
sizeof(us->vendor));
else
strcpy(us->vendor, "Unknown");
}
if (strlen(us->product) == 0) {
if (unusual_dev->productName)
strncpy(us->product, unusual_dev->productName,
sizeof(us->product) - 1);
strlcpy(us->product, unusual_dev->productName,
sizeof(us->product));
else
strcpy(us->product, "Unknown");
}
......@@ -714,18 +758,9 @@ static int usb_stor_acquire_resources(struct us_data *us)
{
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);
if (!us->current_urb) {
US_DEBUGP("allocation failed\n");
US_DEBUGP("URB allocation failed\n");
return -ENOMEM;
}
......@@ -778,8 +813,24 @@ static void dissociate_dev(struct us_data *us)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
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_put_dev(us->pusb_dev);
us->pusb_dev = NULL;
us->pusb_intf = NULL;
up(&us->dev_semaphore);
......@@ -818,16 +869,11 @@ void usb_stor_release_resources(struct us_data *us)
us->extra_destructor(us->extra);
}
/* Destroy the extra data */
if (us->extra) {
/* Free the extra data and the URB */
if (us->extra)
kfree(us->extra);
}
/* Free the USB control blocks */
if (us->current_urb)
usb_free_urb(us->current_urb);
if (us->dr)
kfree(us->dr);
/* Free the structure itself */
kfree(us);
......@@ -857,15 +903,10 @@ static int storage_probe(struct usb_interface *intf,
init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify));
/* 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);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
if (result)
goto BadDevice;
/*
* Get the unusual_devs entries and the descriptors
......
......@@ -71,6 +71,7 @@ struct us_unusual_dev {
#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for
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_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
......@@ -92,6 +93,15 @@ struct us_unusual_dev {
#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_reset)(struct us_data*);
typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
......@@ -106,6 +116,7 @@ struct us_data {
struct semaphore dev_semaphore; /* protect pusb_dev */
struct usb_device *pusb_dev; /* this usb_device */
struct usb_interface *pusb_intf; /* this interface */
struct us_unusual_dev *unusual_dev; /* device-filter entry */
unsigned long flags; /* from filter initially */
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
......@@ -139,20 +150,19 @@ struct us_data {
int pid; /* control thread */
int sm_state; /* what we are doing */
/* interrupt communications data */
unsigned char irqdata[2]; /* data from USB IRQ */
/* control and bulk communications data */
struct urb *current_urb; /* non-int USB requests */
struct usb_ctrlrequest *dr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather USB */
/* the semaphore for sleeping the control thread */
struct semaphore sema; /* to sleep thread on */
struct urb *current_urb; /* USB requests */
struct usb_ctrlrequest *cr; /* control requests */
struct usb_sg_request current_sg; /* scatter-gather req. */
unsigned char *iobuf; /* I/O buffer */
dma_addr_t cr_dma; /* buffer DMA addresses */
dma_addr_t iobuf_dma;
/* mutual exclusion structures */
struct semaphore sema; /* to sleep thread on */
struct completion notify; /* thread begin/end */
struct us_unusual_dev *unusual_dev; /* If unusual device */
/* subdriver information */
void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */
};
......
......@@ -112,6 +112,7 @@ struct usb_skel {
struct completion write_finished; /* wait for the write to finish */
int open; /* if the port is open or not */
int present; /* if the device is not disconnected */
struct semaphore sem; /* locks this structure */
};
......@@ -296,7 +297,7 @@ static int skel_release (struct inode *inode, struct file *file)
dev->open = 0;
if (dev->udev == NULL) {
if (!dev->present) {
/* the device was unplugged before the file was released */
up (&dev->sem);
skel_delete (dev);
......@@ -326,7 +327,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
down (&dev->sem);
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
if (!dev->present) {
up (&dev->sem);
return -ENODEV;
}
......@@ -382,7 +383,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
down (&dev->sem);
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
if (!dev->present) {
retval = -ENODEV;
goto exit;
}
......@@ -452,7 +453,7 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
down (&dev->sem);
/* verify that the device wasn't unplugged */
if (dev->udev == NULL) {
if (!dev->present) {
up (&dev->sem);
return -ENODEV;
}
......@@ -507,8 +508,6 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
size_t buffer_size;
int i;
int retval;
char name[14];
/* See if the device offered us matches what we can accept */
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
*/
buffer_size = endpoint->wMaxPacketSize;
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);
dev->bulk_out_buffer = usb_buffer_alloc (udev,
buffer_size, GFP_KERNEL,
......@@ -601,6 +600,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
goto error;
}
/* allow device read, write and ioctl */
dev->present = 1;
/* let the user know what node this device is now attached to */
info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
......@@ -663,10 +665,12 @@ static void skel_disconnect(struct usb_interface *interface)
wait_for_completion (&dev->write_finished);
}
dev->udev = NULL;
/* prevent device read, write and ioctl */
dev->present = 0;
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)
skel_delete (dev);
......
......@@ -207,8 +207,10 @@ struct usb_bus {
struct dentry *usbfs_dentry; /* usbfs 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