Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
20b397bb
Commit
20b397bb
authored
Feb 03, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
46b11ba9
fb6d52e5
Changes
42
Show whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
1692 additions
and
1381 deletions
+1692
-1381
drivers/net/Kconfig
drivers/net/Kconfig
+8
-0
drivers/net/Makefile
drivers/net/Makefile
+4
-0
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.c
+2
-1
drivers/usb/core/devices.c
drivers/usb/core/devices.c
+1
-1
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+7
-4
drivers/usb/core/hcd.h
drivers/usb/core/hcd.h
+14
-0
drivers/usb/core/message.c
drivers/usb/core/message.c
+24
-7
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+17
-7
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-dbg.c
+74
-16
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+29
-16
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-mem.c
+0
-2
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-q.c
+83
-40
drivers/usb/host/ehci.h
drivers/usb/host/ehci.h
+5
-12
drivers/usb/host/hc_simple.c
drivers/usb/host/hc_simple.c
+1
-2
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hcd.c
+12
-12
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-mem.c
+1
-7
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-q.c
+17
-11
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+0
-1
drivers/usb/image/scanner.c
drivers/usb/image/scanner.c
+25
-7
drivers/usb/image/scanner.h
drivers/usb/image/scanner.h
+81
-62
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+9
-0
drivers/usb/misc/atmsar.c
drivers/usb/misc/atmsar.c
+79
-3
drivers/usb/misc/atmsar.h
drivers/usb/misc/atmsar.h
+3
-0
drivers/usb/misc/speedtouch.c
drivers/usb/misc/speedtouch.c
+421
-330
drivers/usb/net/Makefile.mii
drivers/usb/net/Makefile.mii
+5
-0
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+2
-0
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ftdi_sio.h
+3
-0
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipaq.c
+2
-0
drivers/usb/serial/ipaq.h
drivers/usb/serial/ipaq.h
+4
-0
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.c
+1
-0
drivers/usb/serial/pl2303.h
drivers/usb/serial/pl2303.h
+3
-0
drivers/usb/storage/datafab.h
drivers/usb/storage/datafab.h
+7
-7
drivers/usb/storage/freecom.c
drivers/usb/storage/freecom.c
+204
-204
drivers/usb/storage/isd200.c
drivers/usb/storage/isd200.c
+123
-123
drivers/usb/storage/protocol.h
drivers/usb/storage/protocol.h
+1
-1
drivers/usb/storage/scsiglue.c
drivers/usb/storage/scsiglue.c
+97
-88
drivers/usb/storage/scsiglue.h
drivers/usb/storage/scsiglue.h
+1
-1
drivers/usb/storage/transport.h
drivers/usb/storage/transport.h
+8
-9
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+5
-5
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+309
-362
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+0
-39
include/linux/usb.h
include/linux/usb.h
+0
-1
No files found.
drivers/net/Kconfig
View file @
20b397bb
...
@@ -212,6 +212,14 @@ config NET_ETHERNET
...
@@ -212,6 +212,14 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.
the questions about Ethernet network cards. If unsure, say N.
config MII
tristate "generic Media Independent Interface device support"
depends on NET_ETHERNET
help
Most ethernet controllers have MII transceiver either as an external
or internal device. It is safe to say Y or M here even if your
ethernet card lack MII.
config ARM_AM79C961A
config ARM_AM79C961A
bool "ARM EBSA110 AM79C961A support"
bool "ARM EBSA110 AM79C961A support"
depends on NET_ETHERNET && ARM && ARCH_EBSA110
depends on NET_ETHERNET && ARM && ARCH_EBSA110
...
...
drivers/net/Makefile
View file @
20b397bb
...
@@ -57,6 +57,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o mii.o
...
@@ -57,6 +57,7 @@ obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o mii.o
# end link order section
# end link order section
#
#
obj-$(CONFIG_MII)
+=
mii.o
obj-$(CONFIG_AIRONET4500)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500_CS)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500_CS)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500_NONCS)
+=
aironet4500_card.o
obj-$(CONFIG_AIRONET4500_NONCS)
+=
aironet4500_card.o
...
@@ -193,3 +194,6 @@ obj-$(CONFIG_NET_WIRELESS) += wireless/
...
@@ -193,3 +194,6 @@ obj-$(CONFIG_NET_WIRELESS) += wireless/
obj-$(CONFIG_NET_TULIP)
+=
tulip/
obj-$(CONFIG_NET_TULIP)
+=
tulip/
obj-$(CONFIG_HAMRADIO)
+=
hamradio/
obj-$(CONFIG_HAMRADIO)
+=
hamradio/
obj-$(CONFIG_IRDA)
+=
irda/
obj-$(CONFIG_IRDA)
+=
irda/
include
$(TOPDIR)/drivers/usb/net/Makefile.mii
drivers/usb/class/cdc-acm.c
View file @
20b397bb
...
@@ -257,7 +257,7 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
...
@@ -257,7 +257,7 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
if
(
urb
->
status
)
if
(
urb
->
status
)
dbg
(
"nonzero read bulk status received: %d"
,
urb
->
status
);
dbg
(
"nonzero read bulk status received: %d"
,
urb
->
status
);
if
(
!
urb
->
status
&
!
acm
->
throttle
)
{
if
(
!
urb
->
status
&
&
!
acm
->
throttle
)
{
for
(
i
=
0
;
i
<
urb
->
actual_length
&&
!
acm
->
throttle
;
i
++
)
{
for
(
i
=
0
;
i
<
urb
->
actual_length
&&
!
acm
->
throttle
;
i
++
)
{
/* if we insert more than TTY_FLIPBUF_SIZE characters,
/* if we insert more than TTY_FLIPBUF_SIZE characters,
* we drop them. */
* we drop them. */
...
@@ -697,6 +697,7 @@ static void acm_disconnect(struct usb_interface *intf)
...
@@ -697,6 +697,7 @@ static void acm_disconnect(struct usb_interface *intf)
static
struct
usb_device_id
acm_ids
[]
=
{
static
struct
usb_device_id
acm_ids
[]
=
{
{
USB_DEVICE_INFO
(
USB_CLASS_COMM
,
0
,
0
)
},
{
USB_DEVICE_INFO
(
USB_CLASS_COMM
,
0
,
0
)
},
{
USB_DEVICE_INFO
(
USB_CLASS_COMM
,
2
,
0
)
},
{
}
{
}
};
};
...
...
drivers/usb/core/devices.c
View file @
20b397bb
...
@@ -68,7 +68,7 @@
...
@@ -68,7 +68,7 @@
static
char
*
format_topo
=
static
char
*
format_topo
=
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
"
T: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d
\n
"
;
"
\n
T: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d
\n
"
;
static
char
*
format_string_manufacturer
=
static
char
*
format_string_manufacturer
=
/* S: Manufacturer=xxxx */
/* S: Manufacturer=xxxx */
...
...
drivers/usb/core/hcd.c
View file @
20b397bb
...
@@ -310,9 +310,9 @@ static int rh_string (
...
@@ -310,9 +310,9 @@ static int rh_string (
}
else
}
else
return
0
;
return
0
;
data
[
0
]
=
2
+
ascii2utf
(
buf
,
data
+
2
,
len
-
2
);
data
[
0
]
=
2
*
(
strlen
(
buf
)
+
1
);
data
[
1
]
=
3
;
/* type == string */
data
[
1
]
=
3
;
/* type == string */
return
data
[
0
]
;
return
2
+
ascii2utf
(
buf
,
data
+
2
,
len
-
2
)
;
}
}
...
@@ -1029,8 +1029,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
...
@@ -1029,8 +1029,11 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
return
status
;
return
status
;
}
}
/* lower level hcd code should use *_dma exclusively */
/* lower level hcd code should use *_dma exclusively,
if
(
!
(
urb
->
transfer_flags
&
URB_NO_DMA_MAP
))
{
* unless it uses pio or talks to another transport.
*/
if
(
!
(
urb
->
transfer_flags
&
URB_NO_DMA_MAP
)
&&
hcd
->
controller
->
dma_mask
)
{
if
(
usb_pipecontrol
(
urb
->
pipe
))
if
(
usb_pipecontrol
(
urb
->
pipe
))
urb
->
setup_dma
=
dma_map_single
(
urb
->
setup_dma
=
dma_map_single
(
hcd
->
controller
,
hcd
->
controller
,
...
...
drivers/usb/core/hcd.h
View file @
20b397bb
...
@@ -111,6 +111,13 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
...
@@ -111,6 +111,13 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
*/
*/
};
};
/* 2.4 does this a bit differently ... */
static
inline
struct
usb_bus
*
hcd_to_bus
(
struct
usb_hcd
*
hcd
)
{
return
&
hcd
->
self
;
}
struct
hcd_dev
{
/* usb_device.hcpriv points to this */
struct
hcd_dev
{
/* usb_device.hcpriv points to this */
struct
list_head
dev_list
;
/* on this hcd */
struct
list_head
dev_list
;
/* on this hcd */
struct
list_head
urb_list
;
/* pending on this dev */
struct
list_head
urb_list
;
/* pending on this dev */
...
@@ -343,6 +350,13 @@ extern void usb_deregister_bus (struct usb_bus *);
...
@@ -343,6 +350,13 @@ 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
,
struct
device
*
parent_dev
);
struct
device
*
parent_dev
);
/* for portability to 2.4, hcds should call this */
static
inline
int
hcd_register_root
(
struct
usb_hcd
*
hcd
)
{
return
usb_register_root_hub
(
hcd_to_bus
(
hcd
)
->
root_hub
,
hcd
->
controller
);
}
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
/* exported only within usbcore */
...
...
drivers/usb/core/message.c
View file @
20b397bb
...
@@ -206,6 +206,7 @@ static void sg_clean (struct usb_sg_request *io)
...
@@ -206,6 +206,7 @@ static void sg_clean (struct usb_sg_request *io)
kfree
(
io
->
urbs
);
kfree
(
io
->
urbs
);
io
->
urbs
=
0
;
io
->
urbs
=
0
;
}
}
if
(
io
->
dev
->
dev
.
dma_mask
!=
0
)
usb_buffer_unmap_sg
(
io
->
dev
,
io
->
pipe
,
io
->
sg
,
io
->
nents
);
usb_buffer_unmap_sg
(
io
->
dev
,
io
->
pipe
,
io
->
sg
,
io
->
nents
);
io
->
dev
=
0
;
io
->
dev
=
0
;
}
}
...
@@ -301,6 +302,7 @@ int usb_sg_init (
...
@@ -301,6 +302,7 @@ int usb_sg_init (
{
{
int
i
;
int
i
;
int
urb_flags
;
int
urb_flags
;
int
dma
;
if
(
!
io
||
!
dev
||
!
sg
if
(
!
io
||
!
dev
||
!
sg
||
usb_pipecontrol
(
pipe
)
||
usb_pipecontrol
(
pipe
)
...
@@ -314,8 +316,16 @@ int usb_sg_init (
...
@@ -314,8 +316,16 @@ int usb_sg_init (
io
->
sg
=
sg
;
io
->
sg
=
sg
;
io
->
nents
=
nents
;
io
->
nents
=
nents
;
/* initialize all the urbs we'll use */
/* not all host controllers use DMA (like the mainstream pci ones);
* they can use PIO (sl811) or be software over another transport.
*/
dma
=
(
dev
->
dev
.
dma_mask
!=
0
);
if
(
dma
)
io
->
entries
=
usb_buffer_map_sg
(
dev
,
pipe
,
sg
,
nents
);
io
->
entries
=
usb_buffer_map_sg
(
dev
,
pipe
,
sg
,
nents
);
else
io
->
entries
=
nents
;
/* initialize all the urbs we'll use */
if
(
io
->
entries
<=
0
)
if
(
io
->
entries
<=
0
)
return
io
->
entries
;
return
io
->
entries
;
...
@@ -347,8 +357,17 @@ int usb_sg_init (
...
@@ -347,8 +357,17 @@ int usb_sg_init (
io
->
urbs
[
i
]
->
status
=
-
EINPROGRESS
;
io
->
urbs
[
i
]
->
status
=
-
EINPROGRESS
;
io
->
urbs
[
i
]
->
actual_length
=
0
;
io
->
urbs
[
i
]
->
actual_length
=
0
;
if
(
dma
)
{
/* hc may use _only_ transfer_dma */
io
->
urbs
[
i
]
->
transfer_dma
=
sg_dma_address
(
sg
+
i
);
io
->
urbs
[
i
]
->
transfer_dma
=
sg_dma_address
(
sg
+
i
);
len
=
sg_dma_len
(
sg
+
i
);
len
=
sg_dma_len
(
sg
+
i
);
}
else
{
/* hc may use _only_ transfer_buffer */
io
->
urbs
[
i
]
->
transfer_buffer
=
page_address
(
sg
[
i
].
page
)
+
sg
[
i
].
offset
;
len
=
sg
[
i
].
length
;
}
if
(
length
)
{
if
(
length
)
{
len
=
min_t
(
unsigned
,
len
,
length
);
len
=
min_t
(
unsigned
,
len
,
length
);
length
-=
len
;
length
-=
len
;
...
@@ -434,9 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io)
...
@@ -434,9 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io)
retval
=
0
;
retval
=
0
;
i
--
;
i
--
;
// FIXME: should it usb_sg_cancel() on INTERRUPT?
// FIXME: should it usb_sg_cancel() on INTERRUPT?
// how about imposing a backoff?
yield
();
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
break
;
break
;
/* no error? continue immediately.
/* no error? continue immediately.
...
...
drivers/usb/core/usb.c
View file @
20b397bb
...
@@ -1224,7 +1224,8 @@ void usb_buffer_free (
...
@@ -1224,7 +1224,8 @@ void usb_buffer_free (
*
*
* Return value is either null (indicating no buffer could be mapped), or
* Return value is either null (indicating no buffer could be mapped), or
* the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the
* the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the
* operation succeeds.
* operation succeeds. If the device is connected to this system through
* a non-DMA controller, this operation always succeeds.
*
*
* This call would normally be used for an urb which is reused, perhaps
* This call would normally be used for an urb which is reused, perhaps
* as the target of a large periodic transfer, with usb_buffer_dmasync()
* as the target of a large periodic transfer, with usb_buffer_dmasync()
...
@@ -1245,12 +1246,15 @@ struct urb *usb_buffer_map (struct urb *urb)
...
@@ -1245,12 +1246,15 @@ struct urb *usb_buffer_map (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
))
return
0
;
return
0
;
if
(
controller
->
dma_mask
)
{
urb
->
transfer_dma
=
dma_map_single
(
controller
,
urb
->
transfer_dma
=
dma_map_single
(
controller
,
urb
->
transfer_buffer
,
urb
->
transfer_buffer_length
,
urb
->
transfer_buffer
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
usb_pipein
(
urb
->
pipe
)
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
// FIXME generic api broken like pci, can't report errors
// FIXME generic api broken like pci, can't report errors
// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
}
else
urb
->
transfer_dma
=
~
0
;
urb
->
transfer_flags
|=
URB_NO_DMA_MAP
;
urb
->
transfer_flags
|=
URB_NO_DMA_MAP
;
return
urb
;
return
urb
;
}
}
...
@@ -1271,6 +1275,7 @@ void usb_buffer_dmasync (struct urb *urb)
...
@@ -1271,6 +1275,7 @@ void usb_buffer_dmasync (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
))
return
;
return
;
if
(
controller
->
dma_mask
)
dma_sync_single
(
controller
,
dma_sync_single
(
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
usb_pipein
(
urb
->
pipe
)
...
@@ -1295,10 +1300,12 @@ void usb_buffer_unmap (struct urb *urb)
...
@@ -1295,10 +1300,12 @@ void usb_buffer_unmap (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
))
return
;
return
;
if
(
controller
->
dma_mask
)
dma_unmap_single
(
controller
,
dma_unmap_single
(
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
usb_pipein
(
urb
->
pipe
)
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
urb
->
transfer_flags
&=
~
URB_NO_DMA_MAP
;
}
}
/**
/**
...
@@ -1336,7 +1343,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
...
@@ -1336,7 +1343,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
if
(
!
dev
if
(
!
dev
||
usb_pipecontrol
(
pipe
)
||
usb_pipecontrol
(
pipe
)
||
!
(
bus
=
dev
->
bus
)
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
-
1
;
return
-
1
;
// FIXME generic api broken like pci, can't report errors
// FIXME generic api broken like pci, can't report errors
...
@@ -1362,7 +1370,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
...
@@ -1362,7 +1370,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
if
(
!
dev
if
(
!
dev
||
!
(
bus
=
dev
->
bus
)
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
;
return
;
dma_sync_sg
(
controller
,
sg
,
n_hw_ents
,
dma_sync_sg
(
controller
,
sg
,
n_hw_ents
,
...
@@ -1386,7 +1395,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
...
@@ -1386,7 +1395,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
if
(
!
dev
if
(
!
dev
||
!
(
bus
=
dev
->
bus
)
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
;
return
;
dma_unmap_sg
(
controller
,
sg
,
n_hw_ents
,
dma_unmap_sg
(
controller
,
sg
,
n_hw_ents
,
...
...
drivers/usb/host/ehci-dbg.c
View file @
20b397bb
...
@@ -277,7 +277,26 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
...
@@ -277,7 +277,26 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
default: tmp = '?'; break; \
default: tmp = '?'; break; \
}; tmp; })
}; tmp; })
static
void
qh_lines
(
struct
ehci_qh
*
qh
,
char
**
nextp
,
unsigned
*
sizep
)
static
inline
char
token_mark
(
u32
token
)
{
token
=
le32_to_cpu
(
token
);
if
(
token
&
QTD_STS_ACTIVE
)
return
'*'
;
if
(
token
&
QTD_STS_HALT
)
return
'-'
;
if
(
QTD_PID
(
token
)
!=
1
/* not IN: OUT or SETUP */
||
QTD_LENGTH
(
token
)
==
0
)
return
' '
;
/* tries to advance through hw_alt_next */
return
'/'
;
}
static
void
qh_lines
(
struct
ehci_hcd
*
ehci
,
struct
ehci_qh
*
qh
,
char
**
nextp
,
unsigned
*
sizep
)
{
{
u32
scratch
;
u32
scratch
;
u32
hw_curr
;
u32
hw_curr
;
...
@@ -286,26 +305,49 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
...
@@ -286,26 +305,49 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
unsigned
temp
;
unsigned
temp
;
unsigned
size
=
*
sizep
;
unsigned
size
=
*
sizep
;
char
*
next
=
*
nextp
;
char
*
next
=
*
nextp
;
char
mark
;
mark
=
token_mark
(
qh
->
hw_token
);
if
(
mark
==
'/'
)
{
/* qh_alt_next controls qh advance? */
if
((
qh
->
hw_alt_next
&
QTD_MASK
)
==
ehci
->
async
->
hw_alt_next
)
mark
=
'#'
;
/* blocked */
else
if
(
qh
->
hw_alt_next
&
cpu_to_le32
(
0x01
))
mark
=
'.'
;
/* use hw_qtd_next */
/* else alt_next points to some other qtd */
}
scratch
=
cpu_to_le32p
(
&
qh
->
hw_info1
);
scratch
=
cpu_to_le32p
(
&
qh
->
hw_info1
);
hw_curr
=
cpu_to_le32p
(
&
qh
->
hw_current
)
;
hw_curr
=
(
mark
==
'*'
)
?
cpu_to_le32p
(
&
qh
->
hw_current
)
:
0
;
temp
=
snprintf
(
next
,
size
,
temp
=
snprintf
(
next
,
size
,
"qh/%p dev%d %cs ep%d %08x %08x (%08x
%08x
)"
,
"qh/%p dev%d %cs ep%d %08x %08x (%08x
%c %s nak%d
)"
,
qh
,
scratch
&
0x007f
,
qh
,
scratch
&
0x007f
,
speed_char
(
scratch
),
speed_char
(
scratch
),
(
scratch
>>
8
)
&
0x000f
,
(
scratch
>>
8
)
&
0x000f
,
scratch
,
cpu_to_le32p
(
&
qh
->
hw_info2
),
scratch
,
cpu_to_le32p
(
&
qh
->
hw_info2
),
hw_curr
,
cpu_to_le32p
(
&
qh
->
hw_token
));
cpu_to_le32p
(
&
qh
->
hw_token
),
mark
,
(
cpu_to_le32
(
0x8000000
)
&
qh
->
hw_token
)
?
"data0"
:
"data1"
,
(
cpu_to_le32p
(
&
qh
->
hw_alt_next
)
>>
1
)
&
0x0f
);
size
-=
temp
;
size
-=
temp
;
next
+=
temp
;
next
+=
temp
;
/* hc may be modifying the list as we read it ... */
list_for_each
(
entry
,
&
qh
->
qtd_list
)
{
list_for_each
(
entry
,
&
qh
->
qtd_list
)
{
td
=
list_entry
(
entry
,
struct
ehci_qtd
,
qtd_list
);
td
=
list_entry
(
entry
,
struct
ehci_qtd
,
qtd_list
);
scratch
=
cpu_to_le32p
(
&
td
->
hw_token
);
scratch
=
cpu_to_le32p
(
&
td
->
hw_token
);
mark
=
' '
;
if
(
hw_curr
==
td
->
qtd_dma
)
mark
=
'*'
;
else
if
(
qh
->
hw_qtd_next
==
td
->
qtd_dma
)
mark
=
'+'
;
else
if
(
QTD_LENGTH
(
scratch
))
{
if
(
td
->
hw_alt_next
==
ehci
->
async
->
hw_alt_next
)
mark
=
'#'
;
else
if
(
td
->
hw_alt_next
!=
EHCI_LIST_END
)
mark
=
'/'
;
}
temp
=
snprintf
(
next
,
size
,
temp
=
snprintf
(
next
,
size
,
"
\n\t
%std/%p %s len=%d %08x urb %p"
,
"
\n\t
%p%c%s len=%d %08x urb %p"
,
(
hw_curr
==
td
->
qtd_dma
)
?
"*"
:
""
,
td
,
mark
,
({
char
*
tmp
;
td
,
({
char
*
tmp
;
switch
((
scratch
>>
8
)
&
0x03
)
{
switch
((
scratch
>>
8
)
&
0x03
)
{
case
0
:
tmp
=
"out"
;
break
;
case
0
:
tmp
=
"out"
;
break
;
case
1
:
tmp
=
"in"
;
break
;
case
1
:
tmp
=
"in"
;
break
;
...
@@ -315,13 +357,27 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
...
@@ -315,13 +357,27 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
(
scratch
>>
16
)
&
0x7fff
,
(
scratch
>>
16
)
&
0x7fff
,
scratch
,
scratch
,
td
->
urb
);
td
->
urb
);
if
(
temp
<
0
)
temp
=
0
;
else
if
(
size
<
temp
)
temp
=
size
;
size
-=
temp
;
size
-=
temp
;
next
+=
temp
;
next
+=
temp
;
if
(
temp
==
size
)
goto
done
;
}
}
temp
=
snprintf
(
next
,
size
,
"
\n
"
);
temp
=
snprintf
(
next
,
size
,
"
\n
"
);
*
sizep
=
size
-
temp
;
if
(
temp
<
0
)
*
nextp
=
next
+
temp
;
temp
=
0
;
else
if
(
size
<
temp
)
temp
=
size
;
size
-=
temp
;
next
+=
temp
;
done:
*
sizep
=
size
;
*
nextp
=
next
;
}
}
static
ssize_t
static
ssize_t
...
@@ -344,14 +400,15 @@ show_async (struct device *dev, char *buf)
...
@@ -344,14 +400,15 @@ show_async (struct device *dev, char *buf)
* one QH per line, and TDs we know about
* one QH per line, and TDs we know about
*/
*/
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
for
(
qh
=
ehci
->
async
->
qh_next
.
qh
;
qh
;
qh
=
qh
->
qh_next
.
qh
)
for
(
qh
=
ehci
->
async
->
qh_next
.
qh
;
size
>
0
&&
qh
;
qh
=
qh
->
qh_next
.
qh
)
qh_lines
(
qh
,
&
next
,
&
size
);
qh_lines
(
ehci
,
qh
,
&
next
,
&
size
);
if
(
ehci
->
reclaim
)
{
if
(
ehci
->
reclaim
&&
size
>
0
)
{
temp
=
snprintf
(
next
,
size
,
"
\n
reclaim =
\n
"
);
temp
=
snprintf
(
next
,
size
,
"
\n
reclaim =
\n
"
);
size
-=
temp
;
size
-=
temp
;
next
+=
temp
;
next
+=
temp
;
qh_lines
(
ehci
->
reclaim
,
&
next
,
&
size
);
for
(
qh
=
ehci
->
reclaim
;
size
>
0
&&
qh
;
qh
=
qh
->
reclaim
)
qh_lines
(
ehci
,
qh
,
&
next
,
&
size
);
}
}
spin_unlock_irqrestore
(
&
ehci
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
ehci
->
lock
,
flags
);
...
@@ -421,7 +478,7 @@ show_periodic (struct device *dev, char *buf)
...
@@ -421,7 +478,7 @@ show_periodic (struct device *dev, char *buf)
scratch
&
0x007f
,
scratch
&
0x007f
,
(
scratch
>>
8
)
&
0x000f
,
(
scratch
>>
8
)
&
0x000f
,
p
.
qh
->
usecs
,
p
.
qh
->
c_usecs
,
p
.
qh
->
usecs
,
p
.
qh
->
c_usecs
,
scratch
>>
16
);
0x7ff
&
(
scratch
>>
16
)
);
/* FIXME TD info too */
/* FIXME TD info too */
...
@@ -490,7 +547,8 @@ show_registers (struct device *dev, char *buf)
...
@@ -490,7 +547,8 @@ show_registers (struct device *dev, char *buf)
/* Capability Registers */
/* Capability Registers */
i
=
readw
(
&
ehci
->
caps
->
hci_version
);
i
=
readw
(
&
ehci
->
caps
->
hci_version
);
temp
=
snprintf
(
next
,
size
,
"EHCI %x.%02x, hcd state %d
\n
"
,
temp
=
snprintf
(
next
,
size
,
"EHCI %x.%02x, hcd state %d (version "
DRIVER_VERSION
")
\n
"
,
i
>>
8
,
i
&
0x0ff
,
ehci
->
hcd
.
state
);
i
>>
8
,
i
&
0x0ff
,
ehci
->
hcd
.
state
);
size
-=
temp
;
size
-=
temp
;
next
+=
temp
;
next
+=
temp
;
...
...
drivers/usb/host/ehci-hcd.c
View file @
20b397bb
...
@@ -94,7 +94,7 @@
...
@@ -94,7 +94,7 @@
* 2001-June Works with usb-storage and NEC EHCI on 2.4
* 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
*/
#define DRIVER_VERSION "200
2-Nov-29
"
#define DRIVER_VERSION "200
3-Jan-22
"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
...
@@ -110,10 +110,11 @@ static const char hcd_name [] = "ehci-hcd";
...
@@ -110,10 +110,11 @@ static const char hcd_name [] = "ehci-hcd";
/* magic numbers that can affect system performance */
/* magic numbers that can affect system performance */
#define EHCI_TUNE_CERR 3
/* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_CERR 3
/* 0-3 qtd retries; 0 == don't stop */
#define EHCI_TUNE_RL_HS
0
/* nak throttle; see 4.9 */
#define EHCI_TUNE_RL_HS
4
/* nak throttle; see 4.9 */
#define EHCI_TUNE_RL_TT 0
#define EHCI_TUNE_RL_TT 0
#define EHCI_TUNE_MULT_HS 1
/* 1-3 transactions/uframe; 4.10.3 */
#define EHCI_TUNE_MULT_HS 1
/* 1-3 transactions/uframe; 4.10.3 */
#define EHCI_TUNE_MULT_TT 1
#define EHCI_TUNE_MULT_TT 1
#define EHCI_TUNE_FLS 2
/* (small) 256 frame schedule */
#define EHCI_WATCHDOG_JIFFIES (HZ/100)
/* arbitrary; ~10 msec */
#define EHCI_WATCHDOG_JIFFIES (HZ/100)
/* arbitrary; ~10 msec */
#define EHCI_ASYNC_JIFFIES (HZ/20)
/* async idle timeout */
#define EHCI_ASYNC_JIFFIES (HZ/20)
/* async idle timeout */
...
@@ -416,13 +417,26 @@ static int ehci_start (struct usb_hcd *hcd)
...
@@ -416,13 +417,26 @@ static int ehci_start (struct usb_hcd *hcd)
ehci_info
(
ehci
,
"enabled 64bit PCI DMA
\n
"
);
ehci_info
(
ehci
,
"enabled 64bit PCI DMA
\n
"
);
}
}
/* help hc dma work well with cachelines */
pci_set_mwi
(
ehci
->
hcd
.
pdev
);
/* clear interrupt enables, set irq latency */
/* clear interrupt enables, set irq latency */
temp
=
readl
(
&
ehci
->
regs
->
command
)
&
0xff
;
temp
=
readl
(
&
ehci
->
regs
->
command
)
&
0xff
;
if
(
log2_irq_thresh
<
0
||
log2_irq_thresh
>
6
)
if
(
log2_irq_thresh
<
0
||
log2_irq_thresh
>
6
)
log2_irq_thresh
=
0
;
log2_irq_thresh
=
0
;
temp
|=
1
<<
(
16
+
log2_irq_thresh
);
temp
|=
1
<<
(
16
+
log2_irq_thresh
);
// if hc can park (ehci >= 0.96), default is 3 packets per async QH
// if hc can park (ehci >= 0.96), default is 3 packets per async QH
// keeping default periodic framelist size
if
(
HCC_PGM_FRAMELISTLEN
(
hcc_params
))
{
/* periodic schedule size can be smaller than default */
temp
&=
~
(
3
<<
2
);
temp
|=
(
EHCI_TUNE_FLS
<<
2
);
switch
(
EHCI_TUNE_FLS
)
{
case
0
:
ehci
->
periodic_size
=
1024
;
break
;
case
1
:
ehci
->
periodic_size
=
512
;
break
;
case
2
:
ehci
->
periodic_size
=
256
;
break
;
default:
BUG
();
}
}
temp
&=
~
(
CMD_IAAD
|
CMD_ASE
|
CMD_PSE
),
temp
&=
~
(
CMD_IAAD
|
CMD_ASE
|
CMD_PSE
),
// Philips, Intel, and maybe others need CMD_RUN before the
// Philips, Intel, and maybe others need CMD_RUN before the
// root hub will detect new devices (why?); NEC doesn't
// root hub will detect new devices (why?); NEC doesn't
...
@@ -759,7 +773,6 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
...
@@ -759,7 +773,6 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
struct
ehci_qh
*
qh
;
struct
ehci_qh
*
qh
;
unsigned
long
flags
;
unsigned
long
flags
;
int
maybe_irq
=
1
;
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
switch
(
usb_pipetype
(
urb
->
pipe
))
{
switch
(
usb_pipetype
(
urb
->
pipe
))
{
...
@@ -769,23 +782,23 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
...
@@ -769,23 +782,23 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
qh
=
(
struct
ehci_qh
*
)
urb
->
hcpriv
;
qh
=
(
struct
ehci_qh
*
)
urb
->
hcpriv
;
if
(
!
qh
)
if
(
!
qh
)
break
;
break
;
while
(
qh
->
qh_state
==
QH_STATE_LINKED
/* if we need to use IAA and it's busy, defer */
if
(
qh
->
qh_state
==
QH_STATE_LINKED
&&
ehci
->
reclaim
&&
ehci
->
reclaim
&&
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
&&
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
)
{
)
{
s
pin_unlock_irqrestore
(
&
ehci
->
lock
,
flags
)
;
s
truct
ehci_qh
*
last
;
if
(
maybe_irq
)
{
for
(
last
=
ehci
->
reclaim
;
if
(
in_interrupt
())
last
->
reclaim
;
return
-
EAGAIN
;
last
=
last
->
reclaim
)
maybe_irq
=
0
;
continue
;
}
qh
->
qh_state
=
QH_STATE_UNLINK_WAIT
;
/* let pending unlinks complete, so this can start */
last
->
reclaim
=
qh
;
wait_ms
(
1
);
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
/* bypass IAA if the hc can't care */
}
}
else
if
(
!
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
&&
ehci
->
reclaim
)
if
(
!
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
&&
ehci
->
reclaim
)
end_unlink_async
(
ehci
,
NULL
);
end_unlink_async
(
ehci
,
NULL
);
/* something else might have unlinked the qh by now */
/* something else might have unlinked the qh by now */
...
...
drivers/usb/host/ehci-mem.c
View file @
20b397bb
...
@@ -75,8 +75,6 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
...
@@ -75,8 +75,6 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
qtd
=
pci_pool_alloc
(
ehci
->
qtd_pool
,
flags
,
&
dma
);
qtd
=
pci_pool_alloc
(
ehci
->
qtd_pool
,
flags
,
&
dma
);
if
(
qtd
!=
0
)
{
if
(
qtd
!=
0
)
{
ehci_qtd_init
(
qtd
,
dma
);
ehci_qtd_init
(
qtd
,
dma
);
if
(
ehci
->
async
)
qtd
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
}
}
return
qtd
;
return
qtd
;
}
}
...
...
drivers/usb/host/ehci-q.c
View file @
20b397bb
...
@@ -43,7 +43,8 @@
...
@@ -43,7 +43,8 @@
/* fill a qtd, returning how much of the buffer we were able to queue up */
/* fill a qtd, returning how much of the buffer we were able to queue up */
static
int
static
int
qtd_fill
(
struct
ehci_qtd
*
qtd
,
dma_addr_t
buf
,
size_t
len
,
int
token
)
qtd_fill
(
struct
ehci_qtd
*
qtd
,
dma_addr_t
buf
,
size_t
len
,
int
token
,
int
maxpacket
)
{
{
int
i
,
count
;
int
i
,
count
;
u64
addr
=
buf
;
u64
addr
=
buf
;
...
@@ -69,6 +70,10 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
...
@@ -69,6 +70,10 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
else
else
count
=
len
;
count
=
len
;
}
}
/* short packets may only terminate transfers */
if
(
count
!=
len
)
count
-=
(
count
%
maxpacket
);
}
}
qtd
->
hw_token
=
cpu_to_le32
((
count
<<
16
)
|
token
);
qtd
->
hw_token
=
cpu_to_le32
((
count
<<
16
)
|
token
);
qtd
->
length
=
count
;
qtd
->
length
=
count
;
...
@@ -85,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
...
@@ -85,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
{
{
qh
->
hw_current
=
0
;
qh
->
hw_current
=
0
;
qh
->
hw_qtd_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
qh
->
hw_qtd_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
qh
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
qh
->
hw_alt_next
=
EHCI_LIST_END
;
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
wmb
();
wmb
();
...
@@ -96,7 +101,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
...
@@ -96,7 +101,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
static
inline
void
qtd_copy_status
(
static
void
qtd_copy_status
(
struct
ehci_hcd
*
ehci
,
struct
ehci_hcd
*
ehci
,
struct
urb
*
urb
,
struct
urb
*
urb
,
size_t
length
,
size_t
length
,
...
@@ -224,12 +229,24 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
...
@@ -224,12 +229,24 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
{
{
struct
ehci_qtd
*
last
=
0
,
*
end
=
qh
->
dummy
;
struct
ehci_qtd
*
last
=
0
,
*
end
=
qh
->
dummy
;
struct
list_head
*
entry
,
*
tmp
;
struct
list_head
*
entry
,
*
tmp
;
int
stopped
=
0
;
int
stopped
;
unsigned
count
=
0
;
unsigned
count
=
0
;
int
do_status
=
0
;
u8
state
;
if
(
unlikely
(
list_empty
(
&
qh
->
qtd_list
)))
if
(
unlikely
(
list_empty
(
&
qh
->
qtd_list
)))
return
count
;
return
count
;
/* completions (or tasks on other cpus) must never clobber HALT
* till we've gone through and cleaned everything up, even when
* they add urbs to this qh's queue or mark them for unlinking.
*
* NOTE: unlinking expects to be done in queue order.
*/
state
=
qh
->
qh_state
;
qh
->
qh_state
=
QH_STATE_COMPLETING
;
stopped
=
(
state
==
QH_STATE_IDLE
);
/* remove de-activated QTDs from front of queue.
/* remove de-activated QTDs from front of queue.
* after faults (including short reads), cleanup this urb
* after faults (including short reads), cleanup this urb
* then let the queue advance.
* then let the queue advance.
...
@@ -261,7 +278,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
...
@@ -261,7 +278,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
rmb
();
rmb
();
token
=
le32_to_cpu
(
qtd
->
hw_token
);
token
=
le32_to_cpu
(
qtd
->
hw_token
);
stopped
=
stopped
stopped
=
stopped
||
(
qh
->
qh_state
==
QH_STATE_IDLE
)
||
(
HALT_BIT
&
qh
->
hw_token
)
!=
0
||
(
HALT_BIT
&
qh
->
hw_token
)
!=
0
||
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
);
||
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
);
...
@@ -271,36 +287,53 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
...
@@ -271,36 +287,53 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
/* magic dummy for short reads; won't advance */
/* magic dummy for short reads; won't advance */
if
(
IS_SHORT_READ
(
token
)
if
(
IS_SHORT_READ
(
token
)
&&
!
(
token
&
QTD_STS_HALT
)
&&
!
(
token
&
QTD_STS_HALT
)
&&
ehci
->
async
->
hw_alt_next
&&
(
qh
->
hw_alt_next
&
QTD_MASK
)
==
qh
->
hw_alt_next
)
==
ehci
->
async
->
hw_alt_next
)
{
stopped
=
1
;
goto
halt
;
goto
halt
;
}
/* stop scanning when we reach qtds the hc is using */
/* stop scanning when we reach qtds the hc is using */
}
else
if
(
likely
(
!
stopped
))
{
}
else
if
(
likely
(
!
stopped
))
{
last
=
0
;
break
;
break
;
}
else
{
}
else
{
/* ignore active
qtd
s unless some previous qtd
/* ignore active
urb
s unless some previous qtd
* for the urb faulted (including short read) or
* for the urb faulted (including short read) or
* its urb was canceled. we may patch qh or qtds.
* its urb was canceled. we may patch qh or qtds.
*/
*/
if
((
token
&
QTD_STS_ACTIVE
)
if
(
likely
(
urb
->
status
==
-
EINPROGRESS
))
&&
urb
->
status
==
-
EINPROGRESS
)
{
continue
;
last
=
0
;
/* issue status after short control reads */
if
(
unlikely
(
do_status
!=
0
)
&&
QTD_PID
(
token
)
==
0
/* OUT */
)
{
do_status
=
0
;
continue
;
continue
;
}
}
/* token in overlay may be most current */
if
(
state
==
QH_STATE_IDLE
&&
cpu_to_le32
(
qtd
->
qtd_dma
)
==
qh
->
hw_current
)
token
=
le32_to_cpu
(
qh
->
hw_token
);
/* force halt for unlinked or blocked qh, so we'll
* patch the qh later and so that completions can't
* activate it while we "know" it's stopped.
*/
if
((
HALT_BIT
&
qh
->
hw_token
)
==
0
)
{
if
((
HALT_BIT
&
qh
->
hw_token
)
==
0
)
{
halt:
halt:
qh
->
hw_token
|=
HALT_BIT
;
qh
->
hw_token
|=
HALT_BIT
;
wmb
();
wmb
();
stopped
=
1
;
}
}
}
}
/* remove it from the queue */
/* remove it from the queue */
spin_lock
(
&
urb
->
lock
);
spin_lock
(
&
urb
->
lock
);
qtd_copy_status
(
ehci
,
urb
,
qtd
->
length
,
token
);
qtd_copy_status
(
ehci
,
urb
,
qtd
->
length
,
token
);
do_status
=
(
urb
->
status
==
-
EREMOTEIO
)
&&
usb_pipecontrol
(
urb
->
pipe
);
spin_unlock
(
&
urb
->
lock
);
spin_unlock
(
&
urb
->
lock
);
if
(
stopped
&&
qtd
->
qtd_list
.
prev
!=
&
qh
->
qtd_list
)
{
if
(
stopped
&&
qtd
->
qtd_list
.
prev
!=
&
qh
->
qtd_list
)
{
...
@@ -319,6 +352,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
...
@@ -319,6 +352,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
ehci_qtd_free
(
ehci
,
last
);
ehci_qtd_free
(
ehci
,
last
);
}
}
/* restore original state; caller must unlink or relink */
qh
->
qh_state
=
state
;
/* update qh after fault cleanup */
/* update qh after fault cleanup */
if
(
unlikely
((
HALT_BIT
&
qh
->
hw_token
)
!=
0
))
{
if
(
unlikely
((
HALT_BIT
&
qh
->
hw_token
)
!=
0
))
{
qh_update
(
ehci
,
qh
,
qh_update
(
ehci
,
qh
,
...
@@ -367,7 +403,7 @@ qh_urb_transaction (
...
@@ -367,7 +403,7 @@ qh_urb_transaction (
struct
ehci_qtd
*
qtd
,
*
qtd_prev
;
struct
ehci_qtd
*
qtd
,
*
qtd_prev
;
dma_addr_t
buf
;
dma_addr_t
buf
;
int
len
,
maxpacket
;
int
len
,
maxpacket
;
int
is_input
,
status_patch
=
0
;
int
is_input
;
u32
token
;
u32
token
;
/*
/*
...
@@ -388,7 +424,7 @@ qh_urb_transaction (
...
@@ -388,7 +424,7 @@ qh_urb_transaction (
if
(
usb_pipecontrol
(
urb
->
pipe
))
{
if
(
usb_pipecontrol
(
urb
->
pipe
))
{
/* SETUP pid */
/* SETUP pid */
qtd_fill
(
qtd
,
urb
->
setup_dma
,
sizeof
(
struct
usb_ctrlrequest
),
qtd_fill
(
qtd
,
urb
->
setup_dma
,
sizeof
(
struct
usb_ctrlrequest
),
token
|
(
2
/* "setup" */
<<
8
));
token
|
(
2
/* "setup" */
<<
8
)
,
8
);
/* ... and always at least one more pid */
/* ... and always at least one more pid */
token
^=
QTD_TOGGLE
;
token
^=
QTD_TOGGLE
;
...
@@ -399,10 +435,6 @@ qh_urb_transaction (
...
@@ -399,10 +435,6 @@ qh_urb_transaction (
qtd
->
urb
=
urb
;
qtd
->
urb
=
urb
;
qtd_prev
->
hw_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
qtd_prev
->
hw_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
if
(
len
>
0
&&
is_input
&&
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
status_patch
=
1
;
}
}
/*
/*
...
@@ -413,6 +445,7 @@ qh_urb_transaction (
...
@@ -413,6 +445,7 @@ qh_urb_transaction (
else
else
buf
=
0
;
buf
=
0
;
// FIXME this 'buf' check break some zlps...
if
(
!
buf
||
is_input
)
if
(
!
buf
||
is_input
)
token
|=
(
1
/* "in" */
<<
8
);
token
|=
(
1
/* "in" */
<<
8
);
/* else it's already initted to "out" pid (0 << 8) */
/* else it's already initted to "out" pid (0 << 8) */
...
@@ -427,9 +460,11 @@ qh_urb_transaction (
...
@@ -427,9 +460,11 @@ qh_urb_transaction (
for
(;;)
{
for
(;;)
{
int
this_qtd_len
;
int
this_qtd_len
;
this_qtd_len
=
qtd_fill
(
qtd
,
buf
,
len
,
token
);
this_qtd_len
=
qtd_fill
(
qtd
,
buf
,
len
,
token
,
maxpacket
);
len
-=
this_qtd_len
;
len
-=
this_qtd_len
;
buf
+=
this_qtd_len
;
buf
+=
this_qtd_len
;
if
(
is_input
)
qtd
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
/* qh makes control packets use qtd toggle; maybe switch it */
/* qh makes control packets use qtd toggle; maybe switch it */
if
((
maxpacket
&
(
this_qtd_len
+
(
maxpacket
-
1
)))
==
0
)
if
((
maxpacket
&
(
this_qtd_len
+
(
maxpacket
-
1
)))
==
0
)
...
@@ -447,6 +482,13 @@ qh_urb_transaction (
...
@@ -447,6 +482,13 @@ qh_urb_transaction (
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
}
}
/* unless the bulk/interrupt caller wants a chance to clean
* up after short reads, hc should advance qh past this urb
*/
if
(
likely
((
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
)
==
0
||
usb_pipecontrol
(
urb
->
pipe
)))
qtd
->
hw_alt_next
=
EHCI_LIST_END
;
/*
/*
* control requests may need a terminating data "status" ack;
* control requests may need a terminating data "status" ack;
* bulk ones may need a terminating short packet (zero length).
* bulk ones may need a terminating short packet (zero length).
...
@@ -473,21 +515,8 @@ qh_urb_transaction (
...
@@ -473,21 +515,8 @@ qh_urb_transaction (
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
/* never any data in such packets */
/* never any data in such packets */
qtd_fill
(
qtd
,
0
,
0
,
token
);
qtd_fill
(
qtd
,
0
,
0
,
token
,
0
);
}
}
}
/* if we're permitting a short control read, we want the hardware to
* just continue after short data and send the status ack. it can do
* that on the last data packet (typically the only one). for other
* packets, software fixup is needed (in qh_completions).
*/
if
(
status_patch
)
{
struct
ehci_qtd
*
prev
;
prev
=
list_entry
(
qtd
->
qtd_list
.
prev
,
struct
ehci_qtd
,
qtd_list
);
prev
->
hw_alt_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
}
}
/* by default, enable interrupt on urb completion */
/* by default, enable interrupt on urb completion */
...
@@ -611,6 +640,7 @@ qh_make (
...
@@ -611,6 +640,7 @@ qh_make (
case
USB_SPEED_FULL
:
case
USB_SPEED_FULL
:
/* EPS 0 means "full" */
/* EPS 0 means "full" */
if
(
type
!=
PIPE_INTERRUPT
)
info1
|=
(
EHCI_TUNE_RL_TT
<<
28
);
info1
|=
(
EHCI_TUNE_RL_TT
<<
28
);
if
(
type
==
PIPE_CONTROL
)
{
if
(
type
==
PIPE_CONTROL
)
{
info1
|=
(
1
<<
27
);
/* for TT */
info1
|=
(
1
<<
27
);
/* for TT */
...
@@ -628,12 +658,13 @@ qh_make (
...
@@ -628,12 +658,13 @@ qh_make (
case
USB_SPEED_HIGH
:
/* no TT involved */
case
USB_SPEED_HIGH
:
/* no TT involved */
info1
|=
(
2
<<
12
);
/* EPS "high" */
info1
|=
(
2
<<
12
);
/* EPS "high" */
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
if
(
type
==
PIPE_CONTROL
)
{
if
(
type
==
PIPE_CONTROL
)
{
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
info1
|=
64
<<
16
;
/* usb2 fixed maxpacket */
info1
|=
64
<<
16
;
/* usb2 fixed maxpacket */
info1
|=
1
<<
14
;
/* toggle from qtd */
info1
|=
1
<<
14
;
/* toggle from qtd */
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
}
else
if
(
type
==
PIPE_BULK
)
{
}
else
if
(
type
==
PIPE_BULK
)
{
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
info1
|=
512
<<
16
;
/* usb2 fixed maxpacket */
info1
|=
512
<<
16
;
/* usb2 fixed maxpacket */
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
}
else
{
/* PIPE_INTERRUPT */
}
else
{
/* PIPE_INTERRUPT */
...
@@ -769,8 +800,7 @@ static struct ehci_qh *qh_append_tds (
...
@@ -769,8 +800,7 @@ static struct ehci_qh *qh_append_tds (
&&
!
usb_pipecontrol
(
urb
->
pipe
))
{
&&
!
usb_pipecontrol
(
urb
->
pipe
))
{
/* "never happens": drivers do stall cleanup right */
/* "never happens": drivers do stall cleanup right */
if
(
qh
->
qh_state
!=
QH_STATE_IDLE
if
(
qh
->
qh_state
!=
QH_STATE_IDLE
&&
(
cpu_to_le32
(
QTD_STS_HALT
)
&&
qh
->
qh_state
!=
QH_STATE_COMPLETING
)
&
qh
->
hw_token
)
==
0
)
ehci_warn
(
ehci
,
"clear toggle dev%d "
ehci_warn
(
ehci
,
"clear toggle dev%d "
"ep%d%s: not idle
\n
"
,
"ep%d%s: not idle
\n
"
,
usb_pipedevice
(
urb
->
pipe
),
usb_pipedevice
(
urb
->
pipe
),
...
@@ -809,7 +839,6 @@ static struct ehci_qh *qh_append_tds (
...
@@ -809,7 +839,6 @@ static struct ehci_qh *qh_append_tds (
__list_splice
(
qtd_list
,
qh
->
qtd_list
.
prev
);
__list_splice
(
qtd_list
,
qh
->
qtd_list
.
prev
);
ehci_qtd_init
(
qtd
,
qtd
->
qtd_dma
);
ehci_qtd_init
(
qtd
,
qtd
->
qtd_dma
);
qtd
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
qh
->
dummy
=
qtd
;
qh
->
dummy
=
qtd
;
/* hc must see the new dummy at list end */
/* hc must see the new dummy at list end */
...
@@ -877,9 +906,12 @@ submit_async (
...
@@ -877,9 +906,12 @@ submit_async (
/* the async qh for the qtds being reclaimed are now unlinked from the HC */
/* the async qh for the qtds being reclaimed are now unlinked from the HC */
static
void
start_unlink_async
(
struct
ehci_hcd
*
ehci
,
struct
ehci_qh
*
qh
);
static
void
end_unlink_async
(
struct
ehci_hcd
*
ehci
,
struct
pt_regs
*
regs
)
static
void
end_unlink_async
(
struct
ehci_hcd
*
ehci
,
struct
pt_regs
*
regs
)
{
{
struct
ehci_qh
*
qh
=
ehci
->
reclaim
;
struct
ehci_qh
*
qh
=
ehci
->
reclaim
;
struct
ehci_qh
*
next
;
del_timer
(
&
ehci
->
watchdog
);
del_timer
(
&
ehci
->
watchdog
);
...
@@ -890,6 +922,10 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
...
@@ -890,6 +922,10 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
ehci
->
reclaim
=
0
;
ehci
->
reclaim
=
0
;
ehci
->
reclaim_ready
=
0
;
ehci
->
reclaim_ready
=
0
;
/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
next
=
qh
->
reclaim
;
qh
->
reclaim
=
0
;
qh_completions
(
ehci
,
qh
,
regs
);
qh_completions
(
ehci
,
qh
,
regs
);
if
(
!
list_empty
(
&
qh
->
qtd_list
)
if
(
!
list_empty
(
&
qh
->
qtd_list
)
...
@@ -909,6 +945,9 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
...
@@ -909,6 +945,9 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
jiffies
+
EHCI_ASYNC_JIFFIES
);
jiffies
+
EHCI_ASYNC_JIFFIES
);
}
}
}
}
if
(
next
)
start_unlink_async
(
ehci
,
next
);
}
}
/* makes sure the async qh will become idle */
/* makes sure the async qh will become idle */
...
@@ -921,7 +960,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
...
@@ -921,7 +960,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
#ifdef DEBUG
#ifdef DEBUG
if
(
ehci
->
reclaim
if
(
ehci
->
reclaim
||
qh
->
qh_state
!=
QH_STATE_LINKED
||
(
qh
->
qh_state
!=
QH_STATE_LINKED
&&
qh
->
qh_state
!=
QH_STATE_UNLINK_WAIT
)
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
// this macro lies except on SMP compiles
// this macro lies except on SMP compiles
||
!
spin_is_locked
(
&
ehci
->
lock
)
||
!
spin_is_locked
(
&
ehci
->
lock
)
...
@@ -953,6 +993,9 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
...
@@ -953,6 +993,9 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
wmb
();
wmb
();
if
(
unlikely
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
))
{
if
(
unlikely
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
))
{
/* if (unlikely (qh->reclaim != 0))
* this will recurse, probably not much
*/
end_unlink_async
(
ehci
,
NULL
);
end_unlink_async
(
ehci
,
NULL
);
return
;
return
;
}
}
...
...
drivers/usb/host/ehci.h
View file @
20b397bb
...
@@ -236,12 +236,12 @@ struct ehci_qtd {
...
@@ -236,12 +236,12 @@ struct ehci_qtd {
/* the rest is HCD-private */
/* the rest is HCD-private */
dma_addr_t
qtd_dma
;
/* qtd address */
dma_addr_t
qtd_dma
;
/* qtd address */
struct
list_head
qtd_list
;
/* sw qtd list */
struct
list_head
qtd_list
;
/* sw qtd list */
/* dma same in urb's qtds, except 1st control qtd (setup buffer) */
struct
urb
*
urb
;
/* qtd's urb */
struct
urb
*
urb
;
/* qtd's urb */
size_t
length
;
/* length of buffer */
size_t
length
;
/* length of buffer */
}
__attribute__
((
aligned
(
32
)));
}
__attribute__
((
aligned
(
32
)));
#define QTD_MASK cpu_to_le32 (~0x1f)
/* mask NakCnt+T in qh->hw_alt_next */
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/* type tag from {qh,itd,sitd,fstn}->hw_next */
/* type tag from {qh,itd,sitd,fstn}->hw_next */
...
@@ -305,6 +305,7 @@ struct ehci_qh {
...
@@ -305,6 +305,7 @@ struct ehci_qh {
union
ehci_shadow
qh_next
;
/* ptr to qh; or periodic */
union
ehci_shadow
qh_next
;
/* ptr to qh; or periodic */
struct
list_head
qtd_list
;
/* sw qtd list */
struct
list_head
qtd_list
;
/* sw qtd list */
struct
ehci_qtd
*
dummy
;
struct
ehci_qtd
*
dummy
;
struct
ehci_qh
*
reclaim
;
/* next to reclaim */
atomic_t
refcount
;
atomic_t
refcount
;
unsigned
stamp
;
unsigned
stamp
;
...
@@ -313,6 +314,8 @@ struct ehci_qh {
...
@@ -313,6 +314,8 @@ struct ehci_qh {
#define QH_STATE_LINKED 1
/* HC sees this */
#define QH_STATE_LINKED 1
/* HC sees this */
#define QH_STATE_UNLINK 2
/* HC may still see this */
#define QH_STATE_UNLINK 2
/* HC may still see this */
#define QH_STATE_IDLE 3
/* HC doesn't see this */
#define QH_STATE_IDLE 3
/* HC doesn't see this */
#define QH_STATE_UNLINK_WAIT 4
/* LINKED and on reclaim q */
#define QH_STATE_COMPLETING 5
/* don't touch token.HALT */
/* periodic schedule info */
/* periodic schedule info */
u8
usecs
;
/* intr bandwidth */
u8
usecs
;
/* intr bandwidth */
...
@@ -426,16 +429,6 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
...
@@ -426,16 +429,6 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
#else
/* LINUX_VERSION_CODE */
#else
/* LINUX_VERSION_CODE */
// hcd_to_bus() eventually moves to hcd.h on 2.5 too
static
inline
struct
usb_bus
*
hcd_to_bus
(
struct
usb_hcd
*
hcd
)
{
return
&
hcd
->
self
;
}
// ... as does hcd_register_root()
static
inline
int
hcd_register_root
(
struct
usb_hcd
*
hcd
)
{
return
usb_register_root_hub
(
hcd_to_bus
(
hcd
)
->
root_hub
,
&
hcd
->
pdev
->
dev
);
}
#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
#ifndef DEBUG
#ifndef DEBUG
...
...
drivers/usb/host/hc_simple.c
View file @
20b397bb
...
@@ -219,7 +219,7 @@ static int hci_unlink_urb (struct urb * urb)
...
@@ -219,7 +219,7 @@ static int hci_unlink_urb (struct urb * urb)
if
(
!
list_empty
(
&
urb
->
urb_list
)
&&
urb
->
status
==
-
EINPROGRESS
)
{
if
(
!
list_empty
(
&
urb
->
urb_list
)
&&
urb
->
status
==
-
EINPROGRESS
)
{
/* URB active? */
/* URB active? */
if
(
urb
->
transfer_flags
&
(
URB_ASYNC_UNLINK
|
URB_TIMEOUT_KILLED
)
)
{
if
(
urb
->
transfer_flags
&
URB_ASYNC_UNLINK
)
{
/* asynchronous with callback */
/* asynchronous with callback */
/* relink the urb to the del list */
/* relink the urb to the del list */
list_move
(
&
urb
->
urb_list
,
&
hci
->
del_list
);
list_move
(
&
urb
->
urb_list
,
&
hci
->
del_list
);
...
@@ -388,7 +388,6 @@ static void qu_urb_timeout (unsigned long lurb)
...
@@ -388,7 +388,6 @@ static void qu_urb_timeout (unsigned long lurb)
struct
urb
*
urb
=
(
struct
urb
*
)
lurb
;
struct
urb
*
urb
=
(
struct
urb
*
)
lurb
;
DBGFUNC
(
"enter qu_urb_timeout
\n
"
);
DBGFUNC
(
"enter qu_urb_timeout
\n
"
);
urb
->
transfer_flags
|=
URB_TIMEOUT_KILLED
;
hci_unlink_urb
(
urb
);
hci_unlink_urb
(
urb
);
}
}
#endif
#endif
...
...
drivers/usb/host/ohci-hcd.c
View file @
20b397bb
...
@@ -203,26 +203,26 @@ static int ohci_urb_enqueue (
...
@@ -203,26 +203,26 @@ static int ohci_urb_enqueue (
return
-
ENOMEM
;
return
-
ENOMEM
;
memset
(
urb_priv
,
0
,
sizeof
(
urb_priv_t
)
+
size
*
sizeof
(
struct
td
*
));
memset
(
urb_priv
,
0
,
sizeof
(
urb_priv_t
)
+
size
*
sizeof
(
struct
td
*
));
spin_lock_irqsave
(
&
ohci
->
lock
,
flags
);
/* don't submit to a dead HC */
if
(
ohci
->
disabled
||
ohci
->
sleeping
)
{
retval
=
-
ENODEV
;
goto
fail
;
}
/* fill the private part of the URB */
/* fill the private part of the URB */
urb_priv
->
length
=
size
;
urb_priv
->
length
=
size
;
urb_priv
->
ed
=
ed
;
urb_priv
->
ed
=
ed
;
/* allocate the TDs (
updating hash chain
s) */
/* allocate the TDs (
deferring hash chain update
s) */
for
(
i
=
0
;
i
<
size
;
i
++
)
{
for
(
i
=
0
;
i
<
size
;
i
++
)
{
urb_priv
->
td
[
i
]
=
td_alloc
(
ohci
,
SLAB_ATOMIC
);
urb_priv
->
td
[
i
]
=
td_alloc
(
ohci
,
mem_flags
);
if
(
!
urb_priv
->
td
[
i
])
{
if
(
!
urb_priv
->
td
[
i
])
{
urb_priv
->
length
=
i
;
urb_priv
->
length
=
i
;
retval
=
-
ENOMEM
;
urb_free_priv
(
ohci
,
urb_priv
);
goto
fail
;
return
-
ENOMEM
;
}
}
}
spin_lock_irqsave
(
&
ohci
->
lock
,
flags
);
/* don't submit to a dead HC */
if
(
ohci
->
disabled
||
ohci
->
sleeping
)
{
retval
=
-
ENODEV
;
goto
fail
;
}
}
/* schedule the ed if needed */
/* schedule the ed if needed */
...
...
drivers/usb/host/ohci-mem.c
View file @
20b397bb
...
@@ -97,17 +97,11 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
...
@@ -97,17 +97,11 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
td
=
pci_pool_alloc
(
hc
->
td_cache
,
mem_flags
,
&
dma
);
td
=
pci_pool_alloc
(
hc
->
td_cache
,
mem_flags
,
&
dma
);
if
(
td
)
{
if
(
td
)
{
int
hash
;
/* in case hc fetches it, make it look dead */
/* in case hc fetches it, make it look dead */
memset
(
td
,
0
,
sizeof
*
td
);
memset
(
td
,
0
,
sizeof
*
td
);
td
->
hwNextTD
=
cpu_to_le32
(
dma
);
td
->
hwNextTD
=
cpu_to_le32
(
dma
);
td
->
td_dma
=
dma
;
td
->
td_dma
=
dma
;
/* hashed in td_fill */
/* hash it for later reverse mapping */
hash
=
TD_HASH_FUNC
(
dma
);
td
->
td_hash
=
hc
->
td_hash
[
hash
];
hc
->
td_hash
[
hash
]
=
td
;
}
}
return
td
;
return
td
;
}
}
...
...
drivers/usb/host/ohci-q.c
View file @
20b397bb
...
@@ -463,13 +463,14 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
...
@@ -463,13 +463,14 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed)
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static
void
static
void
td_fill
(
unsigned
int
info
,
td_fill
(
struct
ohci_hcd
*
ohci
,
u32
info
,
dma_addr_t
data
,
int
len
,
dma_addr_t
data
,
int
len
,
struct
urb
*
urb
,
int
index
)
struct
urb
*
urb
,
int
index
)
{
{
struct
td
*
td
,
*
td_pt
;
struct
td
*
td
,
*
td_pt
;
struct
urb_priv
*
urb_priv
=
urb
->
hcpriv
;
struct
urb_priv
*
urb_priv
=
urb
->
hcpriv
;
int
is_iso
=
info
&
TD_ISO
;
int
is_iso
=
info
&
TD_ISO
;
int
hash
;
// ASSERT (index < urb_priv->length);
// ASSERT (index < urb_priv->length);
...
@@ -516,11 +517,16 @@ td_fill (unsigned int info,
...
@@ -516,11 +517,16 @@ td_fill (unsigned int info,
td
->
hwBE
=
0
;
td
->
hwBE
=
0
;
td
->
hwNextTD
=
cpu_to_le32
(
td_pt
->
td_dma
);
td
->
hwNextTD
=
cpu_to_le32
(
td_pt
->
td_dma
);
/* HC might read the TD right after we link it ... */
wmb
();
/* append to queue */
/* append to queue */
list_add_tail
(
&
td
->
td_list
,
&
td
->
ed
->
td_list
);
list_add_tail
(
&
td
->
td_list
,
&
td
->
ed
->
td_list
);
/* hash it for later reverse mapping */
hash
=
TD_HASH_FUNC
(
td
->
td_dma
);
td
->
td_hash
=
ohci
->
td_hash
[
hash
];
ohci
->
td_hash
[
hash
]
=
td
;
/* HC might read the TD (or cachelines) right away ... */
wmb
();
td
->
ed
->
hwTailP
=
td
->
hwNextTD
;
td
->
ed
->
hwTailP
=
td
->
hwNextTD
;
}
}
...
@@ -578,7 +584,7 @@ static void td_submit_urb (
...
@@ -578,7 +584,7 @@ static void td_submit_urb (
:
TD_T_TOGGLE
|
TD_CC
|
TD_DP_IN
;
:
TD_T_TOGGLE
|
TD_CC
|
TD_DP_IN
;
/* TDs _could_ transfer up to 8K each */
/* TDs _could_ transfer up to 8K each */
while
(
data_len
>
4096
)
{
while
(
data_len
>
4096
)
{
td_fill
(
info
,
data
,
4096
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
data
,
4096
,
urb
,
cnt
);
data
+=
4096
;
data
+=
4096
;
data_len
-=
4096
;
data_len
-=
4096
;
cnt
++
;
cnt
++
;
...
@@ -586,11 +592,11 @@ static void td_submit_urb (
...
@@ -586,11 +592,11 @@ static void td_submit_urb (
/* maybe avoid ED halt on final TD short read */
/* maybe avoid ED halt on final TD short read */
if
(
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
if
(
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
info
|=
TD_R
;
info
|=
TD_R
;
td_fill
(
info
,
data
,
data_len
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
data
,
data_len
,
urb
,
cnt
);
cnt
++
;
cnt
++
;
if
((
urb
->
transfer_flags
&
URB_ZERO_PACKET
)
if
((
urb
->
transfer_flags
&
URB_ZERO_PACKET
)
&&
cnt
<
urb_priv
->
length
)
{
&&
cnt
<
urb_priv
->
length
)
{
td_fill
(
info
,
0
,
0
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
0
,
0
,
urb
,
cnt
);
cnt
++
;
cnt
++
;
}
}
/* maybe kickstart bulk list */
/* maybe kickstart bulk list */
...
@@ -605,17 +611,17 @@ static void td_submit_urb (
...
@@ -605,17 +611,17 @@ static void td_submit_urb (
*/
*/
case
PIPE_CONTROL
:
case
PIPE_CONTROL
:
info
=
TD_CC
|
TD_DP_SETUP
|
TD_T_DATA0
;
info
=
TD_CC
|
TD_DP_SETUP
|
TD_T_DATA0
;
td_fill
(
info
,
urb
->
setup_dma
,
8
,
urb
,
cnt
++
);
td_fill
(
ohci
,
info
,
urb
->
setup_dma
,
8
,
urb
,
cnt
++
);
if
(
data_len
>
0
)
{
if
(
data_len
>
0
)
{
info
=
TD_CC
|
TD_R
|
TD_T_DATA1
;
info
=
TD_CC
|
TD_R
|
TD_T_DATA1
;
info
|=
is_out
?
TD_DP_OUT
:
TD_DP_IN
;
info
|=
is_out
?
TD_DP_OUT
:
TD_DP_IN
;
/* NOTE: mishandles transfers >8K, some >4K */
/* NOTE: mishandles transfers >8K, some >4K */
td_fill
(
info
,
data
,
data_len
,
urb
,
cnt
++
);
td_fill
(
ohci
,
info
,
data
,
data_len
,
urb
,
cnt
++
);
}
}
info
=
is_out
info
=
is_out
?
TD_CC
|
TD_DP_IN
|
TD_T_DATA1
?
TD_CC
|
TD_DP_IN
|
TD_T_DATA1
:
TD_CC
|
TD_DP_OUT
|
TD_T_DATA1
;
:
TD_CC
|
TD_DP_OUT
|
TD_T_DATA1
;
td_fill
(
info
,
data
,
0
,
urb
,
cnt
++
);
td_fill
(
ohci
,
info
,
data
,
0
,
urb
,
cnt
++
);
/* maybe kickstart control list */
/* maybe kickstart control list */
wmb
();
wmb
();
writel
(
OHCI_CLF
,
&
ohci
->
regs
->
cmdstatus
);
writel
(
OHCI_CLF
,
&
ohci
->
regs
->
cmdstatus
);
...
@@ -634,7 +640,7 @@ static void td_submit_urb (
...
@@ -634,7 +640,7 @@ static void td_submit_urb (
// a 2^16 iso range, vs other HCs max of 2^10)
// a 2^16 iso range, vs other HCs max of 2^10)
frame
+=
cnt
*
urb
->
interval
;
frame
+=
cnt
*
urb
->
interval
;
frame
&=
0xffff
;
frame
&=
0xffff
;
td_fill
(
TD_CC
|
TD_ISO
|
frame
,
td_fill
(
ohci
,
TD_CC
|
TD_ISO
|
frame
,
data
+
urb
->
iso_frame_desc
[
cnt
].
offset
,
data
+
urb
->
iso_frame_desc
[
cnt
].
offset
,
urb
->
iso_frame_desc
[
cnt
].
length
,
urb
,
cnt
);
urb
->
iso_frame_desc
[
cnt
].
length
,
urb
,
cnt
);
}
}
...
...
drivers/usb/host/uhci-hcd.c
View file @
20b397bb
...
@@ -1747,7 +1747,6 @@ static void stall_callback(unsigned long ptr)
...
@@ -1747,7 +1747,6 @@ static void stall_callback(unsigned long ptr)
tmp
=
tmp
->
next
;
tmp
=
tmp
->
next
;
u
->
transfer_flags
|=
URB_TIMEOUT_KILLED
;
uhci_urb_dequeue
(
hcd
,
u
);
uhci_urb_dequeue
(
hcd
,
u
);
}
}
...
...
drivers/usb/image/scanner.c
View file @
20b397bb
/* -*- linux-c -*- */
/* -*- linux-c -*- */
/*
/*
* Driver for USB Scanners (linux-2.5.
54
)
* Driver for USB Scanners (linux-2.5.
60
)
*
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 2002, 2003 Henning Meier-Geinitz
*
*
* Portions may be copyright Brad Keryan and Michael Gee.
* Portions may be copyright Brad Keryan and Michael Gee.
*
*
* Brian Beattie <beattie@beattie-home.net>
* Previously maintained by Brian Beattie
*
* Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de>
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* modify it under the terms of the GNU General Public License as
...
@@ -300,8 +303,6 @@
...
@@ -300,8 +303,6 @@
* Frank Zago <fzago@greshamstorage.com> and
* Frank Zago <fzago@greshamstorage.com> and
* Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
* Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
*
*
* 05/21/02 Currently maintained by Brian Beattie <beattie@beattie-home.net>
*
* 0.4.8 5/30/2002
* 0.4.8 5/30/2002
* - Added Mustek BearPaw 2400 TA. Thanks to Sergey
* - Added Mustek BearPaw 2400 TA. Thanks to Sergey
* Vlasov <vsu@mivlgu.murom.ru>.
* Vlasov <vsu@mivlgu.murom.ru>.
...
@@ -332,12 +333,18 @@
...
@@ -332,12 +333,18 @@
* <oliver@neukum.name>.
* <oliver@neukum.name>.
*
*
* 0.4.10 01/07/2003
* 0.4.10 01/07/2003
* - Added vendor/product ids for Visioneer scanners.
* - Added vendor/product ids for Artec, Canon, Compaq, Epson, HP, Microtek
* and Visioneer scanners. Thanks to William Lam <wklam@triad.rr.com>,
* Till Kamppeter <till.kamppeter@gmx.net> and others for all the ids.
* - Cleaned up list of vendor/product ids.
* - Print information about user-supplied ids only once at startup instead
* - Print information about user-supplied ids only once at startup instead
* of everytime any USB device is plugged in.
* of everytime any USB device is plugged in.
* - Removed PV8630 ioctls. Use the standard ioctls instead.
* - Removed PV8630 ioctls. Use the standard ioctls instead.
* - Made endpoint detection more generic. Basically, only one bulk-in
* - Made endpoint detection more generic. Basically, only one bulk-in
* endpoint is required, everything else is optional.
* endpoint is required, everything else is optional.
* - New maintainer: Henning Meier-Geinitz.
* - Print ids and device number when a device was detected.
* - Don't print errors when the device is busy.
*
*
* TODO
* TODO
* - Performance
* - Performance
...
@@ -360,7 +367,7 @@
...
@@ -360,7 +367,7 @@
* - All the developers that are working on USB SANE backends or other
* - All the developers that are working on USB SANE backends or other
* applications to use USB scanners.
* applications to use USB scanners.
* - Thanks to Greg KH <greg@kroah.com> for setting up Brian Beattie
* - Thanks to Greg KH <greg@kroah.com> for setting up Brian Beattie
* to be the new USB Scanner maintainer.
*
and Henning Meier-Geinitz
to be the new USB Scanner maintainer.
*
*
* Performance:
* Performance:
*
*
...
@@ -369,6 +376,14 @@
...
@@ -369,6 +376,14 @@
* 24 Bit Color ~ 70 secs - 3.6 Mbit/sec
* 24 Bit Color ~ 70 secs - 3.6 Mbit/sec
* 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
* 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
/*
* For documentation, see Documentation/usb/scanner.txt.
* Website: http://www.meier-geinitz.de/kernel/
* Please contact the maintainer if your scanner is not detected by this
* driver automatically.
*/
#include <asm/byteorder.h>
#include <asm/byteorder.h>
/*
/*
...
@@ -461,7 +476,7 @@ open_scanner(struct inode * inode, struct file * file)
...
@@ -461,7 +476,7 @@ open_scanner(struct inode * inode, struct file * file)
}
}
if
(
scn
->
isopen
)
{
if
(
scn
->
isopen
)
{
err
(
"open_scanner(%d): Scanner device is already open"
,
scn_minor
);
dbg
(
"open_scanner(%d): Scanner device is already open"
,
scn_minor
);
err
=
-
EBUSY
;
err
=
-
EBUSY
;
goto
out_error
;
goto
out_error
;
}
}
...
@@ -1047,6 +1062,9 @@ probe_scanner(struct usb_interface *intf,
...
@@ -1047,6 +1062,9 @@ probe_scanner(struct usb_interface *intf,
if
(
scn
->
devfs
==
NULL
)
if
(
scn
->
devfs
==
NULL
)
dbg
(
"scanner%d: device node registration failed"
,
scn_minor
);
dbg
(
"scanner%d: device node registration failed"
,
scn_minor
);
info
(
"USB scanner device (0x%04x/0x%04x) now attached to %s"
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
name
);
up
(
&
scn_mutex
);
up
(
&
scn_mutex
);
usb_set_intfdata
(
intf
,
scn
);
usb_set_intfdata
(
intf
,
scn
);
...
...
drivers/usb/image/scanner.h
View file @
20b397bb
/*
/*
* Driver for USB Scanners (linux-2.5.
54
)
* Driver for USB Scanners (linux-2.5.
60
)
*
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Previously maintained by Brian Beattie
*
*
*
Brian Beattie <beattie@beattie-home.net
>
*
Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de
>
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* modify it under the terms of the GNU General Public License as
...
@@ -19,11 +20,16 @@
...
@@ -19,11 +20,16 @@
* along with this program; if not, write to the Free Software
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* 05/21/02 Currently maintained by Brian Beattie <beattie@beattie-home.net>
*
*
*/
*/
/*
* For documentation, see Documentation/usb/scanner.txt.
* Website: http://www.meier-geinitz.de/kernel/
* Please contact the maintainer if your scanner is not detected by this
* driver automatically.
*/
#include <linux/module.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
...
@@ -45,7 +51,7 @@
...
@@ -45,7 +51,7 @@
static
__s32
vendor
=-
1
,
product
=-
1
,
read_timeout
=
0
;
static
__s32
vendor
=-
1
,
product
=-
1
,
read_timeout
=
0
;
MODULE_AUTHOR
(
"
Brian Beattie, beattie@beattie-home.net
"
);
MODULE_AUTHOR
(
"
Henning Meier-Geinitz, henning@meier-geinitz.de
"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
" "
DRIVER_VERSION
);
MODULE_DESCRIPTION
(
DRIVER_DESC
" "
DRIVER_VERSION
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
...
@@ -65,79 +71,90 @@ MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
...
@@ -65,79 +71,90 @@ MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
static
struct
usb_device_id
scanner_device_ids
[]
=
{
static
struct
usb_device_id
scanner_device_ids
[]
=
{
/* Acer (now Benq) */
/* Acer (now Benq) */
{
USB_DEVICE
(
0x04a5
,
0x2060
)
},
/* 620U & 640U (!)*/
{
USB_DEVICE
(
0x04a5
,
0x2040
)
},
/* 620U (!) */
{
USB_DEVICE
(
0x04a5
,
0x20c0
)
},
/* 1240UT, 1240U */
{
USB_DEVICE
(
0x04a5
,
0x2022
)
},
/* 340U */
{
USB_DEVICE
(
0x04a5
,
0x1a20
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x1a20
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x1a2a
)
},
/* Another 620U */
{
USB_DEVICE
(
0x04a5
,
0x1a2a
)
},
/* Another 620U */
{
USB_DEVICE
(
0x04a5
,
0x2022
)
},
/* 340U */
{
USB_DEVICE
(
0x04a5
,
0x2040
)
},
/* 620U (!) */
{
USB_DEVICE
(
0x04a5
,
0x2060
)
},
/* 620U & 640U (!)*/
{
USB_DEVICE
(
0x04a5
,
0x207e
)
},
/* 640BU */
{
USB_DEVICE
(
0x04a5
,
0x207e
)
},
/* 640BU */
{
USB_DEVICE
(
0x04a5
,
0x20b0
)
},
/* Benq 4300 */
{
USB_DEVICE
(
0x04a5
,
0x20be
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x20be
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x20c0
)
},
/* 1240UT, 1240U */
{
USB_DEVICE
(
0x04a5
,
0x20de
)
},
/* S2W 3300U */
{
USB_DEVICE
(
0x04a5
,
0x20de
)
},
/* S2W 3300U */
{
USB_DEVICE
(
0x04a5
,
0x20b0
)
},
/* Benq 4300 */
{
USB_DEVICE
(
0x04a5
,
0x20fe
)
},
/* Benq 5300 */
{
USB_DEVICE
(
0x04a5
,
0x20fc
)
},
/* Benq 5000 */
{
USB_DEVICE
(
0x04a5
,
0x20fc
)
},
/* Benq 5000 */
{
USB_DEVICE
(
0x04a5
,
0x20fe
)
},
/* Benq 5300 */
/* Agfa */
/* Agfa */
{
USB_DEVICE
(
0x06bd
,
0x0001
)
},
/* SnapScan 1212U */
{
USB_DEVICE
(
0x06bd
,
0x0001
)
},
/* SnapScan 1212U */
{
USB_DEVICE
(
0x06bd
,
0x0002
)
},
/* SnapScan 1236U */
{
USB_DEVICE
(
0x06bd
,
0x0002
)
},
/* SnapScan 1236U */
{
USB_DEVICE
(
0x06bd
,
0x2061
)
},
/* Another SnapScan 1212U (?)*/
{
USB_DEVICE
(
0x06bd
,
0x0100
)
},
/* SnapScan Touch */
{
USB_DEVICE
(
0x06bd
,
0x0100
)
},
/* SnapScan Touch */
{
USB_DEVICE
(
0x06bd
,
0x2061
)
},
/* Another SnapScan 1212U (?)*/
{
USB_DEVICE
(
0x06bd
,
0x208d
)
},
/* Snapscan e40 */
{
USB_DEVICE
(
0x06bd
,
0x208f
)
},
/* SnapScan e50*/
{
USB_DEVICE
(
0x06bd
,
0x2091
)
},
/* SnapScan e20 */
{
USB_DEVICE
(
0x06bd
,
0x2091
)
},
/* SnapScan e20 */
{
USB_DEVICE
(
0x06bd
,
0x2093
)
},
/* SnapScan e10*/
{
USB_DEVICE
(
0x06bd
,
0x2095
)
},
/* SnapScan e25 */
{
USB_DEVICE
(
0x06bd
,
0x2095
)
},
/* SnapScan e25 */
{
USB_DEVICE
(
0x06bd
,
0x2097
)
},
/* SnapScan e26 */
{
USB_DEVICE
(
0x06bd
,
0x2097
)
},
/* SnapScan e26 */
{
USB_DEVICE
(
0x06bd
,
0x208d
)
},
/* Snapscan e40 */
{
USB_DEVICE
(
0x06bd
,
0x2093
)
},
/* SnapScan e10*/
{
USB_DEVICE
(
0x06bd
,
0x20ff
)
},
/* SnapScan e42*/
{
USB_DEVICE
(
0x06bd
,
0x208f
)
},
/* SnapScan e50*/
{
USB_DEVICE
(
0x06bd
,
0x20fd
)
},
/* SnapScan e52*/
{
USB_DEVICE
(
0x06bd
,
0x20fd
)
},
/* SnapScan e52*/
{
USB_DEVICE
(
0x06bd
,
0x20ff
)
},
/* SnapScan e42*/
/* Artec */
{
USB_DEVICE
(
0x05d8
,
0x4001
)
},
/* Ultima 2000 */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* Ultima 2000 (GT6801 based) */
/* Benq: see Acer */
/* Benq: see Acer */
/* Canon */
/* Canon */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* CanoScan FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2205
)
},
/* FB1210U */
{
USB_DEVICE
(
0x04a9
,
0x2202
)
},
/* CanoScan FB620U */
{
USB_DEVICE
(
0x04a9
,
0x2202
)
},
/* CanoScan FB620U */
{
USB_DEVICE
(
0x04a9
,
0x2204
)
},
/* CanoScan FB630U/FB636U */
{
USB_DEVICE
(
0x04a9
,
0x2204
)
},
/* CanoScan FB630U/FB636U */
{
USB_DEVICE
(
0x04a9
,
0x2205
)
},
/* CanoScan FB1210U */
{
USB_DEVICE
(
0x04a9
,
0x2206
)
},
/* CanoScan N650U/N656U */
{
USB_DEVICE
(
0x04a9
,
0x2206
)
},
/* CanoScan N650U/N656U */
{
USB_DEVICE
(
0x04a9
,
0x2207
)
},
/* CanoScan N1220U */
{
USB_DEVICE
(
0x04a9
,
0x2207
)
},
/* CanoScan N1220U */
{
USB_DEVICE
(
0x04a9
,
0x2208
)
},
/* CanoScan D660U */
{
USB_DEVICE
(
0x04a9
,
0x2208
)
},
/* CanoScan D660U */
{
USB_DEVICE
(
0x04a9
,
0x220b
)
},
/* D646U */
{
USB_DEVICE
(
0x04a9
,
0x220b
)
},
/* CanoScan D646U */
{
USB_DEVICE
(
0x04a9
,
0x220c
)
},
/* CanoScan D1250U2 */
{
USB_DEVICE
(
0x04a9
,
0x220d
)
},
/* CanoScan N670U/N676U/LIDE 20 */
{
USB_DEVICE
(
0x04a9
,
0x220d
)
},
/* CanoScan N670U/N676U/LIDE 20 */
{
USB_DEVICE
(
0x04a9
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
/* Colorado -- See Primax/Colorado below */
/* Colorado -- See Primax/Colorado below */
/* Compaq */
{
USB_DEVICE
(
0x049f
,
0x0021
)
},
/* S200 */
/* Epson -- See Seiko/Epson below */
/* Epson -- See Seiko/Epson below */
/* Genius */
/* Genius */
{
USB_DEVICE
(
0x0458
,
0x2001
)
},
/* ColorPage
-
Vivid Pro */
{
USB_DEVICE
(
0x0458
,
0x2001
)
},
/* ColorPage
Vivid Pro */
{
USB_DEVICE
(
0x0458
,
0x2007
)
},
/* ColorPage HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2007
)
},
/* ColorPage HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2008
)
},
/* ColorPage
-
HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2008
)
},
/* ColorPage
HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2009
)
},
/* ColorPage
-
HR6A */
{
USB_DEVICE
(
0x0458
,
0x2009
)
},
/* ColorPage
HR6A */
{
USB_DEVICE
(
0x0458
,
0x2011
)
},
/* ColorPage
-
Vivid3x */
{
USB_DEVICE
(
0x0458
,
0x2011
)
},
/* ColorPage
Vivid3x */
{
USB_DEVICE
(
0x0458
,
0x2013
)
},
/* ColorPage
-
HR7 */
{
USB_DEVICE
(
0x0458
,
0x2013
)
},
/* ColorPage
HR7 */
{
USB_DEVICE
(
0x0458
,
0x2015
)
},
/* ColorPage
-
HR7LE */
{
USB_DEVICE
(
0x0458
,
0x2015
)
},
/* ColorPage
HR7LE */
{
USB_DEVICE
(
0x0458
,
0x2016
)
},
/* ColorPage
-
HR6X */
{
USB_DEVICE
(
0x0458
,
0x2016
)
},
/* ColorPage
HR6X */
/* Hewlett Packard */
/* Hewlett Packard */
{
USB_DEVICE
(
0x03f0
,
0x0505
)
},
/* ScanJet 2100C */
{
USB_DEVICE
(
0x03f0
,
0x0101
)
},
/* ScanJet 4100C */
{
USB_DEVICE
(
0x03f0
,
0x0605
)
},
/* 2200C */
{
USB_DEVICE
(
0x03f0
,
0x0901
)
},
/* 2300C */
{
USB_DEVICE
(
0x03f0
,
0x0205
)
},
/* 3300C */
{
USB_DEVICE
(
0x03f0
,
0x0405
)
},
/* 3400C */
{
USB_DEVICE
(
0x03f0
,
0x0101
)
},
/* 4100C */
{
USB_DEVICE
(
0x03f0
,
0x0105
)
},
/* 4200C */
{
USB_DEVICE
(
0x03f0
,
0x0305
)
},
/* 4300C */
{
USB_DEVICE
(
0x03f0
,
0x0705
)
},
/* 4400C */
{
USB_DEVICE
(
0x03f0
,
0x0102
)
},
/* PhotoSmart S20 */
{
USB_DEVICE
(
0x03f0
,
0x0102
)
},
/* PhotoSmart S20 */
{
USB_DEVICE
(
0x03f0
,
0x0401
)
},
/* 5200C */
{
USB_DEVICE
(
0x03f0
,
0x0105
)
},
/* ScanJet 4200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
{
USB_DEVICE
(
0x03f0
,
0x0201
)
},
/* ScanJet 6200C */
{
USB_DEVICE
(
0x03f0
,
0x0201
)
},
/* 6200C */
{
USB_DEVICE
(
0x03f0
,
0x0205
)
},
/* ScanJet 3300C */
{
USB_DEVICE
(
0x03f0
,
0x0601
)
},
/* 6300C */
{
USB_DEVICE
(
0x03f0
,
0x0305
)
},
/* ScanJet 4300C */
{
USB_DEVICE
(
0x03f0
,
0x0401
)
},
/* ScanJet 5200C */
{
USB_DEVICE
(
0x03f0
,
0x0405
)
},
/* ScanJet 3400C */
{
USB_DEVICE
(
0x03f0
,
0x0505
)
},
/* ScanJet 2100C */
{
USB_DEVICE
(
0x03f0
,
0x0601
)
},
/* ScanJet 6300C */
{
USB_DEVICE
(
0x03f0
,
0x0605
)
},
/* ScanJet 2200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* ScanJet 5300C - NOT SUPPORTED - use hpusbscsi driver */
{
USB_DEVICE
(
0x03f0
,
0x0705
)
},
/* ScanJet 4400C */
// { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
{
USB_DEVICE
(
0x03f0
,
0x0901
)
},
/* ScanJet 2300C */
{
USB_DEVICE
(
0x03f0
,
0x1305
)
},
/* Scanjet 4570c */
{
USB_DEVICE
(
0x03f0
,
0x2005
)
},
/* ScanJet 3570c */
{
USB_DEVICE
(
0x03f0
,
0x2205
)
},
/* ScanJet 3500c */
/* iVina */
/* iVina */
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* 1200U */
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* 1200U */
/* Lexmark */
/* Lexmark */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
/* Lifetec */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* Lifetec LT9385 */
/* Memorex */
/* Memorex */
{
USB_DEVICE
(
0x0461
,
0x0346
)
},
/* 6136u - repackaged Primax ? */
{
USB_DEVICE
(
0x0461
,
0x0346
)
},
/* 6136u - repackaged Primax ? */
/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
/* Microtek */
{
USB_DEVICE
(
0x05da
,
0x30ce
)
},
/* ScanMaker 3800 */
/* The following SCSI-over-USB Microtek devices are supported by the
microtek driver: Enable SCSI and USB Microtek in kernel config */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */
// { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */
// { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */
// { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */
...
@@ -146,58 +163,59 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -146,58 +163,59 @@ static struct usb_device_id scanner_device_ids [] = {
// { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */
// { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */
// { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */
// { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */
/* Minolta */
/* Minolta */
// { USB_DEVICE(0x0638,0x026a) }, /* Minolta Dimage Scan Dual II */
// { USB_DEVICE(0x0686, 0x4004) }, /* Scan Elite II (need interrupt ep) */
{
USB_DEVICE
(
0x0686
,
0x400d
)
},
/* Scan Dual III */
{
USB_DEVICE
(
0x0686
,
0x400d
)
},
/* Scan Dual III */
/* The following SCSI-over-USB Minolta devices are supported by the
hpusbscsi driver: Enable SCSI and USB hpusbscsi in kernel config */
// { USB_DEVICE(0x0638, 0x026a) }, /* Minolta Dimage Scan Dual II */
// { USB_DEVICE(0x0686, 0x4004) }, /* Scan Elite II (need interrupt ep) */
/* Mustek */
/* Mustek */
{
USB_DEVICE
(
0x0400
,
0x1000
)
},
/* BearPaw 1200 (National Semiconductor LM9831) */
{
USB_DEVICE
(
0x0400
,
0x1001
)
},
/* BearPaw 2400 (National Semiconductor LM9832) */
{
USB_DEVICE
(
0x055f
,
0x0001
)
},
/* ScanExpress 1200 CU */
{
USB_DEVICE
(
0x055f
,
0x0001
)
},
/* ScanExpress 1200 CU */
{
USB_DEVICE
(
0x0400
,
0x1000
)
},
/* BearPaw 1200 */
{
USB_DEVICE
(
0x055f
,
0x0002
)
},
/* ScanExpress 600 CU */
{
USB_DEVICE
(
0x055f
,
0x0002
)
},
/* ScanExpress 600 CU */
{
USB_DEVICE
(
0x055f
,
0x0873
)
},
/* ScanExpress 600 USB */
{
USB_DEVICE
(
0x055f
,
0x0003
)
},
/* ScanExpress 1200 USB */
{
USB_DEVICE
(
0x055f
,
0x0003
)
},
/* ScanExpress 1200 USB */
{
USB_DEVICE
(
0x055f
,
0x0006
)
},
/* ScanExpress 1200 UB */
{
USB_DEVICE
(
0x055f
,
0x0006
)
},
/* ScanExpress 1200 UB */
{
USB_DEVICE
(
0x055f
,
0x0007
)
},
/* ScanExpress 1200 USB Plus */
{
USB_DEVICE
(
0x055f
,
0x0007
)
},
/* ScanExpress 1200 USB Plus */
{
USB_DEVICE
(
0x055f
,
0x0210
)
},
/* ScanExpress A3 USB */
{
USB_DEVICE
(
0x0400
,
0x1001
)
},
/* BearPaw 2400 */
{
USB_DEVICE
(
0x055f
,
0x0008
)
},
/* ScanExpress 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x0008
)
},
/* ScanExpress 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x0010
)
},
/* BearPaw 1200F */
{
USB_DEVICE
(
0x055f
,
0x0010
)
},
/* BearPaw 1200F */
{
USB_DEVICE
(
0x055f
,
0x0210
)
},
/* ScanExpress A3 USB */
{
USB_DEVICE
(
0x055f
,
0x0218
)
},
/* BearPaw 2400 TA */
{
USB_DEVICE
(
0x055f
,
0x0218
)
},
/* BearPaw 2400 TA */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* BearPaw 1200 CU and ScanExpress 1200 UB Plus */
{
USB_DEVICE
(
0x055f
,
0x0219
)
},
/* BearPaw 2400 TA Plus */
{
USB_DEVICE
(
0x055f
,
0x0219
)
},
/* BearPaw 2400 TA Plus */
{
USB_DEVICE
(
0x055f
,
0x021c
)
},
/* BearPaw 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021c
)
},
/* BearPaw 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021d
)
},
/* Bearpaw 2400 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021d
)
},
/* Bearpaw 2400 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021e
)
},
/* BearPaw 1200 TA/CS */
{
USB_DEVICE
(
0x055f
,
0x021e
)
},
/* BearPaw 1200 TA/CS */
{
USB_DEVICE
(
0x055f
,
0x0400
)
},
/* BearPaw 2400 TA PRO */
{
USB_DEVICE
(
0x055f
,
0x0400
)
},
/* BearPaw 2400 TA PRO */
{
USB_DEVICE
(
0x055f
,
0x0873
)
},
/* ScanExpress 600 USB */
{
USB_DEVICE
(
0x055f
,
0x1000
)
},
/* BearPaw 4800 TA PRO */
{
USB_DEVICE
(
0x055f
,
0x1000
)
},
/* BearPaw 4800 TA PRO */
// { USB_DEVICE(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */
/* Nikon */
/* Nikon */
{
USB_DEVICE
(
0x04b0
,
0x4000
)
},
/* Coolscan LS 40 ED */
{
USB_DEVICE
(
0x04b0
,
0x4000
)
},
/* Coolscan LS 40 ED */
/* Plustek */
/* Plustek */
{
USB_DEVICE
(
0x07b3
,
0x0017
)
},
/* OpticPro UT12/UT16/UT24 */
{
USB_DEVICE
(
0x07b3
,
0x0011
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0010
)
},
/* OpticPro U12 */
{
USB_DEVICE
(
0x07b3
,
0x0015
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0005
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0005
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0007
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0007
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x000F
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x000F
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0010
)
},
/* OpticPro U12 */
{
USB_DEVICE
(
0x07b3
,
0x0011
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0012
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0012
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0013
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0013
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0014
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0014
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0015
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0016
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0016
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x001
2
)
},
/* Unknown
*/
{
USB_DEVICE
(
0x07b3
,
0x001
7
)
},
/* OpticPro UT12/UT16/UT24
*/
{
USB_DEVICE
(
0x07b3
,
0x0401
)
},
/* OpticPro 1248U */
{
USB_DEVICE
(
0x07b3
,
0x0401
)
},
/* OpticPro 1248U */
/* Primax/Colorado */
/* Primax/Colorado */
{
USB_DEVICE
(
0x0461
,
0x0300
)
},
/* G2-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0300
)
},
/* G2-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0380
)
},
/* G2-600 #1 */
{
USB_DEVICE
(
0x0461
,
0x0301
)
},
/* G2E-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0301
)
},
/* G2E-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0381
)
},
/* ReadyScan 636i */
{
USB_DEVICE
(
0x0461
,
0x0302
)
},
/* G2-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0302
)
},
/* G2-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0382
)
},
/* G2-600 #2 */
{
USB_DEVICE
(
0x0461
,
0x0303
)
},
/* G2E-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0303
)
},
/* G2E-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0383
)
},
/* G2E-600 */
{
USB_DEVICE
(
0x0461
,
0x0340
)
},
/* Colorado USB 9600 */
{
USB_DEVICE
(
0x0461
,
0x0340
)
},
/* Colorado USB 9600 */
// { USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 - undetected endpoint */
{
USB_DEVICE
(
0x0461
,
0x0341
)
},
/* Colorado 600u */
{
USB_DEVICE
(
0x0461
,
0x0341
)
},
/* Colorado 600u */
{
USB_DEVICE
(
0x0461
,
0x0360
)
},
/* Colorado USB 19200 */
{
USB_DEVICE
(
0x0461
,
0x0361
)
},
/* Colorado 1200u */
{
USB_DEVICE
(
0x0461
,
0x0361
)
},
/* Colorado 1200u */
{
USB_DEVICE
(
0x0461
,
0x0380
)
},
/* G2-600 #1 */
{
USB_DEVICE
(
0x0461
,
0x0381
)
},
/* ReadyScan 636i */
{
USB_DEVICE
(
0x0461
,
0x0382
)
},
/* G2-600 #2 */
{
USB_DEVICE
(
0x0461
,
0x0383
)
},
/* G2E-600 */
/* Relisis */
/* Relisis */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
/* Seiko/Epson Corp. */
/* Seiko/Epson Corp. */
...
@@ -221,6 +239,7 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -221,6 +239,7 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x04b8
,
0x011c
)
},
/* Perfection 3200 */
{
USB_DEVICE
(
0x04b8
,
0x011c
)
},
/* Perfection 3200 */
{
USB_DEVICE
(
0x04b8
,
0x011d
)
},
/* Perfection 1260 */
{
USB_DEVICE
(
0x04b8
,
0x011d
)
},
/* Perfection 1260 */
{
USB_DEVICE
(
0x04b8
,
0x011e
)
},
/* Perfection 1660 Photo */
{
USB_DEVICE
(
0x04b8
,
0x011e
)
},
/* Perfection 1660 Photo */
{
USB_DEVICE
(
0x04b8
,
0x0801
)
},
/* Stylus CX5200 */
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
/* Umax */
/* Umax */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
...
@@ -230,8 +249,8 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -230,8 +249,8 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x1606
,
0x0160
)
},
/* Astra 5400U */
{
USB_DEVICE
(
0x1606
,
0x0160
)
},
/* Astra 5400U */
{
USB_DEVICE
(
0x1606
,
0x0230
)
},
/* Astra 2200U */
{
USB_DEVICE
(
0x1606
,
0x0230
)
},
/* Astra 2200U */
/* Visioneer */
/* Visioneer */
{
USB_DEVICE
(
0x04a7
,
0x0221
)
},
/* OneTouch 5300 USB */
{
USB_DEVICE
(
0x04a7
,
0x0211
)
},
/* OneTouch 7600 USB */
{
USB_DEVICE
(
0x04a7
,
0x0211
)
},
/* OneTouch 7600 USB */
{
USB_DEVICE
(
0x04a7
,
0x0221
)
},
/* OneTouch 5300 USB */
{
USB_DEVICE
(
0x04a7
,
0x0231
)
},
/* 6100 USB */
{
USB_DEVICE
(
0x04a7
,
0x0231
)
},
/* 6100 USB */
{
USB_DEVICE
(
0x04a7
,
0x0311
)
},
/* 6200 EPP/USB */
{
USB_DEVICE
(
0x04a7
,
0x0311
)
},
/* 6200 EPP/USB */
{
USB_DEVICE
(
0x04a7
,
0x0321
)
},
/* OneTouch 8100 EPP/USB */
{
USB_DEVICE
(
0x04a7
,
0x0321
)
},
/* OneTouch 8100 EPP/USB */
...
...
drivers/usb/input/hid-core.c
View file @
20b397bb
...
@@ -1324,6 +1324,9 @@ void hid_init_reports(struct hid_device *hid)
...
@@ -1324,6 +1324,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
#define USB_DEVICE_ID_MGE_UPS1 0x0001
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
struct
hid_blacklist
{
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idVendor
;
__u16
idProduct
;
__u16
idProduct
;
...
@@ -1359,6 +1362,12 @@ struct hid_blacklist {
...
@@ -1359,6 +1362,12 @@ struct hid_blacklist {
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS1
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS1
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
200
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
300
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
400
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
500
,
HID_QUIRK_IGNORE
},
{
0
,
0
}
{
0
,
0
}
};
};
...
...
drivers/usb/misc/atmsar.c
View file @
20b397bb
...
@@ -381,6 +381,83 @@ void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc)
...
@@ -381,6 +381,83 @@ void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc)
**
**
***********************/
***********************/
/* encapsulate in an AAL5 frame, which is then split into ATM cells */
unsigned
int
atmsar_encode
(
struct
atmsar_vcc_data
*
ctx
,
char
*
source
,
char
*
target
,
unsigned
int
pdu_length
)
{
unsigned
int
num_cells
=
(
pdu_length
+
ATM_AAL5_TRAILER
+
ATM_CELL_PAYLOAD
-
1
)
/
ATM_CELL_PAYLOAD
;
unsigned
int
num_pdu_cells
=
pdu_length
/
ATM_CELL_PAYLOAD
+
1
;
unsigned
int
aal5_length
=
num_cells
*
ATM_CELL_PAYLOAD
;
unsigned
int
zero_padding
=
aal5_length
-
pdu_length
-
ATM_AAL5_TRAILER
;
unsigned
int
final_length
=
num_cells
*
ATM_CELL_SIZE
;
unsigned
char
aal5_trailer
[
ATM_AAL5_TRAILER
];
unsigned
char
cell_header
[
ATM_CELL_HEADER
];
u32
crc
;
int
i
;
PDEBUG
(
"atmsar_encode entered
\n
"
);
PDEBUG
(
"pdu_length %d, num_cells %d, num_pdu_cells %d, aal5_length %d, zero_padding %d, final_length %d
\n
"
,
pdu_length
,
num_cells
,
num_pdu_cells
,
aal5_length
,
zero_padding
,
final_length
);
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
aal5_trailer
[
0
]
=
0
;
/* UU = 0 */
aal5_trailer
[
1
]
=
0
;
/* CPI = 0 */
aal5_trailer
[
2
]
=
pdu_length
>>
8
;
aal5_trailer
[
3
]
=
pdu_length
;
crc
=
crc32
(
~
0
,
source
,
pdu_length
);
for
(
i
=
0
;
i
<
zero_padding
;
i
++
)
crc
=
CRC32
(
0
,
crc
);
crc
=
crc32
(
crc
,
aal5_trailer
,
4
);
crc
=
~
crc
;
aal5_trailer
[
4
]
=
crc
>>
24
;
aal5_trailer
[
5
]
=
crc
>>
16
;
aal5_trailer
[
6
]
=
crc
>>
8
;
aal5_trailer
[
7
]
=
crc
;
cell_header
[
0
]
=
ctx
->
atmHeader
>>
24
;
cell_header
[
1
]
=
ctx
->
atmHeader
>>
16
;
cell_header
[
2
]
=
ctx
->
atmHeader
>>
8
;
cell_header
[
3
]
=
ctx
->
atmHeader
;
cell_header
[
4
]
=
0xec
;
for
(
i
=
1
;
i
<
num_pdu_cells
;
i
++
)
{
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
memcpy
(
target
,
source
,
ATM_CELL_PAYLOAD
);
target
+=
ATM_CELL_PAYLOAD
;
source
+=
ATM_CELL_PAYLOAD
;
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
}
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
memcpy
(
target
,
source
,
pdu_length
%
ATM_CELL_PAYLOAD
);
target
+=
pdu_length
%
ATM_CELL_PAYLOAD
;
if
(
num_pdu_cells
<
num_cells
)
{
memset
(
target
,
0
,
zero_padding
+
ATM_AAL5_TRAILER
-
ATM_CELL_PAYLOAD
);
target
+=
zero_padding
+
ATM_AAL5_TRAILER
-
ATM_CELL_PAYLOAD
;
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
zero_padding
=
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
;
}
memset
(
target
,
0
,
zero_padding
);
target
+=
zero_padding
;
memcpy
(
target
,
aal5_trailer
,
ATM_AAL5_TRAILER
);
/* set pti bit in last cell */
*
(
target
+
ATM_AAL5_TRAILER
+
3
-
ATM_CELL_SIZE
)
|=
0x2
;
/* update stats */
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
tx
);
if
(
ctx
->
stats
&&
(
ctx
->
type
<=
ATMSAR_TYPE_AAL1
))
atomic_add
(
num_cells
,
&
(
ctx
->
stats
->
tx
));
return
final_length
;
}
struct
sk_buff
*
atmsar_encode_rawcell
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
struct
sk_buff
*
atmsar_encode_rawcell
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
{
{
int
number_of_cells
=
(
skb
->
len
)
/
48
;
int
number_of_cells
=
(
skb
->
len
)
/
48
;
...
@@ -624,9 +701,8 @@ struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_b
...
@@ -624,9 +701,8 @@ struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_b
}
else
{
}
else
{
/* If data is corrupt and skb doesn't hold a whole cell, flush the lot */
/* If data is corrupt and skb doesn't hold a whole cell, flush the lot */
if
(
skb_pull
(
skb
,
(
list
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
))
==
if
(
skb_pull
(
skb
,
(
list
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
))
==
NULL
)
{
NULL
)
skb_trim
(
skb
,
0
);
return
NULL
;
}
}
}
}
}
...
...
drivers/usb/misc/atmsar.h
View file @
20b397bb
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#define ATMSAR_USE_53BYTE_CELL 0x1L
#define ATMSAR_USE_53BYTE_CELL 0x1L
#define ATMSAR_SET_PTI 0x2L
#define ATMSAR_SET_PTI 0x2L
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
/* types */
/* types */
#define ATMSAR_TYPE_AAL0 ATM_AAL0
#define ATMSAR_TYPE_AAL0 ATM_AAL0
...
@@ -89,4 +90,6 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff
...
@@ -89,4 +90,6 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff
struct
sk_buff
*
atmsar_alloc_tx
(
struct
atmsar_vcc_data
*
vcc
,
unsigned
int
size
);
struct
sk_buff
*
atmsar_alloc_tx
(
struct
atmsar_vcc_data
*
vcc
,
unsigned
int
size
);
unsigned
int
atmsar_encode
(
struct
atmsar_vcc_data
*
ctx
,
char
*
source
,
char
*
target
,
unsigned
int
pdu_length
);
#endif
/* _ATMSAR_H_ */
#endif
/* _ATMSAR_H_ */
drivers/usb/misc/speedtouch.c
View file @
20b397bb
...
@@ -46,6 +46,7 @@
...
@@ -46,6 +46,7 @@
*
*
*/
*/
#include <asm/semaphore.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
...
@@ -58,7 +59,6 @@
...
@@ -58,7 +59,6 @@
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/atm.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmdev.h>
#include "atmsar.h"
#include "atmsar.h"
...
@@ -106,20 +106,21 @@
...
@@ -106,20 +106,21 @@
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_IN 0x87
#define UDSL_ENDPOINT_DATA_IN 0x87
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
/* usb_device_id struct */
/* usb_device_id struct */
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
}
/* list terminator
*/
{
}
/* Terminating entry
*/
};
};
/* not exporting this prevents the depmod from generating the map that causes the modules to be isnserted as driver.
MODULE_DEVICE_TABLE
(
usb
,
udsl_usb_ids
);
* we do not want this, we want the script run.
MODULE_DEVICE_TABLE ( usb, udsl_usb_ids);
*/
/* context declarations */
/* context declarations */
struct
udsl_data_ctx
{
struct
udsl_receiver
{
struct
list_head
list
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
urb
*
urb
;
struct
urb
*
urb
;
struct
udsl_instance_data
*
instance
;
struct
udsl_instance_data
*
instance
;
...
@@ -137,25 +138,32 @@ struct udsl_usb_send_data_context {
...
@@ -137,25 +138,32 @@ struct udsl_usb_send_data_context {
*/
*/
struct
udsl_instance_data
{
struct
udsl_instance_data
{
struct
tasklet_struct
recvqueue_tasklet
;
struct
semaphore
serialize
;
/* usb device part */
/* usb device part */
struct
usb_device
*
usb_dev
;
struct
usb_device
*
usb_dev
;
struct
udsl_data_ctx
*
rcvbufs
;
struct
sk_buff_head
sndqueue
;
struct
sk_buff_head
sndqueue
;
struct
udsl_usb_send_data_context
send_ctx
[
UDSL_NUMBER_SND_URBS
];
struct
udsl_usb_send_data_context
send_ctx
[
UDSL_NUMBER_SND_URBS
];
int
data_start
ed
;
int
firmware_load
ed
;
/* atm device part */
/* atm device part */
struct
atm_dev
*
atm_dev
;
struct
atm_dev
*
atm_dev
;
struct
sk_buff_head
recvqueue
;
struct
atmsar_vcc_data
*
atmsar_vcc_list
;
struct
atmsar_vcc_data
*
atmsar_vcc_list
;
};
static
const
char
udsl_driver_name
[]
=
"Alcatel SpeedTouch USB"
;
/* receiving */
struct
udsl_receiver
all_receivers
[
UDSL_NUMBER_RCV_URBS
];
spinlock_t
spare_receivers_lock
;
struct
list_head
spare_receivers
;
static
DECLARE_MUTEX
(
udsl_usb_ioctl_lock
);
spinlock_t
completed_receivers_lock
;
struct
list_head
completed_receivers
;
struct
tasklet_struct
receive_tasklet
;
};
static
const
char
udsl_driver_name
[]
=
"Alcatel SpeedTouch USB"
;
#ifdef DEBUG_PACKET
#ifdef DEBUG_PACKET
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
);
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
);
...
@@ -169,8 +177,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci);
...
@@ -169,8 +177,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci);
static
void
udsl_atm_close
(
struct
atm_vcc
*
vcc
);
static
void
udsl_atm_close
(
struct
atm_vcc
*
vcc
);
static
int
udsl_atm_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
);
static
int
udsl_atm_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
);
static
int
udsl_atm_send
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
);
static
int
udsl_atm_send
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
);
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
);
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
);
static
void
udsl_atm_processqueue
(
unsigned
long
data
);
static
struct
atmdev_ops
udsl_atm_devops
=
{
static
struct
atmdev_ops
udsl_atm_devops
=
{
.
open
=
udsl_atm_open
,
.
open
=
udsl_atm_open
,
...
@@ -203,6 +210,170 @@ static struct usb_driver udsl_usb_driver = {
...
@@ -203,6 +210,170 @@ static struct usb_driver udsl_usb_driver = {
.
id_table
=
udsl_usb_ids
,
.
id_table
=
udsl_usb_ids
,
};
};
/**************
** receive **
**************/
static
void
udsl_complete_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
udsl_instance_data
*
instance
;
struct
udsl_receiver
*
rcv
;
unsigned
long
flags
;
PDEBUG
(
"udsl_complete_receive entered
\n
"
);
if
(
!
urb
||
!
(
rcv
=
urb
->
context
)
||
!
(
instance
=
rcv
->
instance
))
{
PDEBUG
(
"udsl_complete_receive: bad urb!
\n
"
);
return
;
}
/* may not be in_interrupt() */
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
list_add_tail
(
&
rcv
->
list
,
&
instance
->
completed_receivers
);
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
PDEBUG
(
"udsl_complete_receive: scheduling tasklet
\n
"
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
}
static
void
udsl_process_receive
(
unsigned
long
data
)
{
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
udsl_receiver
*
rcv
;
unsigned
long
flags
;
unsigned
char
*
data_start
;
struct
sk_buff
*
skb
;
struct
urb
*
urb
;
struct
atmsar_vcc_data
*
atmsar_vcc
=
NULL
;
struct
sk_buff
*
new
=
NULL
,
*
tmp
=
NULL
;
PDEBUG
(
"udsl_process_receive entered
\n
"
);
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
while
(
!
list_empty
(
&
instance
->
completed_receivers
))
{
rcv
=
list_entry
(
instance
->
completed_receivers
.
next
,
struct
udsl_receiver
,
list
);
list_del
(
&
rcv
->
list
);
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
urb
=
rcv
->
urb
;
PDEBUG
(
"udsl_process_receive: got packet %p with length %d and status %d
\n
"
,
urb
,
urb
->
actual_length
,
urb
->
status
);
switch
(
urb
->
status
)
{
case
0
:
PDEBUG
(
"udsl_process_receive: processing urb with rcv %p, urb %p, skb %p
\n
"
,
rcv
,
urb
,
rcv
->
skb
);
/* update the skb structure */
skb
=
rcv
->
skb
;
skb_trim
(
skb
,
0
);
skb_put
(
skb
,
urb
->
actual_length
);
data_start
=
skb
->
data
;
PDEBUG
(
"skb->len = %d
\n
"
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
while
((
new
=
atmsar_decode_rawcell
(
instance
->
atmsar_vcc_list
,
skb
,
&
atmsar_vcc
))
!=
NULL
)
{
PDEBUG
(
"(after cell processing)skb->len = %d
\n
"
,
new
->
len
);
switch
(
atmsar_vcc
->
type
)
{
case
ATMSAR_TYPE_AAL5
:
tmp
=
new
;
new
=
atmsar_decode_aal5
(
atmsar_vcc
,
new
);
/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
if
(
new
)
{
PDEBUG
(
"(after aal5 decap) skb->len = %d
\n
"
,
new
->
len
);
if
(
new
->
len
&&
atm_charge
(
atmsar_vcc
->
vcc
,
new
->
truesize
))
{
PACKETDEBUG
(
new
->
data
,
new
->
len
);
atmsar_vcc
->
vcc
->
push
(
atmsar_vcc
->
vcc
,
new
);
}
else
{
PDEBUG
(
"dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d
\n
"
,
atomic_read
(
&
atmsar_vcc
->
vcc
->
rx_inuse
),
atmsar_vcc
->
vcc
->
sk
->
rcvbuf
,
new
->
truesize
);
dev_kfree_skb
(
new
);
}
}
else
{
PDEBUG
(
"atmsar_decode_aal5 returned NULL!
\n
"
);
dev_kfree_skb
(
tmp
);
}
break
;
default:
/* not supported. we delete the skb. */
printk
(
KERN_INFO
"SpeedTouch USB: illegal vcc type. Dropping packet.
\n
"
);
dev_kfree_skb
(
new
);
break
;
}
}
/* restore skb */
skb_push
(
skb
,
skb
->
data
-
data_start
);
usb_fill_bulk_urb
(
urb
,
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
UDSL_RECEIVE_BUFFER_SIZE
,
udsl_complete_receive
,
rcv
);
if
(
!
usb_submit_urb
(
urb
,
GFP_ATOMIC
))
break
;
PDEBUG
(
"udsl_process_receive: submission failed
\n
"
);
/* fall through */
default:
/* error or urb unlinked */
PDEBUG
(
"udsl_process_receive: adding to spare_receivers
\n
"
);
spin_lock_irqsave
(
&
instance
->
spare_receivers_lock
,
flags
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
spin_unlock_irqrestore
(
&
instance
->
spare_receivers_lock
,
flags
);
break
;
}
/* switch */
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
}
/* while */
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
PDEBUG
(
"udsl_process_receive successful
\n
"
);
}
static
void
udsl_fire_receivers
(
struct
udsl_instance_data
*
instance
)
{
struct
list_head
receivers
,
*
pos
,
*
n
;
unsigned
long
flags
;
INIT_LIST_HEAD
(
&
receivers
);
down
(
&
instance
->
serialize
);
spin_lock_irqsave
(
&
instance
->
spare_receivers_lock
,
flags
);
list_splice_init
(
&
instance
->
spare_receivers
,
&
receivers
);
spin_unlock_irqrestore
(
&
instance
->
spare_receivers_lock
,
flags
);
list_for_each_safe
(
pos
,
n
,
&
receivers
)
{
struct
udsl_receiver
*
rcv
=
list_entry
(
pos
,
struct
udsl_receiver
,
list
);
PDEBUG
(
"udsl_fire_receivers: firing urb %p
\n
"
,
rcv
->
urb
);
usb_fill_bulk_urb
(
rcv
->
urb
,
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
UDSL_RECEIVE_BUFFER_SIZE
,
udsl_complete_receive
,
rcv
);
if
(
usb_submit_urb
(
rcv
->
urb
,
GFP_KERNEL
)
<
0
)
{
PDEBUG
(
"udsl_fire_receivers: submit failed!
\n
"
);
spin_lock_irqsave
(
&
instance
->
spare_receivers_lock
,
flags
);
list_move
(
pos
,
&
instance
->
spare_receivers
);
spin_unlock_irqrestore
(
&
instance
->
spare_receivers_lock
,
flags
);
}
}
up
(
&
instance
->
serialize
);
}
/************
/************
** ATM **
** ATM **
************/
************/
...
@@ -213,27 +384,9 @@ static struct usb_driver udsl_usb_driver = {
...
@@ -213,27 +384,9 @@ static struct usb_driver udsl_usb_driver = {
*
*
****************************************************************************/
****************************************************************************/
static
struct
atm_dev
*
udsl_atm_startdevice
(
struct
udsl_instance_data
*
instance
,
struct
atmdev_ops
*
devops
)
{
MOD_INC_USE_COUNT
;
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
devops
,
-
1
,
0
);
instance
->
atm_dev
->
dev_data
=
instance
;
instance
->
atm_dev
->
ci_range
.
vpi_bits
=
ATM_CI_MAX
;
instance
->
atm_dev
->
ci_range
.
vci_bits
=
ATM_CI_MAX
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
skb_queue_head_init
(
&
instance
->
recvqueue
);
/* tmp init atm device, set to 128kbit */
instance
->
atm_dev
->
link_rate
=
128
*
1000
/
424
;
return
instance
->
atm_dev
;
}
static
void
udsl_atm_stopdevice
(
struct
udsl_instance_data
*
instance
)
static
void
udsl_atm_stopdevice
(
struct
udsl_instance_data
*
instance
)
{
{
struct
atm_vcc
*
walk
;
struct
atm_vcc
*
walk
;
struct
sk_buff
*
skb
;
struct
atm_dev
*
atm_dev
;
struct
atm_dev
*
atm_dev
;
if
(
!
instance
->
atm_dev
)
if
(
!
instance
->
atm_dev
)
...
@@ -241,10 +394,6 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
...
@@ -241,10 +394,6 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
atm_dev
=
instance
->
atm_dev
;
atm_dev
=
instance
->
atm_dev
;
/* clean queue */
while
((
skb
=
skb_dequeue
(
&
instance
->
recvqueue
)))
dev_kfree_skb
(
skb
);
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
walk
=
atm_dev
->
vccs
;
walk
=
atm_dev
->
vccs
;
shutdown_atm_dev
(
atm_dev
);
shutdown_atm_dev
(
atm_dev
);
...
@@ -253,16 +402,8 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
...
@@ -253,16 +402,8 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
wake_up
(
&
walk
->
sleep
);
wake_up
(
&
walk
->
sleep
);
instance
->
atm_dev
=
NULL
;
instance
->
atm_dev
=
NULL
;
MOD_DEC_USE_COUNT
;
}
}
static
void
udsl_atm_set_mac
(
struct
udsl_instance_data
*
instance
,
const
char
mac
[
6
])
{
if
(
!
instance
->
atm_dev
)
return
;
memcpy
(
instance
->
atm_dev
->
esi
,
mac
,
6
);
}
/***************************************************************************
/***************************************************************************
*
*
...
@@ -281,11 +422,16 @@ static struct sk_buff *udsl_atm_alloc_tx (struct atm_vcc *vcc, unsigned int size
...
@@ -281,11 +422,16 @@ static struct sk_buff *udsl_atm_alloc_tx (struct atm_vcc *vcc, unsigned int size
return
NULL
;
return
NULL
;
}
}
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
)
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
)
{
{
struct
udsl_instance_data
*
instance
=
atm_dev
->
dev_data
;
struct
udsl_instance_data
*
instance
=
atm_dev
->
dev_data
;
int
left
=
*
pos
;
int
left
=
*
pos
;
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
if
(
!
left
--
)
if
(
!
left
--
)
return
sprintf
(
page
,
"SpeedTouch USB %s-%s (%02x:%02x:%02x:%02x:%02x:%02x)
\n
"
,
return
sprintf
(
page
,
"SpeedTouch USB %s-%s (%02x:%02x:%02x:%02x:%02x:%02x)
\n
"
,
instance
->
usb_dev
->
bus
->
bus_name
,
instance
->
usb_dev
->
devpath
,
instance
->
usb_dev
->
bus
->
bus_name
,
instance
->
usb_dev
->
devpath
,
...
@@ -311,6 +457,7 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t * pos, char *page
...
@@ -311,6 +457,7 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t * pos, char *page
return
0
;
return
0
;
}
}
/***************************************************************************
/***************************************************************************
*
*
* ATM DATA functions
* ATM DATA functions
...
@@ -325,8 +472,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
...
@@ -325,8 +472,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
PDEBUG
(
"udsl_atm_send called
\n
"
);
PDEBUG
(
"udsl_atm_send called
\n
"
);
if
(
!
dev_data
)
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL data!
\n
"
);
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
!
instance
->
firmware_loaded
)
return
-
EAGAIN
;
switch
(
vcc
->
qos
.
aal
)
{
switch
(
vcc
->
qos
.
aal
)
{
case
ATM_AAL5
:
case
ATM_AAL5
:
...
@@ -350,67 +502,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
...
@@ -350,67 +502,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
break
;
break
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
;
}
PDEBUG
(
"udsl_atm_send unsuccessfull
\n
"
);
PDEBUG
(
"udsl_atm_send unsuccessfull
\n
"
);
return
0
;
return
0
;
nomem:
nomem:
vcc
->
pop
(
vcc
,
skb
);
vcc
->
pop
(
vcc
,
skb
);
return
-
ENOMEM
;
return
-
ENOMEM
;
};
static
void
udsl_atm_processqueue
(
unsigned
long
data
)
{
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
atmsar_vcc_data
*
atmsar_vcc
=
NULL
;
struct
sk_buff
*
new
=
NULL
,
*
skb
=
NULL
,
*
tmp
=
NULL
;
PDEBUG
(
"udsl_atm_processqueue entered
\n
"
);
while
((
skb
=
skb_dequeue
(
&
instance
->
recvqueue
)))
{
PDEBUG
(
"skb = %p, skb->len = %d
\n
"
,
skb
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
while
((
new
=
atmsar_decode_rawcell
(
instance
->
atmsar_vcc_list
,
skb
,
&
atmsar_vcc
))
!=
NULL
)
{
PDEBUG
(
"(after cell processing)skb->len = %d
\n
"
,
new
->
len
);
switch
(
atmsar_vcc
->
type
)
{
case
ATMSAR_TYPE_AAL5
:
tmp
=
new
;
new
=
atmsar_decode_aal5
(
atmsar_vcc
,
new
);
/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
if
(
new
)
{
PDEBUG
(
"(after aal5 decap) skb->len = %d
\n
"
,
new
->
len
);
if
(
new
->
len
&&
atm_charge
(
atmsar_vcc
->
vcc
,
new
->
truesize
))
{
PACKETDEBUG
(
new
->
data
,
new
->
len
);
atmsar_vcc
->
vcc
->
push
(
atmsar_vcc
->
vcc
,
new
);
}
else
{
PDEBUG
(
"dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d
\n
"
,
atomic_read
(
&
atmsar_vcc
->
vcc
->
rx_inuse
),
atmsar_vcc
->
vcc
->
sk
->
rcvbuf
,
new
->
truesize
);
dev_kfree_skb
(
new
);
}
}
else
{
PDEBUG
(
"atmsar_decode_aal5 returned NULL!
\n
"
);
dev_kfree_skb
(
tmp
);
}
break
;
default:
/* not supported. we delete the skb. */
printk
(
KERN_INFO
"SpeedTouch USB: illegal vcc type. Dropping packet.
\n
"
);
dev_kfree_skb
(
new
);
break
;
}
};
dev_kfree_skb
(
skb
);
};
PDEBUG
(
"udsl_atm_processqueue successfull
\n
"
);
}
}
...
@@ -419,6 +517,7 @@ static void udsl_atm_processqueue (unsigned long data)
...
@@ -419,6 +517,7 @@ static void udsl_atm_processqueue (unsigned long data)
* SAR driver entries
* SAR driver entries
*
*
****************************************************************************/
****************************************************************************/
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
{
{
struct
udsl_atm_dev_data
*
dev_data
;
struct
udsl_atm_dev_data
*
dev_data
;
...
@@ -426,6 +525,11 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -426,6 +525,11 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
PDEBUG
(
"udsl_atm_open called
\n
"
);
PDEBUG
(
"udsl_atm_open called
\n
"
);
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
/* at the moment only AAL5 support */
/* at the moment only AAL5 support */
if
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
if
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -453,6 +557,9 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -453,6 +557,9 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
dev_data
->
atmsar_vcc
->
mtu
=
UDSL_MAX_AAL5_MRU
;
dev_data
->
atmsar_vcc
->
mtu
=
UDSL_MAX_AAL5_MRU
;
if
(
instance
->
firmware_loaded
)
udsl_fire_receivers
(
instance
);
PDEBUG
(
"udsl_atm_open successfull
\n
"
);
PDEBUG
(
"udsl_atm_open successfull
\n
"
);
return
0
;
return
0
;
}
}
...
@@ -464,6 +571,11 @@ static void udsl_atm_close (struct atm_vcc *vcc)
...
@@ -464,6 +571,11 @@ static void udsl_atm_close (struct atm_vcc *vcc)
PDEBUG
(
"udsl_atm_close called
\n
"
);
PDEBUG
(
"udsl_atm_close called
\n
"
);
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL data!
\n
"
);
return
;
}
/* freeing resources */
/* freeing resources */
/* cancel all sends on this vcc */
/* cancel all sends on this vcc */
udsl_usb_cancelsends
(
instance
,
vcc
);
udsl_usb_cancelsends
(
instance
,
vcc
);
...
@@ -482,7 +594,7 @@ static void udsl_atm_close (struct atm_vcc *vcc)
...
@@ -482,7 +594,7 @@ static void udsl_atm_close (struct atm_vcc *vcc)
PDEBUG
(
"udsl_atm_close successfull
\n
"
);
PDEBUG
(
"udsl_atm_close successfull
\n
"
);
return
;
return
;
}
;
}
static
int
udsl_atm_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
)
static
int
udsl_atm_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
)
{
{
...
@@ -492,7 +604,7 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
...
@@ -492,7 +604,7 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
default:
default:
return
-
ENOIOCTLCMD
;
return
-
ENOIOCTLCMD
;
}
}
}
;
}
/************
/************
...
@@ -566,9 +678,6 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
...
@@ -566,9 +678,6 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
PDEBUG
(
"udsl_usb_send_data entered, sending packet %p with length %d
\n
"
,
skb
,
skb
->
len
);
PDEBUG
(
"udsl_usb_send_data entered, sending packet %p with length %d
\n
"
,
skb
,
skb
->
len
);
if
(
!
instance
->
data_started
)
return
-
EAGAIN
;
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
spin_lock_irqsave
(
&
instance
->
sndqueue
.
lock
,
flags
);
spin_lock_irqsave
(
&
instance
->
sndqueue
.
lock
,
flags
);
...
@@ -592,7 +701,7 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
...
@@ -592,7 +701,7 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
PDEBUG
(
"udsl_usb_send_data: skb (0x%p) queued
\n
"
,
skb
);
PDEBUG
(
"udsl_usb_send_data: skb (0x%p) queued
\n
"
,
skb
);
return
0
;
return
0
;
}
;
}
/* init context */
/* init context */
urb
=
instance
->
send_ctx
[
i
].
urb
;
urb
=
instance
->
send_ctx
[
i
].
urb
;
...
@@ -620,285 +729,264 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
...
@@ -620,285 +729,264 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
return
err
;
return
err
;
}
}
/********* receive *******/
static
void
udsl_usb_data_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
udsl_data_ctx
*
ctx
;
struct
udsl_instance_data
*
instance
;
if
(
!
urb
)
/***************************************************************************
return
;
*
* usb driver entries
*
****************************************************************************/
PDEBUG
(
"udsl_usb_receive_data entered, got packet %p with length %d an status %d
\n
"
,
urb
,
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
urb
->
actual_length
,
urb
->
status
);
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
ctx
=
urb
->
context
;
PDEBUG
(
"udsl_usb_ioctl entered
\n
"
);
if
(
!
ctx
||
!
ctx
->
skb
)
return
;
instance
=
ctx
->
instance
;
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
switch
(
urb
->
status
)
{
switch
(
code
)
{
case
0
:
case
UDSL_IOCTL_START
:
PDEBUG
(
"udsl_usb_data_receive: processing urb with ctx %p, urb %p (%p), skb %p
\n
"
,
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
ctx
,
ctx
?
ctx
->
urb
:
NULL
,
urb
,
ctx
?
ctx
->
skb
:
NULL
);
down
(
&
instance
->
serialize
);
/* vs self */
/* update the skb structure */
if
(
!
instance
->
firmware_loaded
)
{
skb_put
(
ctx
->
skb
,
urb
->
actual_length
);
usb_set_interface
(
instance
->
usb_dev
,
1
,
2
);
instance
->
firmware_loaded
=
1
;
/* queue the skb for processing and wake the SAR */
skb_queue_tail
(
&
instance
->
recvqueue
,
ctx
->
skb
);
tasklet_schedule
(
&
instance
->
recvqueue_tasklet
);
/* get a new skb */
ctx
->
skb
=
dev_alloc_skb
(
UDSL_RECEIVE_BUFFER_SIZE
);
if
(
!
ctx
->
skb
)
{
PDEBUG
(
"No skb, loosing urb.
\n
"
);
usb_free_urb
(
ctx
->
urb
);
ctx
->
urb
=
NULL
;
return
;
}
}
break
;
up
(
&
instance
->
serialize
)
;
case
-
ENOENT
:
/* buffer was unlinked */
udsl_fire_receivers
(
instance
);
case
-
EILSEQ
:
/* unplug or timeout */
return
0
;
case
-
ETIMEDOUT
:
/* unplug or timeout */
case
UDSL_IOCTL_STOP
:
/*
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
* we don't do anything here and we don't resubmit
return
0
;
*/
default:
return
;
return
-
ENOTTY
;
}
}
}
usb_fill_bulk_urb
(
urb
,
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
ctx
->
skb
->
data
,
UDSL_RECEIVE_BUFFER_SIZE
,
udsl_usb_data_receive
,
ctx
);
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
return
;
};
static
int
udsl_usb_data_init
(
struct
udsl_instance_data
*
instance
)
{
{
int
i
,
succes
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
int
ifnum
=
intf
->
altsetting
->
desc
.
bInterfaceNumber
;
struct
udsl_instance_data
*
instance
;
unsigned
char
mac_str
[
13
];
unsigned
char
mac
[
6
];
int
i
,
err
;
if
(
instance
->
data_started
)
PDEBUG
(
"Trying device with Vendor=0x%x, Product=0x%x, ifnum %d
\n
"
,
return
1
;
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
ifnum
)
;
/* set alternate setting 1 on interface 1 */
if
((
dev
->
descriptor
.
bDeviceClass
!=
USB_CLASS_VENDOR_SPEC
)
||
usb_set_interface
(
instance
->
usb_dev
,
1
,
2
);
(
dev
->
descriptor
.
idVendor
!=
SPEEDTOUCH_VENDORID
)
||
(
dev
->
descriptor
.
idProduct
!=
SPEEDTOUCH_PRODUCTID
)
||
(
ifnum
!=
1
))
return
-
ENODEV
;
PDEBUG
(
"max packet size on endpoint %d is %d
\n
"
,
UDSL_ENDPOINT_DATA_OUT
,
PDEBUG
(
"Device Accepted
\n
"
);
usb_maxpacket
(
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
0
));
instance
->
rcvbufs
=
kmalloc
(
sizeof
(
struct
udsl_data_ctx
)
*
UDSL_NUMBER_RCV_URBS
,
GFP_KERNEL
);
/* instance init */
if
(
!
instance
->
rcvbufs
)
if
(
!
(
instance
=
kmalloc
(
sizeof
(
struct
udsl_instance_data
),
GFP_KERNEL
)))
{
return
-
ENOMEM
;
PDEBUG
(
"No memory for Instance data!
\n
"
);
err
=
-
ENOMEM
;
goto
fail_instance
;
}
memset
(
instance
->
rcvbufs
,
0
,
sizeof
(
struct
udsl_data_ctx
)
*
UDSL_NUMBER_RCV_URBS
);
memset
(
instance
,
0
,
sizeof
(
struct
udsl_instance_data
)
);
skb_queue_head_init
(
&
instance
->
sndqueu
e
);
init_MUTEX
(
&
instance
->
serializ
e
);
for
(
i
=
0
,
succes
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
instance
->
usb_dev
=
dev
;
struct
udsl_data_ctx
*
ctx
=
&
(
instance
->
rcvbufs
[
i
]);
ctx
->
urb
=
NULL
;
spin_lock_init
(
&
instance
->
spare_receivers_lock
);
ctx
->
skb
=
dev_alloc_skb
(
UDSL_RECEIVE_BUFFER_SIZE
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
if
(
!
ctx
->
skb
)
continue
;
ctx
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
spin_lock_init
(
&
instance
->
completed_receivers_lock
);
if
(
!
ctx
->
urb
)
{
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
kfree_skb
(
ctx
->
skb
);
ctx
->
skb
=
NULL
;
break
;
};
usb_fill_bulk_urb
(
ctx
->
urb
,
tasklet_init
(
&
instance
->
receive_tasklet
,
udsl_process_receive
,
(
unsigned
long
)
instance
);
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
ctx
->
skb
->
data
,
UDSL_RECEIVE_BUFFER_SIZE
,
udsl_usb_data_receive
,
ctx
);
skb_queue_head_init
(
&
instance
->
sndqueue
);
ctx
->
instance
=
instance
;
/* receive urb init */
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
PDEBUG
(
"udsl_usb_data_init: usb with skb->truesize = %d (Asked for %d)
\n
"
,
if
(
!
(
rcv
->
skb
=
dev_alloc_skb
(
UDSL_RECEIVE_BUFFER_SIZE
)))
{
ctx
->
skb
->
truesize
,
UDSL_RECEIVE_BUFFER_SIZE
);
PDEBUG
(
"No memory for skb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
}
if
(
usb_submit_urb
(
ctx
->
urb
,
GFP_KERNEL
)
<
0
)
if
(
!
(
rcv
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
PDEBUG
(
"
udsl_usb_data_init: Submit failed, loosing urb.
\n
"
);
PDEBUG
(
"
No memory for receive urb %d!
\n
"
,
i
);
else
err
=
-
ENOMEM
;
succes
++
;
goto
fail_urbs
;
}
}
PDEBUG
(
"udsl_usb_data_init %d urb%s queued for receive
\n
"
,
succes
,
rcv
->
instance
=
instance
;
(
succes
!=
1
)
?
"s"
:
""
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
for
(
i
=
0
,
succes
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
PDEBUG
(
"skb->truesize = %d (asked for %d)
\n
"
,
rcv
->
skb
->
truesize
,
UDSL_RECEIVE_BUFFER_SIZE
);
instance
->
send_ctx
[
i
].
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
PDEBUG
(
"udsl_usb_data_init: send urb allocted address %p
\n
"
,
instance
->
send_ctx
[
i
].
urb
);
if
(
instance
->
send_ctx
[
i
].
urb
)
succes
++
;
}
}
PDEBUG
(
"udsl_usb_data_init %d urb%s queued for send
\n
"
,
succes
,
(
succes
!=
1
)
?
"s"
:
""
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_usb_send_data_context
*
snd
=
&
(
instance
->
send_ctx
[
i
]);
instance
->
data_started
=
1
;
if
(
!
(
snd
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
PDEBUG
(
"No memory for send urb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
}
return
0
;
snd
->
instance
=
instance
;
}
}
static
int
udsl_usb_data_exit
(
struct
udsl_instance_data
*
instance
)
/* atm init */
{
if
(
!
(
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
&
udsl_atm_devops
,
-
1
,
0
)))
{
int
i
;
PDEBUG
(
"failed to register ATM device!
\n
"
);
err
=
-
ENOMEM
;
goto
fail_atm
;
}
if
(
!
instance
->
data_started
)
instance
->
atm_dev
->
ci_range
.
vpi_bits
=
ATM_CI_MAX
;
return
0
;
instance
->
atm_dev
->
ci_range
.
vci_bits
=
ATM_CI_MAX
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
if
(
!
instance
->
rcvbufs
)
/* tmp init atm device, set to 128kbit */
return
0
;
instance
->
atm_dev
->
link_rate
=
128
*
1000
/
424
;
/* destroy urbs */
/* set MAC address, it is stored in the serial number */
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
usb_string
(
instance
->
usb_dev
,
instance
->
usb_dev
->
descriptor
.
iSerialNumber
,
mac_str
,
13
);
struct
udsl_data_ctx
*
ctx
=
&
(
instance
->
rcvbufs
[
i
]);
for
(
i
=
0
;
i
<
6
;
i
++
)
mac
[
i
]
=
(
hex2int
(
mac_str
[
i
*
2
])
*
16
)
+
(
hex2int
(
mac_str
[
i
*
2
+
1
]));
if
((
!
ctx
->
urb
)
||
(
!
ctx
->
skb
))
PDEBUG
(
"MAC is %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]);
continue
;
usb_unlink_urb
(
ctx
->
urb
);
memcpy
(
instance
->
atm_dev
->
esi
,
mac
,
6
);
usb_free_urb
(
ctx
->
urb
);
wmb
();
kfree_skb
(
ctx
->
skb
);
ctx
->
skb
=
NULL
;
instance
->
atm_dev
->
dev_data
=
instance
;
}
tasklet_kill
(
&
instance
->
recvqueue_tasklet
);
usb_set_intfdata
(
intf
,
instance
);
return
0
;
fail_atm:
fail_urbs:
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_usb_send_data_context
*
ctx
=
&
(
instance
->
send_ctx
[
i
]);
struct
udsl_usb_send_data_context
*
snd
=
&
(
instance
->
send_ctx
[
i
]);
usb_unlink_urb
(
ctx
->
urb
);
if
(
snd
->
urb
)
usb_free_urb
(
snd
->
urb
);
}
if
(
ctx
->
skb
)
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
ctx
->
skb
=
NULL
;
usb_free_urb
(
ctx
->
urb
);
if
(
rcv
->
skb
)
kfree_skb
(
rcv
->
skb
);
if
(
rcv
->
urb
)
usb_free_urb
(
rcv
->
urb
);
}
}
kfree
(
instance
);
fail_instance:
return
err
;
}
/* free receive contexts */
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
)
kfree
(
instance
->
rcvbufs
);
{
instance
->
rcvbufs
=
NULL
;
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
struct
list_head
*
pos
;
unsigned
long
flags
;
unsigned
int
count
=
0
;
int
i
;
instance
->
data_started
=
0
;
PDEBUG
(
"disconnecting
\n
"
);
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
return
0
;
usb_set_intfdata
(
intf
,
NULL
);
};
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
;
}
/***************************************************************************
tasklet_disable
(
&
instance
->
receive_tasklet
);
*
* usb driver entries
*
****************************************************************************/
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
down
(
&
instance
->
serialize
);
/* vs udsl_fire_receivers */
/* no need to take the spinlock - receive_tasklet is not running */
list_for_each
(
pos
,
&
instance
->
spare_receivers
)
if
(
++
count
>
UDSL_NUMBER_RCV_URBS
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
up
(
&
instance
->
serialize
);
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
PDEBUG
(
"udsl_usb_disconnect: flushed %u spare receivers
\n
"
,
count
);
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
int
retval
;
down
(
&
udsl_usb_ioctl_lock
);
count
=
UDSL_NUMBER_RCV_URBS
-
count
;
switch
(
code
)
{
case
UDSL_IOCTL_START
:
retval
=
udsl_usb_data_init
(
instance
);
break
;
case
UDSL_IOCTL_STOP
:
retval
=
udsl_usb_data_exit
(
instance
);
break
;
default:
retval
=
-
ENOTTY
;
break
;
}
up
(
&
udsl_usb_ioctl_lock
);
return
retval
;
}
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
usb_unlink_urb
(
instance
->
all_receivers
[
i
].
urb
);
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
int
ifnum
=
intf
->
altsetting
->
desc
.
bInterfaceNumber
;
int
i
;
unsigned
char
mac
[
6
];
unsigned
char
mac_str
[
13
];
struct
udsl_instance_data
*
instance
=
NULL
;
PDEBUG
(
"Trying device with Vendor=0x%x, Product=0x%x, ifnum %d
\n
"
,
/* wait for completion handlers to finish */
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
ifnum
);
do
{
unsigned
int
completed
=
0
;
if
((
dev
->
descriptor
.
bDeviceClass
!=
USB_CLASS_VENDOR_SPEC
)
||
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
(
dev
->
descriptor
.
idVendor
!=
SPEEDTOUCH_VENDORID
)
||
list_for_each
(
pos
,
&
instance
->
completed_receivers
)
(
dev
->
descriptor
.
idProduct
!=
SPEEDTOUCH_PRODUCTID
)
||
(
ifnum
!=
1
))
if
(
++
completed
>
count
)
return
-
ENODEV
;
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
MOD_INC_USE_COUNT
;
PDEBUG
(
"udsl_usb_disconnect: found %u completed receivers
\n
"
,
completed
)
;
PDEBUG
(
"Device Accepted
\n
"
);
if
(
completed
==
count
)
break
;
/* device init */
/* not all urbs completed */
instance
=
kmalloc
(
sizeof
(
struct
udsl_instance_data
),
GFP_KERNEL
);
yield
();
if
(
!
instance
)
{
}
while
(
1
);
PDEBUG
(
"No memory for Instance data!
\n
"
);
return
-
ENOMEM
;
}
/* initialize structure */
PDEBUG
(
"udsl_usb_disconnect: flushing %u completed receivers
\n
"
,
count
);
memset
(
instance
,
0
,
sizeof
(
struct
udsl_instance_data
));
/* no need to take the spinlock - no completion handlers running */
instance
->
usb_dev
=
dev
;
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
instance
->
rcvbufs
=
NULL
;
tasklet_init
(
&
instance
->
recvqueue_tasklet
,
udsl_atm_processqueue
,
(
unsigned
long
)
instance
);
udsl_atm_startdevice
(
instance
,
&
udsl_atm_devops
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
tasklet_kill
(
&
instance
->
receive_tasklet
);
/* set MAC address, it is stored in the serial number */
PDEBUG
(
"udsl_usb_disconnect: freeing receivers
\n
"
);
usb_string
(
instance
->
usb_dev
,
instance
->
usb_dev
->
descriptor
.
iSerialNumber
,
mac_str
,
13
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
6
;
i
++
)
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
mac
[
i
]
=
(
hex2int
(
mac_str
[
i
*
2
])
*
16
)
+
(
hex2int
(
mac_str
[
i
*
2
+
1
]));
PDEBUG
(
"MAC is %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
usb_free_urb
(
rcv
->
urb
);
mac
[
5
]
);
kfree_skb
(
rcv
->
skb
);
udsl_atm_set_mac
(
instance
,
mac
);
}
usb_set_intfdata
(
intf
,
instance
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
return
0
;
struct
udsl_usb_send_data_context
*
ctx
=
&
(
instance
->
send_ctx
[
i
]);
}
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
)
usb_unlink_urb
(
ctx
->
urb
);
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
PDEBUG
(
"disconnecting
\n
"
);
if
(
ctx
->
skb
)
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
ctx
->
skb
=
NULL
;
usb_free_urb
(
ctx
->
urb
);
}
usb_set_intfdata
(
intf
,
NULL
);
if
(
instance
)
{
/* unlinking receive buffers */
udsl_usb_data_exit
(
instance
);
/* removing atm device */
/* removing atm device */
if
(
instance
->
atm_dev
)
if
(
instance
->
atm_dev
)
udsl_atm_stopdevice
(
instance
);
udsl_atm_stopdevice
(
instance
);
kfree
(
instance
);
kfree
(
instance
);
MOD_DEC_USE_COUNT
;
}
}
}
/***************************************************************************
/***************************************************************************
*
*
* Driver Init
* Driver Init
...
@@ -907,18 +995,25 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -907,18 +995,25 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
static
int
__init
udsl_usb_init
(
void
)
static
int
__init
udsl_usb_init
(
void
)
{
{
PDEBUG
(
"
Initializing SpeedTouch Driver V
ersion "
DRIVER_VERSION
"
\n
"
);
PDEBUG
(
"
udsl_usb_init: driver v
ersion "
DRIVER_VERSION
"
\n
"
);
return
usb_register
(
&
udsl_usb_driver
);
return
usb_register
(
&
udsl_usb_driver
);
}
}
static
void
__exit
udsl_usb_cleanup
(
void
)
static
void
__exit
udsl_usb_cleanup
(
void
)
{
{
PDEBUG
(
"udsl_usb_cleanup
\n
"
);
usb_deregister
(
&
udsl_usb_driver
);
usb_deregister
(
&
udsl_usb_driver
);
}
}
module_init
(
udsl_usb_init
);
module_init
(
udsl_usb_init
);
module_exit
(
udsl_usb_cleanup
);
module_exit
(
udsl_usb_cleanup
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG_PACKET
#ifdef DEBUG_PACKET
/*******************************************************************************
/*******************************************************************************
...
@@ -929,7 +1024,7 @@ module_exit(udsl_usb_cleanup);
...
@@ -929,7 +1024,7 @@ module_exit(udsl_usb_cleanup);
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
)
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
)
{
{
unsigned
char
buffer
[
256
];
unsigned
char
buffer
[
256
];
int
i
=
0
,
j
=
0
;
int
i
=
0
,
j
=
0
;
for
(
i
=
0
;
i
<
len
;)
{
for
(
i
=
0
;
i
<
len
;)
{
...
@@ -941,10 +1036,6 @@ static int udsl_print_packet (const unsigned char *data, int len)
...
@@ -941,10 +1036,6 @@ static int udsl_print_packet (const unsigned char *data, int len)
PDEBUG
(
"%s
\n
"
,
buffer
);
PDEBUG
(
"%s
\n
"
,
buffer
);
}
}
return
i
;
return
i
;
}
;
}
#endif
/* PACKETDEBUG */
#endif
/* PACKETDEBUG */
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
drivers/usb/net/Makefile.mii
0 → 100644
View file @
20b397bb
#
# Makefile for USB Network drivers which require generic MII code.
#
obj-$(CONFIG_USB_PEGASUS)
+=
mii.o
drivers/usb/serial/ftdi_sio.c
View file @
20b397bb
...
@@ -135,6 +135,7 @@ static struct usb_device_id id_table_sio [] = {
...
@@ -135,6 +135,7 @@ static struct usb_device_id id_table_sio [] = {
static
struct
usb_device_id
id_table_8U232AM
[]
=
{
static
struct
usb_device_id
id_table_8U232AM
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_RELAIS_PID
)
},
{
USB_DEVICE
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
)
},
{
USB_DEVICE
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
)
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
@@ -143,6 +144,7 @@ static struct usb_device_id id_table_8U232AM [] = {
...
@@ -143,6 +144,7 @@ static struct usb_device_id id_table_8U232AM [] = {
static
struct
usb_device_id
id_table_combined
[]
=
{
static
struct
usb_device_id
id_table_combined
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_SIO_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_SIO_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_RELAIS_PID
)
},
{
USB_DEVICE
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
)
},
{
USB_DEVICE
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
)
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
...
drivers/usb/serial/ftdi_sio.h
View file @
20b397bb
...
@@ -17,11 +17,14 @@
...
@@ -17,11 +17,14 @@
* Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the
* Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the
* FTDI_SIO implementation.
* FTDI_SIO implementation.
*
*
* Philipp Ghring - pg@futureware.at - added the Device ID of the USB relais
* from Rudolf Gugler
*/
*/
#define FTDI_VID 0x0403
/* Vendor Id */
#define FTDI_VID 0x0403
/* Vendor Id */
#define FTDI_SIO_PID 0x8372
/* Product Id SIO application of 8U100AX */
#define FTDI_SIO_PID 0x8372
/* Product Id SIO application of 8U100AX */
#define FTDI_8U232AM_PID 0x6001
/* Similar device to SIO above */
#define FTDI_8U232AM_PID 0x6001
/* Similar device to SIO above */
#define FTDI_RELAIS_PID 0xFA10
/* Relais device from Rudolf Gugler */
#define FTDI_NF_RIC_VID 0x0DCD
/* Vendor Id */
#define FTDI_NF_RIC_VID 0x0DCD
/* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001
/* Product Id */
#define FTDI_NF_RIC_PID 0x0001
/* Product Id */
...
...
drivers/usb/serial/ipaq.c
View file @
20b397bb
...
@@ -106,6 +106,7 @@ static struct usb_device_id ipaq_id_table [] = {
...
@@ -106,6 +106,7 @@ static struct usb_device_id ipaq_id_table [] = {
{
USB_DEVICE
(
CASIO_VENDOR_ID
,
CASIO_EM500_ID
)
},
{
USB_DEVICE
(
CASIO_VENDOR_ID
,
CASIO_EM500_ID
)
},
{
USB_DEVICE
(
COMPAQ_VENDOR_ID
,
COMPAQ_IPAQ_ID
)
},
{
USB_DEVICE
(
COMPAQ_VENDOR_ID
,
COMPAQ_IPAQ_ID
)
},
{
USB_DEVICE
(
COMPAQ_VENDOR_ID
,
COMPAQ_0032_ID
)
},
{
USB_DEVICE
(
COMPAQ_VENDOR_ID
,
COMPAQ_0032_ID
)
},
{
USB_DEVICE
(
DELL_VENDOR_ID
,
DELL_AXIM_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_JORNADA_548_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_JORNADA_548_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_JORNADA_568_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_JORNADA_568_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_2016_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_2016_ID
)
},
...
@@ -126,6 +127,7 @@ static struct usb_device_id ipaq_id_table [] = {
...
@@ -126,6 +127,7 @@ static struct usb_device_id ipaq_id_table [] = {
{
USB_DEVICE
(
SAGEM_VENDOR_ID
,
SAGEM_WIRELESS_ID
)
},
{
USB_DEVICE
(
SAGEM_VENDOR_ID
,
SAGEM_WIRELESS_ID
)
},
{
USB_DEVICE
(
SOCKET_VENDOR_ID
,
SOCKET_PRODUCT_ID
)
},
{
USB_DEVICE
(
SOCKET_VENDOR_ID
,
SOCKET_PRODUCT_ID
)
},
{
USB_DEVICE
(
TOSHIBA_VENDOR_ID
,
TOSHIBA_PRODUCT_ID
)
},
{
USB_DEVICE
(
TOSHIBA_VENDOR_ID
,
TOSHIBA_PRODUCT_ID
)
},
{
USB_DEVICE
(
TOSHIBA_VENDOR_ID
,
TOSHIBA_E740_ID
)
},
{
USB_DEVICE
(
HTC_VENDOR_ID
,
HTC_PRODUCT_ID
)
},
{
USB_DEVICE
(
HTC_VENDOR_ID
,
HTC_PRODUCT_ID
)
},
{
USB_DEVICE
(
NEC_VENDOR_ID
,
NEC_PRODUCT_ID
)
},
{
USB_DEVICE
(
NEC_VENDOR_ID
,
NEC_PRODUCT_ID
)
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
...
...
drivers/usb/serial/ipaq.h
View file @
20b397bb
...
@@ -30,6 +30,9 @@
...
@@ -30,6 +30,9 @@
#define COMPAQ_IPAQ_ID 0x0003
#define COMPAQ_IPAQ_ID 0x0003
#define COMPAQ_0032_ID 0x0032
#define COMPAQ_0032_ID 0x0032
#define DELL_VENDOR_ID 0x413c
#define DELL_AXIM_ID 0x4001
#define HP_VENDOR_ID 0x03f0
#define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
#define HP_JORNADA_568_ID 0x1116
...
@@ -63,6 +66,7 @@
...
@@ -63,6 +66,7 @@
#define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_PRODUCT_ID 0x0700
#define TOSHIBA_PRODUCT_ID 0x0700
#define TOSHIBA_E740_ID 0x0706
#define HTC_VENDOR_ID 0x0bb4
#define HTC_VENDOR_ID 0x0bb4
#define HTC_PRODUCT_ID 0x00ce
#define HTC_PRODUCT_ID 0x00ce
...
...
drivers/usb/serial/pl2303.c
View file @
20b397bb
...
@@ -74,6 +74,7 @@ static struct usb_device_id id_table [] = {
...
@@ -74,6 +74,7 @@ static struct usb_device_id id_table [] = {
{
USB_DEVICE
(
ITEGNO_VENDOR_ID
,
ITEGNO_PRODUCT_ID
)
},
{
USB_DEVICE
(
ITEGNO_VENDOR_ID
,
ITEGNO_PRODUCT_ID
)
},
{
USB_DEVICE
(
MA620_VENDOR_ID
,
MA620_PRODUCT_ID
)
},
{
USB_DEVICE
(
MA620_VENDOR_ID
,
MA620_PRODUCT_ID
)
},
{
USB_DEVICE
(
RATOC_VENDOR_ID
,
RATOC_PRODUCT_ID
)
},
{
USB_DEVICE
(
RATOC_VENDOR_ID
,
RATOC_PRODUCT_ID
)
},
{
USB_DEVICE
(
TRIPP_VENDOR_ID
,
TRIPP_PRODUCT_ID
)
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
...
drivers/usb/serial/pl2303.h
View file @
20b397bb
...
@@ -28,3 +28,6 @@
...
@@ -28,3 +28,6 @@
#define RATOC_VENDOR_ID 0x0584
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID 0xb000
#define RATOC_PRODUCT_ID 0xb000
#define TRIPP_VENDOR_ID 0x2478
#define TRIPP_PRODUCT_ID 0x2008
drivers/usb/storage/datafab.h
View file @
20b397bb
drivers/usb/storage/freecom.c
View file @
20b397bb
drivers/usb/storage/isd200.c
View file @
20b397bb
drivers/usb/storage/protocol.h
View file @
20b397bb
drivers/usb/storage/scsiglue.c
View file @
20b397bb
...
@@ -50,23 +50,25 @@
...
@@ -50,23 +50,25 @@
#include "transport.h"
#include "transport.h"
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/module.h>
/***********************************************************************
/***********************************************************************
* Host functions
* Host functions
***********************************************************************/
***********************************************************************/
static
const
char
*
host
_info
(
struct
Scsi_Host
*
host
)
static
const
char
*
usb_storage
_info
(
struct
Scsi_Host
*
host
)
{
{
return
"SCSI emulation for USB Mass Storage devices"
;
return
"SCSI emulation for USB Mass Storage devices"
;
}
}
#if 0
/* detect a virtual adapter (always works)
/* detect a virtual adapter (always works)
* Synchronization: 2.4: with the io_request_lock
* Synchronization: 2.4: with the io_request_lock
* 2.5: no locks.
* 2.5: no locks.
* fortunately we don't care.
* fortunately we don't care.
* */
* */
static
int
detect
(
struct
SHT
*
sht
)
static int
usb_storage_
detect(struct SHT *sht)
{
{
struct us_data *us;
struct us_data *us;
char local_name[32];
char local_name[32];
...
@@ -109,7 +111,7 @@ static int detect(struct SHT *sht)
...
@@ -109,7 +111,7 @@ static int detect(struct SHT *sht)
* the driver and we're doing each virtual host in turn, not in parallel
* the driver and we're doing each virtual host in turn, not in parallel
* Synchronization: BKL, no spinlock.
* Synchronization: BKL, no spinlock.
*/
*/
static
int
release
(
struct
Scsi_Host
*
psh
)
static int
usb_storage_
release(struct Scsi_Host *psh)
{
{
struct us_data *us = (struct us_data *)psh->hostdata[0];
struct us_data *us = (struct us_data *)psh->hostdata[0];
...
@@ -132,18 +134,11 @@ static int release(struct Scsi_Host *psh)
...
@@ -132,18 +134,11 @@ static int release(struct Scsi_Host *psh)
/* we always have a successful release */
/* we always have a successful release */
return 0;
return 0;
}
}
#endif
/* run command */
static
int
command
(
Scsi_Cmnd
*
srb
)
{
US_DEBUGP
(
"Bad use of us_command
\n
"
);
return
DID_BAD_TARGET
<<
16
;
}
/* queue a command */
/* queue a command */
/* This is always called with scsi_lock(srb->host) held */
/* This is always called with scsi_lock(srb->host) held */
static
int
queuecommand
(
Scsi_Cmnd
*
srb
,
void
(
*
done
)(
Scsi_Cmnd
*
))
static
int
usb_storage_
queuecommand
(
Scsi_Cmnd
*
srb
,
void
(
*
done
)(
Scsi_Cmnd
*
))
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
...
@@ -168,7 +163,7 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
...
@@ -168,7 +163,7 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
/* Command abort */
/* Command abort */
/* This is always called with scsi_lock(srb->host) held */
/* This is always called with scsi_lock(srb->host) held */
static
int
command_abort
(
Scsi_Cmnd
*
srb
)
static
int
usb_storage_
command_abort
(
Scsi_Cmnd
*
srb
)
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
...
@@ -187,7 +182,7 @@ static int command_abort( Scsi_Cmnd *srb )
...
@@ -187,7 +182,7 @@ static int command_abort( Scsi_Cmnd *srb )
/* This invokes the transport reset mechanism to reset the state of the
/* This invokes the transport reset mechanism to reset the state of the
* device */
* device */
/* This is always called with scsi_lock(srb->host) held */
/* This is always called with scsi_lock(srb->host) held */
static
int
device_reset
(
Scsi_Cmnd
*
srb
)
static
int
usb_storage_
device_reset
(
Scsi_Cmnd
*
srb
)
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
int
result
;
int
result
;
...
@@ -202,11 +197,10 @@ static int device_reset( Scsi_Cmnd *srb )
...
@@ -202,11 +197,10 @@ static int device_reset( Scsi_Cmnd *srb )
/* lock the device pointers */
/* lock the device pointers */
down
(
&
(
us
->
dev_semaphore
));
down
(
&
(
us
->
dev_semaphore
));
/* if the device was removed, then we're already reset */
/* do the reset */
if
(
!
(
us
->
flags
&
US_FL_DEV_ATTACHED
))
result
=
SUCCESS
;
else
result
=
us
->
transport_reset
(
us
);
result
=
us
->
transport_reset
(
us
);
/* unlock */
up
(
&
(
us
->
dev_semaphore
));
up
(
&
(
us
->
dev_semaphore
));
/* lock access to the state and clear it */
/* lock access to the state and clear it */
...
@@ -219,31 +213,26 @@ static int device_reset( Scsi_Cmnd *srb )
...
@@ -219,31 +213,26 @@ static int device_reset( Scsi_Cmnd *srb )
* disconnect/reconnect for all drivers which have claimed
* disconnect/reconnect for all drivers which have claimed
* interfaces, including ourself. */
* interfaces, including ourself. */
/* This is always called with scsi_lock(srb->host) held */
/* This is always called with scsi_lock(srb->host) held */
static
int
bus_reset
(
Scsi_Cmnd
*
srb
)
/* FIXME: This needs to be re-examined in the face of the new
* hotplug system -- this will implicitly cause a detach/reattach of
* usb-storage, which is not what we want now.
*
* Can we just skip over usb-storage in the while loop?
*/
static
int
usb_storage_bus_reset
(
Scsi_Cmnd
*
srb
)
{
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
]
;
struct
us_data
*
us
;
int
i
;
int
i
;
int
result
;
int
result
;
struct
usb_device
*
pusb_dev_save
;
/* we use the usb_reset_device() function to handle this for us */
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP
(
"bus_reset() called
\n
"
);
US_DEBUGP
(
"bus_reset() called
\n
"
);
scsi_unlock
(
srb
->
device
->
host
);
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
/* if the device has been removed, this worked */
down
(
&
us
->
dev_semaphore
);
if
(
!
(
us
->
flags
&
US_FL_DEV_ATTACHED
))
{
US_DEBUGP
(
"-- device removed already
\n
"
);
up
(
&
us
->
dev_semaphore
);
scsi_lock
(
srb
->
device
->
host
);
return
SUCCESS
;
}
pusb_dev_save
=
us
->
pusb_dev
;
up
(
&
us
->
dev_semaphore
);
/* attempt to reset the port */
/* attempt to reset the port */
result
=
usb_reset_device
(
pusb_dev_save
);
result
=
usb_reset_device
(
us
->
pusb_dev
);
US_DEBUGP
(
"usb_reset_device returns %d
\n
"
,
result
);
US_DEBUGP
(
"usb_reset_device returns %d
\n
"
,
result
);
if
(
result
<
0
)
{
if
(
result
<
0
)
{
scsi_lock
(
srb
->
device
->
host
);
scsi_lock
(
srb
->
device
->
host
);
...
@@ -253,9 +242,9 @@ static int bus_reset( Scsi_Cmnd *srb )
...
@@ -253,9 +242,9 @@ static int bus_reset( Scsi_Cmnd *srb )
/* FIXME: This needs to lock out driver probing while it's working
/* FIXME: This needs to lock out driver probing while it's working
* or we can have race conditions */
* or we can have race conditions */
/* This functionality really should be provided by the khubd thread */
/* This functionality really should be provided by the khubd thread */
for
(
i
=
0
;
i
<
pusb_dev_save
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
for
(
i
=
0
;
i
<
us
->
pusb_dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
intf
=
struct
usb_interface
*
intf
=
&
pusb_dev_save
->
actconfig
->
interface
[
i
];
&
us
->
pusb_dev
->
actconfig
->
interface
[
i
];
/* if this is an unclaimed interface, skip it */
/* if this is an unclaimed interface, skip it */
if
(
!
intf
->
driver
)
{
if
(
!
intf
->
driver
)
{
...
@@ -274,14 +263,6 @@ static int bus_reset( Scsi_Cmnd *srb )
...
@@ -274,14 +263,6 @@ static int bus_reset( Scsi_Cmnd *srb )
return
SUCCESS
;
return
SUCCESS
;
}
}
/* FIXME: This doesn't do anything right now */
static
int
host_reset
(
Scsi_Cmnd
*
srb
)
{
printk
(
KERN_CRIT
"usb-storage: host_reset() requested but not implemented
\n
"
);
bus_reset
(
srb
);
return
FAILED
;
}
/***********************************************************************
/***********************************************************************
* /proc/scsi/ functions
* /proc/scsi/ functions
***********************************************************************/
***********************************************************************/
...
@@ -291,29 +272,23 @@ static int host_reset( Scsi_Cmnd *srb )
...
@@ -291,29 +272,23 @@ static int host_reset( Scsi_Cmnd *srb )
#define SPRINTF(args...) \
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
static
int
proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
static
int
usb_storage_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
hostno
,
int
inout
)
int
length
,
int
hostno
,
int
inout
)
{
{
struct
us_data
*
us
;
struct
us_data
*
us
;
char
*
pos
=
buffer
;
char
*
pos
=
buffer
;
struct
Scsi_Host
*
hostptr
;
/* if someone is sending us data, just throw it away */
/* if someone is sending us data, just throw it away */
if
(
inout
)
if
(
inout
)
return
length
;
return
length
;
/* lock the data structures */
/* find our data from the given hostno */
down
(
&
us_list_semaphore
);
hostptr
=
scsi_host_hn_get
(
hostno
);
if
(
!
hostptr
)
{
/* if we couldn't find it, we return an error */
/* find our data from hostno */
return
-
ESRCH
;
us
=
us_list
;
while
(
us
)
{
if
(
us
->
host_no
==
hostno
)
break
;
us
=
us
->
next
;
}
}
us
=
(
struct
us_data
*
)
hostptr
->
hostdata
[
0
];
/* release our lock on the data structures */
up
(
&
us_list_semaphore
);
/* if we couldn't find it, we return an error */
/* if we couldn't find it, we return an error */
if
(
!
us
)
{
if
(
!
us
)
{
...
@@ -332,10 +307,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
...
@@ -332,10 +307,8 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
SPRINTF
(
" Protocol: %s
\n
"
,
us
->
protocol_name
);
SPRINTF
(
" Protocol: %s
\n
"
,
us
->
protocol_name
);
SPRINTF
(
" Transport: %s
\n
"
,
us
->
transport_name
);
SPRINTF
(
" Transport: %s
\n
"
,
us
->
transport_name
);
/* show the GUID of the device */
/* release the reference count on this host */
SPRINTF
(
" GUID: "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
us
->
guid
));
scsi_host_put
(
hostptr
);
SPRINTF
(
" Attached: %s
\n
"
,
(
us
->
flags
&
US_FL_DEV_ATTACHED
?
"Yes"
:
"No"
));
/*
/*
* Calculate start of next buffer, and return value.
* Calculate start of next buffer, and return value.
...
@@ -351,33 +324,69 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
...
@@ -351,33 +324,69 @@ static int proc_info (char *buffer, char **start, off_t offset, int length,
}
}
/*
/*
* this defines our
'host'
* this defines our
host template, with which we'll allocate hosts
*/
*/
Scsi_Host_Template
usb_stor_host_template
=
{
struct
SHT
usb_stor_host_template
=
{
/* basic userland interface stuff */
.
name
=
"usb-storage"
,
.
name
=
"usb-storage"
,
.
proc_info
=
proc_info
,
.
proc_name
=
"usb-storage"
,
.
info
=
host_info
,
.
proc_info
=
usb_storage_proc_info
,
.
proc_dir
=
NULL
,
.
info
=
usb_storage_info
,
.
ioctl
=
NULL
,
/* old-style detect and release */
.
detect
=
NULL
,
.
release
=
NULL
,
/* command interface -- queued only */
.
command
=
NULL
,
.
queuecommand
=
usb_storage_queuecommand
,
/* error and abort handlers */
.
eh_abort_handler
=
usb_storage_command_abort
,
.
eh_device_reset_handler
=
usb_storage_device_reset
,
.
eh_bus_reset_handler
=
usb_storage_bus_reset
,
.
eh_host_reset_handler
=
NULL
,
.
eh_strategy_handler
=
NULL
,
/* queue commands only, only one command per LUN */
.
can_queue
=
1
,
.
cmd_per_lun
=
1
,
.
detect
=
detect
,
/* unknown initiator id */
.
release
=
release
,
.
this_id
=
-
1
,
.
command
=
command
,
.
queuecommand
=
queuecommand
,
.
eh_abort_handler
=
command_abort
,
/* no limit on commands */
.
eh_device_reset_handler
=
device_reset
,
.
max_sectors
=
0
,
.
eh_bus_reset_handler
=
bus_reset
,
.
eh_host_reset_handler
=
host_reset
,
.
can_queue
=
1
,
/* pre- and post- device scan functions */
.
this_id
=
-
1
,
.
slave_alloc
=
NULL
,
.
slave_configure
=
NULL
,
.
slave_destroy
=
NULL
,
/* lots of sg segments can be handled */
.
sg_tablesize
=
SG_ALL
,
.
sg_tablesize
=
SG_ALL
,
.
cmd_per_lun
=
1
,
.
present
=
0
,
/* use 32-bit address space for DMA */
.
unchecked_isa_dma
=
FALSE
,
.
unchecked_isa_dma
=
FALSE
,
.
highmem_io
=
FALSE
,
/* merge commands... this seems to help performance, but
* periodically someone should test to see which setting is more
* optimal.
*/
.
use_clustering
=
TRUE
,
.
use_clustering
=
TRUE
,
.
emulated
=
TRUE
/* emulated HBA */
.
emulated
=
TRUE
,
/* sorry, no BIOS to help us */
.
bios_param
=
NULL
,
/* module management */
.
module
=
THIS_MODULE
};
};
/* For a device that is "Not Ready" */
/* For a device that is "Not Ready" */
...
...
drivers/usb/storage/scsiglue.h
View file @
20b397bb
...
@@ -47,7 +47,7 @@
...
@@ -47,7 +47,7 @@
extern
unsigned
char
usb_stor_sense_notready
[
18
];
extern
unsigned
char
usb_stor_sense_notready
[
18
];
extern
unsigned
char
usb_stor_sense_invalidCDB
[
18
];
extern
unsigned
char
usb_stor_sense_invalidCDB
[
18
];
extern
Scsi_Host_Template
usb_stor_host_template
;
extern
struct
SHT
usb_stor_host_template
;
extern
int
usb_stor_scsiSense10to6
(
Scsi_Cmnd
*
);
extern
int
usb_stor_scsiSense10to6
(
Scsi_Cmnd
*
);
extern
int
usb_stor_scsiSense6to10
(
Scsi_Cmnd
*
);
extern
int
usb_stor_scsiSense6to10
(
Scsi_Cmnd
*
);
...
...
drivers/usb/storage/transport.h
View file @
20b397bb
...
@@ -55,8 +55,7 @@
...
@@ -55,8 +55,7 @@
#define US_PR_SCM_ATAPI 0x80
/* SCM-ATAPI bridge */
#define US_PR_SCM_ATAPI 0x80
/* SCM-ATAPI bridge */
#endif
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
#ifdef CONFIG_USB_STORAGE_SDDR09
#define US_PR_EUSB_SDDR09 0x81
/* SCM-SCSI bridge for
#define US_PR_EUSB_SDDR09 0x81
/* SCM-SCSI bridge for SDDR-09 */
SDDR-09 */
#endif
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
#ifdef CONFIG_USB_STORAGE_SDDR55
#define US_PR_SDDR55 0x82
/* SDDR-55 (made up) */
#define US_PR_SDDR55 0x82
/* SDDR-55 (made up) */
...
...
drivers/usb/storage/unusual_devs.h
View file @
20b397bb
drivers/usb/storage/usb.c
View file @
20b397bb
...
@@ -93,16 +93,6 @@ MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
...
@@ -93,16 +93,6 @@ MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
MODULE_DESCRIPTION
(
"USB Mass Storage driver for Linux"
);
MODULE_DESCRIPTION
(
"USB Mass Storage driver for Linux"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
/*
* Per device data
*/
static
int
my_host_number
;
/* The list of structures and the protective lock for them */
struct
us_data
*
us_list
;
struct
semaphore
us_list_semaphore
;
static
int
storage_probe
(
struct
usb_interface
*
iface
,
static
int
storage_probe
(
struct
usb_interface
*
iface
,
const
struct
usb_device_id
*
id
);
const
struct
usb_device_id
*
id
);
...
@@ -319,7 +309,7 @@ static int usb_stor_control_thread(void * __us)
...
@@ -319,7 +309,7 @@ static int usb_stor_control_thread(void * __us)
spin_unlock_irq
(
&
current
->
sig
->
siglock
);
spin_unlock_irq
(
&
current
->
sig
->
siglock
);
/* set our name for identification purposes */
/* set our name for identification purposes */
sprintf
(
current
->
comm
,
"usb-storage
-%d"
,
us
->
host_number
);
sprintf
(
current
->
comm
,
"usb-storage
"
);
unlock_kernel
();
unlock_kernel
();
...
@@ -395,35 +385,6 @@ static int usb_stor_control_thread(void * __us)
...
@@ -395,35 +385,6 @@ static int usb_stor_control_thread(void * __us)
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
}
}
/* our device has gone - pretend not ready */
else
if
(
!
(
us
->
flags
&
US_FL_DEV_ATTACHED
))
{
US_DEBUGP
(
"Request is for removed device
\n
"
);
/* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like
* we auto-sensed for it.
*/
if
(
us
->
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
)
{
memcpy
(
us
->
srb
->
request_buffer
,
usb_stor_sense_notready
,
sizeof
(
usb_stor_sense_notready
));
us
->
srb
->
result
=
GOOD
<<
1
;
}
else
if
(
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
{
/* INQUIRY should always work, per spec... */
unsigned
char
data_ptr
[
36
]
=
{
0x20
,
0x80
,
0x02
,
0x02
,
0x1F
,
0x00
,
0x00
,
0x00
};
US_DEBUGP
(
"Faking INQUIRY command for disconnected device
\n
"
);
fill_inquiry_response
(
us
,
data_ptr
,
36
);
us
->
srb
->
result
=
GOOD
<<
1
;
}
else
{
/* not ready */
memcpy
(
us
->
srb
->
sense_buffer
,
usb_stor_sense_notready
,
sizeof
(
usb_stor_sense_notready
));
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
}
}
/* !(us->flags & US_FL_DEV_ATTACHED) */
/* Handle those devices which need us to fake
/* Handle those devices which need us to fake
* their inquiry data */
* their inquiry data */
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
...
@@ -547,7 +508,6 @@ static void usb_stor_deallocate_urbs(struct us_data *ss)
...
@@ -547,7 +508,6 @@ static void usb_stor_deallocate_urbs(struct us_data *ss)
}
}
/* mark the device as gone */
/* mark the device as gone */
ss
->
flags
&=
~
US_FL_DEV_ATTACHED
;
usb_put_dev
(
ss
->
pusb_dev
);
usb_put_dev
(
ss
->
pusb_dev
);
ss
->
pusb_dev
=
NULL
;
ss
->
pusb_dev
=
NULL
;
}
}
...
@@ -563,12 +523,10 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -563,12 +523,10 @@ static int storage_probe(struct usb_interface *intf,
char
mf
[
USB_STOR_STRING_LEN
];
/* manufacturer */
char
mf
[
USB_STOR_STRING_LEN
];
/* manufacturer */
char
prod
[
USB_STOR_STRING_LEN
];
/* product */
char
prod
[
USB_STOR_STRING_LEN
];
/* product */
char
serial
[
USB_STOR_STRING_LEN
];
/* serial number */
char
serial
[
USB_STOR_STRING_LEN
];
/* serial number */
GUID
(
guid
);
/* Global Unique Identifier */
unsigned
int
flags
;
unsigned
int
flags
;
struct
us_unusual_dev
*
unusual_dev
;
struct
us_unusual_dev
*
unusual_dev
;
struct
us_data
*
ss
=
NULL
;
struct
us_data
*
ss
=
NULL
;
int
result
;
int
result
;
int
new_device
=
0
;
/* these are temporary copies -- we test on these, then put them
/* these are temporary copies -- we test on these, then put them
* in the us-data structure
* in the us-data structure
...
@@ -676,8 +634,7 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -676,8 +634,7 @@ static int storage_probe(struct usb_interface *intf,
/* At this point, we've decided to try to use the device */
/* At this point, we've decided to try to use the device */
usb_get_dev
(
dev
);
usb_get_dev
(
dev
);
/* clear the GUID and fetch the strings */
/* fetch the strings */
GUID_CLEAR
(
guid
);
if
(
dev
->
descriptor
.
iManufacturer
)
if
(
dev
->
descriptor
.
iManufacturer
)
usb_string
(
dev
,
dev
->
descriptor
.
iManufacturer
,
usb_string
(
dev
,
dev
->
descriptor
.
iManufacturer
,
mf
,
sizeof
(
mf
));
mf
,
sizeof
(
mf
));
...
@@ -688,69 +645,7 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -688,69 +645,7 @@ static int storage_probe(struct usb_interface *intf,
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
serial
,
sizeof
(
serial
));
serial
,
sizeof
(
serial
));
/* Create a GUID for this device */
if
(
dev
->
descriptor
.
iSerialNumber
&&
serial
[
0
])
{
/* If we have a serial number, and it's a non-NULL string */
make_guid
(
guid
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
serial
);
}
else
{
/* We don't have a serial number, so we use 0 */
make_guid
(
guid
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
"0"
);
}
/*
* Now check if we have seen this GUID before
* We're looking for a device with a matching GUID that isn't
* already on the system
*/
ss
=
us_list
;
while
((
ss
!=
NULL
)
&&
((
ss
->
flags
&
US_FL_DEV_ATTACHED
)
||
!
GUID_EQUAL
(
guid
,
ss
->
guid
)))
ss
=
ss
->
next
;
if
(
ss
!=
NULL
)
{
/* Existing device -- re-connect */
US_DEBUGP
(
"Found existing GUID "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
guid
));
/* lock the device pointers */
down
(
&
(
ss
->
dev_semaphore
));
/* establish the connection to the new device upon reconnect */
ss
->
ifnum
=
ifnum
;
ss
->
pusb_dev
=
dev
;
ss
->
flags
|=
US_FL_DEV_ATTACHED
;
/* copy over the endpoint data */
ss
->
ep_in
=
ep_in
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
ss
->
ep_out
=
ep_out
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
if
(
ep_int
)
{
ss
->
ep_int
=
ep_int
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
ss
->
ep_bInterval
=
ep_int
->
bInterval
;
}
else
ss
->
ep_int
=
ss
->
ep_bInterval
=
0
;
/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if
(
usb_stor_allocate_urbs
(
ss
))
goto
BadDevice
;
/* Re-Initialize the device if it needs it */
if
(
unusual_dev
&&
unusual_dev
->
initFunction
)
(
unusual_dev
->
initFunction
)(
ss
);
/* unlock the device pointers */
up
(
&
(
ss
->
dev_semaphore
));
}
else
{
/* New device -- allocate memory and initialize */
/* New device -- allocate memory and initialize */
US_DEBUGP
(
"New GUID "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
guid
));
if
((
ss
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
struct
us_data
),
if
((
ss
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
struct
us_data
),
GFP_KERNEL
))
==
NULL
)
{
GFP_KERNEL
))
==
NULL
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
...
@@ -758,7 +653,6 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -758,7 +653,6 @@ static int storage_probe(struct usb_interface *intf,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
new_device
=
1
;
/* Initialize the mutexes only when the struct is new */
/* Initialize the mutexes only when the struct is new */
init_completion
(
&
(
ss
->
notify
));
init_completion
(
&
(
ss
->
notify
));
...
@@ -767,7 +661,7 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -767,7 +661,7 @@ static int storage_probe(struct usb_interface *intf,
/* copy over the subclass and protocol data */
/* copy over the subclass and protocol data */
ss
->
subclass
=
subclass
;
ss
->
subclass
=
subclass
;
ss
->
protocol
=
protocol
;
ss
->
protocol
=
protocol
;
ss
->
flags
=
flags
|
US_FL_DEV_ATTACHED
;
ss
->
flags
=
flags
;
ss
->
unusual_dev
=
unusual_dev
;
ss
->
unusual_dev
=
unusual_dev
;
/* copy over the endpoint data */
/* copy over the endpoint data */
...
@@ -810,9 +704,6 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -810,9 +704,6 @@ static int storage_probe(struct usb_interface *intf,
if
(
strlen
(
ss
->
serial
)
==
0
)
if
(
strlen
(
ss
->
serial
)
==
0
)
strncpy
(
ss
->
serial
,
"None"
,
USB_STOR_STRING_LEN
);
strncpy
(
ss
->
serial
,
"None"
,
USB_STOR_STRING_LEN
);
/* copy the GUID we created before */
memcpy
(
ss
->
guid
,
guid
,
sizeof
(
guid
));
/*
/*
* Set the handler pointers based on the protocol
* Set the handler pointers based on the protocol
* Again, this data is persistant across reattachments
* Again, this data is persistant across reattachments
...
@@ -968,19 +859,6 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -968,19 +859,6 @@ static int storage_probe(struct usb_interface *intf,
* host definition, and register with the higher SCSI layers
* host definition, and register with the higher SCSI layers
*/
*/
/* Initialize the host template based on the default one */
memcpy
(
&
(
ss
->
htmplt
),
&
usb_stor_host_template
,
sizeof
(
usb_stor_host_template
));
/* Grab the next host number */
ss
->
host_number
=
my_host_number
++
;
/* We abuse this pointer so we can pass the ss pointer to
* the host controller thread in us_detect. But how else are
* we to do it?
*/
(
struct
us_data
*
)
ss
->
htmplt
.
proc_dir
=
ss
;
/* Just before we start our control thread, initialize
/* Just before we start our control thread, initialize
* the device if it needs initialization */
* the device if it needs initialization */
if
(
unusual_dev
&&
unusual_dev
->
initFunction
)
if
(
unusual_dev
&&
unusual_dev
->
initFunction
)
...
@@ -1002,10 +880,9 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -1002,10 +880,9 @@ static int storage_probe(struct usb_interface *intf,
/* unlock the device pointers */
/* unlock the device pointers */
up
(
&
(
ss
->
dev_semaphore
));
up
(
&
(
ss
->
dev_semaphore
));
/* now register - our detect function will be called */
/* now register */
ss
->
htmplt
.
module
=
THIS_MODULE
;
ss
->
host
=
scsi_register
(
&
usb_stor_host_template
,
sizeof
(
ss
));
result
=
scsi_register_host
(
&
(
ss
->
htmplt
));
if
(
!
ss
->
host
)
{
if
(
result
)
{
printk
(
KERN_WARNING
USB_STORAGE
printk
(
KERN_WARNING
USB_STORAGE
"Unable to register the scsi host
\n
"
);
"Unable to register the scsi host
\n
"
);
...
@@ -1019,15 +896,26 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -1019,15 +896,26 @@ static int storage_probe(struct usb_interface *intf,
goto
BadDevice
;
goto
BadDevice
;
}
}
/* lock access to the data structures
*/
/* set the hostdata to prepare for scanning
*/
down
(
&
us_list_semaphore
)
;
ss
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
ss
;
/* put us in the list */
/* associate this host with our interface */
ss
->
next
=
us_list
;
scsi_set_device
(
ss
->
host
,
&
intf
->
dev
);
us_list
=
ss
;
/* now add the host */
result
=
scsi_add_host
(
ss
->
host
,
NULL
);
if
(
result
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to add the scsi host
\n
"
);
/* tell the control thread to exit */
ss
->
srb
=
NULL
;
up
(
&
ss
->
sema
);
wait_for_completion
(
&
ss
->
notify
);
/* release the data structure lock */
/* re-lock the device pointers */
up
(
&
us_list_semaphore
);
down
(
&
ss
->
dev_semaphore
);
goto
BadDevice
;
}
}
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
...
@@ -1041,11 +929,10 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -1041,11 +929,10 @@ static int storage_probe(struct usb_interface *intf,
/* we come here if there are any problems */
/* we come here if there are any problems */
/* ss->dev_semaphore must be locked */
/* ss->dev_semaphore must be locked */
BadDevice:
BadDevice:
US_DEBUGP
(
"storage_probe() failed
\n
"
);
US_DEBUGP
(
"storage_probe() failed
\n
"
);
usb_stor_deallocate_urbs
(
ss
);
usb_stor_deallocate_urbs
(
ss
);
up
(
&
ss
->
dev_semaphore
);
up
(
&
ss
->
dev_semaphore
);
if
(
new_device
)
kfree
(
ss
);
kfree
(
ss
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -1053,21 +940,85 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -1053,21 +940,85 @@ static int storage_probe(struct usb_interface *intf,
/* Handle a disconnect event from the USB core */
/* Handle a disconnect event from the USB core */
static
void
storage_disconnect
(
struct
usb_interface
*
intf
)
static
void
storage_disconnect
(
struct
usb_interface
*
intf
)
{
{
struct
us_data
*
ss
=
usb_get_intfdata
(
intf
);
struct
us_data
*
ss
;
struct
scsi_device
*
sdev
;
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
ss
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
usb_set_intfdata
(
intf
,
NULL
);
/* this is the odd case -- we disconnected but weren't using it */
/* serious error -- we're attempting to disconnect an interface but
if
(
!
ss
)
{
* cannot locate the local data structure
US_DEBUGP
(
"-- device was not in use
\n
"
);
*/
return
;
BUG_ON
(
ss
==
NULL
);
}
/* set devices offline -- need host lock for this */
scsi_lock
(
ss
->
host
);
list_for_each_entry
(
sdev
,
&
ss
->
host
->
my_devices
,
siblings
)
sdev
->
online
=
0
;
scsi_unlock
(
ss
->
host
);
/* lock device access -- no need to unlock, as we're going away */
down
(
&
(
ss
->
dev_semaphore
));
down
(
&
(
ss
->
dev_semaphore
));
/* Complete all pending commands with * cmd->result = DID_ERROR << 16.
* Since we only queue one command at a time, this is pretty easy. */
if
(
ss
->
srb
)
{
ss
->
srb
->
result
=
DID_ERROR
<<
16
;
ss
->
srb
->
scsi_done
(
ss
->
srb
);
}
/* TODO: somehow, wait for the device to
* be 'idle' (tasklet completion) */
/* remove the pointer to the data structure we were using */
(
struct
us_data
*
)
ss
->
host
->
hostdata
[
0
]
=
NULL
;
/* begin SCSI host removal sequence */
if
(
scsi_remove_host
(
ss
->
host
))
{
US_DEBUGP
(
"-- SCSI refused to unregister
\n
"
);
BUG
();
return
;
};
/* finish SCSI host removal sequence */
scsi_unregister
(
ss
->
host
);
/* Kill the control threads
*
* Enqueue the command, wake up the thread, and wait for
* notification that it has exited.
*/
US_DEBUGP
(
"-- sending exit command to thread
\n
"
);
BUG_ON
(
atomic_read
(
&
ss
->
sm_state
)
!=
US_STATE_IDLE
);
ss
->
srb
=
NULL
;
up
(
&
(
ss
->
sema
));
wait_for_completion
(
&
(
ss
->
notify
));
/* free allocated urbs */
usb_stor_deallocate_urbs
(
ss
);
usb_stor_deallocate_urbs
(
ss
);
/* If there's extra data in the us_data structure then
* free that first */
if
(
ss
->
extra
)
{
/* call the destructor routine, if it exists */
if
(
ss
->
extra_destructor
)
{
US_DEBUGP
(
"-- calling extra_destructor()
\n
"
);
ss
->
extra_destructor
(
ss
->
extra
);
}
/* destroy the extra data */
US_DEBUGP
(
"-- freeing the data structure
\n
"
);
kfree
(
ss
->
extra
);
}
/* up the semaphore so auto-code-checkers won't complain about
* the down/up imbalance */
up
(
&
(
ss
->
dev_semaphore
));
up
(
&
(
ss
->
dev_semaphore
));
/* free the structure itself */
kfree
(
ss
);
}
}
/***********************************************************************
/***********************************************************************
...
@@ -1078,11 +1029,6 @@ int __init usb_stor_init(void)
...
@@ -1078,11 +1029,6 @@ int __init usb_stor_init(void)
{
{
printk
(
KERN_INFO
"Initializing USB Mass Storage driver...
\n
"
);
printk
(
KERN_INFO
"Initializing USB Mass Storage driver...
\n
"
);
/* initialize internal global data elements */
us_list
=
NULL
;
init_MUTEX
(
&
us_list_semaphore
);
my_host_number
=
0
;
/* register the driver, return -1 if error */
/* register the driver, return -1 if error */
if
(
usb_register
(
&
usb_storage_driver
)
<
0
)
if
(
usb_register
(
&
usb_storage_driver
)
<
0
)
return
-
1
;
return
-
1
;
...
@@ -1094,16 +1040,16 @@ int __init usb_stor_init(void)
...
@@ -1094,16 +1040,16 @@ int __init usb_stor_init(void)
void
__exit
usb_stor_exit
(
void
)
void
__exit
usb_stor_exit
(
void
)
{
{
struct
us_data
*
next
;
US_DEBUGP
(
"usb_stor_exit() called
\n
"
);
US_DEBUGP
(
"usb_stor_exit() called
\n
"
);
/* Deregister the driver
/* Deregister the driver
* This eliminates races with probes and disconnects
* This will cause disconnect() to be called for each
* attached unit
*/
*/
US_DEBUGP
(
"-- calling usb_deregister()
\n
"
);
US_DEBUGP
(
"-- calling usb_deregister()
\n
"
);
usb_deregister
(
&
usb_storage_driver
)
;
usb_deregister
(
&
usb_storage_driver
)
;
#if 0
/* While there are still virtual hosts, unregister them
/* While there are still virtual hosts, unregister them
* Note that it's important to do this completely before removing
* Note that it's important to do this completely before removing
* the structures because of possible races with the /proc
* the structures because of possible races with the /proc
...
@@ -1111,7 +1057,7 @@ void __exit usb_stor_exit(void)
...
@@ -1111,7 +1057,7 @@ void __exit usb_stor_exit(void)
*/
*/
for (next = us_list; next; next = next->next) {
for (next = us_list; next; next = next->next) {
US_DEBUGP("-- calling scsi_unregister_host()\n");
US_DEBUGP("-- calling scsi_unregister_host()\n");
scsi_unregister_host
(
&
(
next
->
htmplt
)
);
scsi_unregister_host(&
usb_stor_host_template
);
}
}
/* While there are still structures, free them. Note that we are
/* While there are still structures, free them. Note that we are
...
@@ -1142,6 +1088,7 @@ void __exit usb_stor_exit(void)
...
@@ -1142,6 +1088,7 @@ void __exit usb_stor_exit(void)
/* advance the list pointer */
/* advance the list pointer */
us_list = next;
us_list = next;
}
}
#endif
}
}
module_init
(
usb_stor_init
);
module_init
(
usb_stor_init
);
...
...
drivers/usb/storage/usb.h
View file @
20b397bb
...
@@ -52,33 +52,6 @@
...
@@ -52,33 +52,6 @@
#include "scsi.h"
#include "scsi.h"
#include "hosts.h"
#include "hosts.h"
/*
* GUID definitions
*/
#define GUID(x) __u32 x[3]
#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2])
#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0;
#define GUID_NONE(x) (!x[0] && !x[1] && !x[2])
#define GUID_FORMAT "%08x%08x%08x"
#define GUID_ARGS(x) x[0], x[1], x[2]
static
inline
void
make_guid
(
__u32
*
pg
,
__u16
vendor
,
__u16
product
,
char
*
serial
)
{
pg
[
0
]
=
(
vendor
<<
16
)
|
product
;
pg
[
1
]
=
pg
[
2
]
=
0
;
while
(
*
serial
)
{
pg
[
1
]
<<=
4
;
pg
[
1
]
|=
pg
[
2
]
>>
28
;
pg
[
2
]
<<=
4
;
if
(
*
serial
>=
'a'
)
*
serial
-=
'a'
-
'A'
;
pg
[
2
]
|=
(
*
serial
<=
'9'
&&
*
serial
>=
'0'
)
?
*
serial
-
'0'
:
*
serial
-
'A'
+
10
;
serial
++
;
}
}
struct
us_data
;
struct
us_data
;
/*
/*
...
@@ -104,7 +77,6 @@ struct us_unusual_dev {
...
@@ -104,7 +77,6 @@ struct us_unusual_dev {
#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 */
#define US_FL_DEV_ATTACHED 0x00010000
/* is the device attached? */
#define US_FLIDX_CAN_CANCEL 18
/* 0x00040000 okay to cancel current_urb? */
#define US_FLIDX_CAN_CANCEL 18
/* 0x00040000 okay to cancel current_urb? */
#define US_FLIDX_CANCEL_SG 19
/* 0x00080000 okay to cancel current_sg? */
#define US_FLIDX_CANCEL_SG 19
/* 0x00080000 okay to cancel current_sg? */
...
@@ -124,12 +96,9 @@ typedef void (*extra_data_destructor)(void *); /* extra data destructor */
...
@@ -124,12 +96,9 @@ typedef void (*extra_data_destructor)(void *); /* extra data destructor */
/* we allocate one of these for every device that we remember */
/* we allocate one of these for every device that we remember */
struct
us_data
{
struct
us_data
{
struct
us_data
*
next
;
/* next device */
/* The device we're working with
/* The device we're working with
* It's important to note:
* It's important to note:
* (o) you must hold dev_semaphore to change pusb_dev
* (o) you must hold dev_semaphore to change pusb_dev
* (o) DEV_ATTACHED in flags should change whenever pusb_dev does
*/
*/
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 */
...
@@ -163,11 +132,7 @@ struct us_data {
...
@@ -163,11 +132,7 @@ struct us_data {
proto_cmnd
proto_handler
;
/* protocol handler */
proto_cmnd
proto_handler
;
/* protocol handler */
/* SCSI interfaces */
/* SCSI interfaces */
GUID
(
guid
);
/* unique dev id */
struct
Scsi_Host
*
host
;
/* our dummy host data */
struct
Scsi_Host
*
host
;
/* our dummy host data */
Scsi_Host_Template
htmplt
;
/* own host template */
int
host_number
;
/* to find us */
int
host_no
;
/* allocated by scsi */
Scsi_Cmnd
*
srb
;
/* current srb */
Scsi_Cmnd
*
srb
;
/* current srb */
/* thread information */
/* thread information */
...
@@ -192,10 +157,6 @@ struct us_data {
...
@@ -192,10 +157,6 @@ struct us_data {
extra_data_destructor
extra_destructor
;
/* extra data destructor */
extra_data_destructor
extra_destructor
;
/* extra data destructor */
};
};
/* The list of structures and the protective lock for them */
extern
struct
us_data
*
us_list
;
extern
struct
semaphore
us_list_semaphore
;
/* The structure which defines our driver */
/* The structure which defines our driver */
extern
struct
usb_driver
usb_storage_driver
;
extern
struct
usb_driver
usb_storage_driver
;
...
...
include/linux/usb.h
View file @
20b397bb
...
@@ -554,7 +554,6 @@ extern int usb_disabled(void);
...
@@ -554,7 +554,6 @@ extern int usb_disabled(void);
#define URB_NO_FSBR 0x0020
/* UHCI-specific */
#define URB_NO_FSBR 0x0020
/* UHCI-specific */
#define URB_ZERO_PACKET 0x0040
/* Finish bulk OUTs with short packet */
#define URB_ZERO_PACKET 0x0040
/* Finish bulk OUTs with short packet */
#define URB_NO_INTERRUPT 0x0080
/* HINT: no non-error interrupt needed */
#define URB_NO_INTERRUPT 0x0080
/* HINT: no non-error interrupt needed */
#define URB_TIMEOUT_KILLED 0x1000
/* only set by HCD! */
struct
usb_iso_packet_descriptor
{
struct
usb_iso_packet_descriptor
{
unsigned
int
offset
;
unsigned
int
offset
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment