Commit 4b59d1b2 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleeding_edge-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 22775da0 86b56955
......@@ -4,7 +4,13 @@
mainmenu_option next_comment
comment 'USB support'
dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" ]; then
tristate 'Support for USB' CONFIG_USB
else
define_bool CONFIG_USB n
fi
if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
source drivers/usb/core/Config.in
......
......@@ -6,9 +6,11 @@
mod-subdirs := serial
obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI) += host/
obj-$(CONFIG_USB_OHCI_SA1111) += host/
obj-$(CONFIG_USB_SL811HS) += host/
obj-$(CONFIG_USB_UHCI_ALT) += host/
obj-$(CONFIG_USB_UHCI_HCD_ALT) += host/
......
......@@ -20,5 +20,6 @@ fi
#fi
#dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB
fi
......@@ -3,6 +3,8 @@
# framework and drivers
#
export-objs := usb-ohci.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += usb-uhci-hcd.o
......@@ -10,7 +12,8 @@ obj-$(CONFIG_USB_UHCI_HCD_ALT) += uhci-hcd.o
obj-$(CONFIG_USB_UHCI) += usb-uhci.o
obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o usb-ohci-pci.o
obj-$(CONFIG_USB_OHCI_SA1111) += usb-ohci.o usb-ohci-sa1111.o
obj-$(CONFIG_USB_SL811HS) += hc_sl811.o
include $(TOPDIR)/Rules.make
This diff is collapsed.
/*
* linux/drivers/usb/usb-ohci-sa1111.c
*
* The outline of this code was taken from Brad Parkers <brad@heeltoe.com>
* original OHCI driver modifications, and reworked into a cleaner form
* by Russell King <rmk@arm.linux.org.uk>.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/errno.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/assabet.h>
#include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h>
#include "usb-ohci.h"
int __devinit
hc_add_ohci(struct pci_dev *dev, int irq, void *membase, unsigned long flags,
ohci_t **ohci, const char *name, const char *slot_name);
extern void hc_remove_ohci(ohci_t *ohci);
static ohci_t *sa1111_ohci;
static void __init sa1111_ohci_configure(void)
{
unsigned int usb_rst = 0;
if (machine_is_xp860() ||
machine_has_neponset() ||
machine_is_pfs168() ||
machine_is_badge4())
usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
/*
* Configure the power sense and control lines. Place the USB
* host controller in reset.
*/
USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
/*
* Now, carefully enable the USB clock, and take
* the USB host controller out of reset.
*/
SKPCR |= SKPCR_UCLKEN;
udelay(11);
USB_RESET = usb_rst;
}
static int __init sa1111_ohci_init(void)
{
int ret;
if (!sa1111)
return -ENODEV;
/*
* Request memory resources.
*/
// if (!request_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT, "usb-ohci"))
// return -EBUSY;
sa1111_ohci_configure();
/*
* Initialise the generic OHCI driver.
*/
ret = hc_add_ohci((struct pci_dev *)1, NIRQHCIM,
(void *)&USB_OHCI_OP_BASE, 0, &sa1111_ohci,
"usb-ohci", "sa1111");
if (ret == 0) {
if (hc_start (sa1111_ohci, &sa1111->dev) < 0) {
err ("can't start usb-%s", sa1111_ohci->slot_name);
hc_remove_ohci (sa1111_ohci);
return -EBUSY;
}
#ifdef DEBUG
ohci_dump (ohci, 1);
#endif
#ifdef CONFIG_SA1100_BADGE4
if (machine_is_badge4()) {
/* found the controller, so now power the bus */
badge4_set_5V(BADGE4_5V_USB, 1);
}
#endif
}
// else
// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
return ret;
}
static void __exit sa1111_ohci_exit(void)
{
hc_remove_ohci(sa1111_ohci);
/*
* Put the USB host controller into reset.
*/
USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET;
/*
* Stop the USB clock.
*/
SKPCR &= ~SKPCR_UCLKEN;
/*
* Release memory resources.
*/
// release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT);
#ifdef CONFIG_SA1100_BADGE4
if (machine_is_badge4()) {
badge4_set_5V(BADGE4_5V_USB, 0);
}
#endif
}
module_init(sa1111_ohci_init);
module_exit(sa1111_ohci_exit);
This diff is collapsed.
......@@ -403,6 +403,7 @@ typedef struct ohci {
/* PCI device handle, settings, ... */
struct pci_dev *ohci_dev;
const char *slot_name;
u8 pci_latency;
struct pci_pool *td_cache;
struct pci_pool *dev_cache;
......@@ -423,6 +424,10 @@ struct ohci_device {
// #define ohci_to_usb(ohci) ((ohci)->usb)
#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv)
/* For initializing controller (mask in an HCFS mode too) */
#define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
/* hcd */
/* endpoint */
static int ep_link(ohci_t * ohci, ed_t * ed);
......@@ -447,11 +452,6 @@ static int rh_init_int_timer(struct urb * urb);
# define OHCI_MEM_FLAGS 0
#endif
#ifndef CONFIG_PCI
# error "usb-ohci currently requires PCI-based controllers"
/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
#endif
/* Recover a TD/ED using its collision chain */
static void *
......@@ -641,3 +641,8 @@ dev_free (struct ohci *hc, struct ohci_device *dev)
pci_pool_free (hc->dev_cache, dev, dev->dma);
}
extern spinlock_t usb_ed_lock;
extern void dl_done_list (ohci_t * ohci, td_t * td_list);
extern td_t * dl_reverse_done_list (ohci_t * ohci);
......@@ -167,108 +167,6 @@ static void us_transfer_freecom(Scsi_Cmnd *srb, struct us_data* us, int transfer
srb->result = result;
}
#if 0
/* Write a value to an ide register. */
static int
freecom_ide_write (struct us_data *us, int reg, int value)
{
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_ide_out *ideout =
(struct freecom_ide_out *) extra->buffer;
int opipe;
int result, partial;
US_DEBUGP("IDE out 0x%02x <- 0x%02x\n", reg, value);
/* Get handles for both transports. */
opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
if (reg < 0 || reg > 8)
return USB_STOR_TRANSPORT_ERROR;
if (reg < 8)
reg |= 0x20;
else
reg = 0x0e;
ideout->Type = FCM_PACKET_IDE_WRITE | reg;
ideout->Pad = 0;
ideout->Value = cpu_to_le16 (value);
memset (ideout->Pad2, 0, sizeof (ideout->Pad2));
result = usb_stor_bulk_msg (us, ideout, opipe,
FCM_PACKET_LENGTH, &partial);
if (result != 0) {
if (result == -ENOENT)
return US_BULK_TRANSFER_ABORTED;
else
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
}
/* Read a value from an ide register. */
static int
freecom_ide_read (struct us_data *us, int reg, int *value)
{
freecom_udata_t extra = (freecom_udata_t) us->extra;
struct freecom_ide_in *idein =
(struct freecom_ide_in *) extra->buffer;
__u8 *buffer = extra->buffer;
int ipipe, opipe;
int result, partial;
int desired_length;
/* Get handles for both transports. */
opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);
if (reg < 0 || reg > 8)
return USB_STOR_TRANSPORT_ERROR;
if (reg < 8)
reg |= 0x10;
else
reg = 0x0e;
US_DEBUGP("IDE in request for register 0x%02x\n", reg);
idein->Type = FCM_PACKET_IDE_READ | reg;
memset (idein->Pad, 0, sizeof (idein->Pad));
result = usb_stor_bulk_msg (us, idein, opipe,
FCM_PACKET_LENGTH, &partial);
if (result != 0) {
if (result == -ENOENT)
return US_BULK_TRANSFER_ABORTED;
else
return USB_STOR_TRANSPORT_ERROR;
}
desired_length = 1;
if (reg == 0x10)
desired_length = 2;
result = usb_stor_bulk_msg (us, buffer, ipipe,
desired_length, &partial);
if (result != 0) {
if (result == -ENOENT)
return US_BULK_TRANSFER_ABORTED;
else
return USB_STOR_TRANSPORT_ERROR;
}
US_DEBUGP("IDE in partial is %d\n", partial);
if (desired_length == 1)
*value = buffer[0];
else
*value = le16_to_cpu (*(__u16 *) buffer);
US_DEBUGP("IDE in 0x%02x -> 0x%02x\n", reg, *value);
return USB_STOR_TRANSPORT_GOOD;
}
#endif
static int
freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
int ipipe, int opipe, int count)
......@@ -292,8 +190,8 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
US_DEBUGP ("Freecom readdata xpot failure: r=%d, p=%d\n",
result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_readdata(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -333,8 +231,8 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
US_DEBUGP ("Freecom writedata xpot failure: r=%d, p=%d\n",
result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* has the current command been aborted? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_writedata(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -396,8 +294,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -410,8 +308,9 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
US_DEBUGP("foo Status result %d %d\n", result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -448,8 +347,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -463,8 +362,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("bar Status result %d %d\n", result, partial);
/* -ENOENT -- we canceled this transfer */
if (result == -ENOENT) {
/* we canceled this transfer */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("freecom_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -524,7 +423,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
US_DEBUG(pdump ((void *) fst, partial));
if (result == -ENOENT) {
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP ("freecom_transport: transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......@@ -552,7 +452,8 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP("FCM: Waiting for status\n");
result = usb_stor_bulk_msg (us, fst, ipipe,
FCM_PACKET_LENGTH, &partial);
if (result == -ENOENT) {
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP ("freecom_transport: transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
......
......@@ -386,9 +386,9 @@ Scsi_Host_Template usb_stor_host_template = {
unsigned char usb_stor_sense_notready[18] = {
[0] = 0x70, /* current error */
[2] = 0x02, /* not ready */
[5] = 0x0a, /* additional length */
[10] = 0x04, /* not ready */
[11] = 0x03 /* manual intervention */
[7] = 0x0a, /* additional length */
[12] = 0x04, /* not ready */
[13] = 0x03 /* manual intervention */
};
#define USB_STOR_SCSI_SENSE_HDRSZ 4
......
......@@ -986,9 +986,11 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
clear_bit(IP_WANTED, &us->bitflags);
}
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_control_msg(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* STALL must be cleared when it is detected */
if (result == -EPIPE) {
......@@ -996,9 +998,12 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_control_msg(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
return USB_STOR_TRANSPORT_FAILED;
}
......@@ -1098,9 +1103,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* check the return code for the command */
US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
if (result < 0) {
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* a stall is a fatal condition from the device */
if (result == -EPIPE) {
......@@ -1108,9 +1115,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_clear_halt(us,
usb_sndctrlpipe(us->pusb_dev, 0));
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
return USB_STOR_TRANSPORT_FAILED;
}
......@@ -1215,18 +1224,22 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
&partial);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* if we stall, we need to clear it before we go on */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
result = usb_stor_clear_halt(us, pipe);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
result = -EPIPE;
} else if (result) {
/* unknown error -- we've got a problem */
......@@ -1259,36 +1272,44 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN,
&partial);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* did the attempt to read the CSW fail? */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
result = usb_stor_clear_halt(us, pipe);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_stor_bulk_msg(us, &bcs, pipe,
US_BULK_CS_WRAP_LEN, &partial);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
US_DEBUGP("clearing halt for pipe 0x%x\n", pipe);
result = usb_stor_clear_halt(us, pipe);
/* if the command was aborted, indicate that */
if (result == -ENOENT)
return USB_STOR_TRANSPORT_ABORTED;
/* did we abort this command? */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_Bulk_transport(): transfer aborted\n");
return US_BULK_TRANSFER_ABORTED;
}
return USB_STOR_TRANSPORT_ERROR;
}
}
......
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