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
Hide 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
kernel: saying N will just cause the configurator to skip all
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
bool "ARM EBSA110 AM79C961A support"
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
# end link order section
#
obj-$(CONFIG_MII)
+=
mii.o
obj-$(CONFIG_AIRONET4500)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500_CS)
+=
aironet4500_core.o
obj-$(CONFIG_AIRONET4500_NONCS)
+=
aironet4500_card.o
...
...
@@ -193,3 +194,6 @@ obj-$(CONFIG_NET_WIRELESS) += wireless/
obj-$(CONFIG_NET_TULIP)
+=
tulip/
obj-$(CONFIG_HAMRADIO)
+=
hamradio/
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)
if
(
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
++
)
{
/* if we insert more than TTY_FLIPBUF_SIZE characters,
* we drop them. */
...
...
@@ -697,6 +697,7 @@ static void acm_disconnect(struct usb_interface *intf)
static
struct
usb_device_id
acm_ids
[]
=
{
{
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 @@
static
char
*
format_topo
=
/* 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
=
/* S: Manufacturer=xxxx */
...
...
drivers/usb/core/hcd.c
View file @
20b397bb
...
...
@@ -310,9 +310,9 @@ static int rh_string (
}
else
return
0
;
data
[
0
]
=
2
+
ascii2utf
(
buf
,
data
+
2
,
len
-
2
);
data
[
0
]
=
2
*
(
strlen
(
buf
)
+
1
);
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)
return
status
;
}
/* lower level hcd code should use *_dma exclusively */
if
(
!
(
urb
->
transfer_flags
&
URB_NO_DMA_MAP
))
{
/* lower level hcd code should use *_dma exclusively,
* 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
))
urb
->
setup_dma
=
dma_map_single
(
hcd
->
controller
,
...
...
drivers/usb/core/hcd.h
View file @
20b397bb
...
...
@@ -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
list_head
dev_list
;
/* on this hcd */
struct
list_head
urb_list
;
/* pending on this dev */
...
...
@@ -343,6 +350,13 @@ extern void usb_deregister_bus (struct usb_bus *);
extern
int
usb_register_root_hub
(
struct
usb_device
*
usb_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 */
...
...
drivers/usb/core/message.c
View file @
20b397bb
...
...
@@ -206,7 +206,8 @@ static void sg_clean (struct usb_sg_request *io)
kfree
(
io
->
urbs
);
io
->
urbs
=
0
;
}
usb_buffer_unmap_sg
(
io
->
dev
,
io
->
pipe
,
io
->
sg
,
io
->
nents
);
if
(
io
->
dev
->
dev
.
dma_mask
!=
0
)
usb_buffer_unmap_sg
(
io
->
dev
,
io
->
pipe
,
io
->
sg
,
io
->
nents
);
io
->
dev
=
0
;
}
...
...
@@ -301,6 +302,7 @@ int usb_sg_init (
{
int
i
;
int
urb_flags
;
int
dma
;
if
(
!
io
||
!
dev
||
!
sg
||
usb_pipecontrol
(
pipe
)
...
...
@@ -314,8 +316,16 @@ int usb_sg_init (
io
->
sg
=
sg
;
io
->
nents
=
nents
;
/* 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
);
else
io
->
entries
=
nents
;
/* initialize all the urbs we'll use */
io
->
entries
=
usb_buffer_map_sg
(
dev
,
pipe
,
sg
,
nents
);
if
(
io
->
entries
<=
0
)
return
io
->
entries
;
...
...
@@ -347,8 +357,17 @@ int usb_sg_init (
io
->
urbs
[
i
]
->
status
=
-
EINPROGRESS
;
io
->
urbs
[
i
]
->
actual_length
=
0
;
io
->
urbs
[
i
]
->
transfer_dma
=
sg_dma_address
(
sg
+
i
);
len
=
sg_dma_len
(
sg
+
i
);
if
(
dma
)
{
/* hc may use _only_ transfer_dma */
io
->
urbs
[
i
]
->
transfer_dma
=
sg_dma_address
(
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
)
{
len
=
min_t
(
unsigned
,
len
,
length
);
length
-=
len
;
...
...
@@ -434,9 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io)
retval
=
0
;
i
--
;
// FIXME: should it usb_sg_cancel() on INTERRUPT?
// how about imposing a backoff?
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
yield
();
break
;
/* no error? continue immediately.
...
...
drivers/usb/core/usb.c
View file @
20b397bb
...
...
@@ -1224,7 +1224,8 @@ void usb_buffer_free (
*
* 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
* 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
* as the target of a large periodic transfer, with usb_buffer_dmasync()
...
...
@@ -1245,12 +1246,15 @@ struct urb *usb_buffer_map (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
return
0
;
urb
->
transfer_dma
=
dma_map_single
(
controller
,
if
(
controller
->
dma_mask
)
{
urb
->
transfer_dma
=
dma_map_single
(
controller
,
urb
->
transfer_buffer
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
// FIXME generic api broken like pci, can't report errors
// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
}
else
urb
->
transfer_dma
=
~
0
;
urb
->
transfer_flags
|=
URB_NO_DMA_MAP
;
return
urb
;
}
...
...
@@ -1271,7 +1275,8 @@ void usb_buffer_dmasync (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
return
;
dma_sync_single
(
controller
,
if
(
controller
->
dma_mask
)
dma_sync_single
(
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
?
DMA_FROM_DEVICE
:
DMA_TO_DEVICE
);
...
...
@@ -1295,10 +1300,12 @@ void usb_buffer_unmap (struct urb *urb)
||
!
(
controller
=
bus
->
controller
))
return
;
dma_unmap_single
(
controller
,
if
(
controller
->
dma_mask
)
dma_unmap_single
(
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
?
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,
if
(
!
dev
||
usb_pipecontrol
(
pipe
)
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
-
1
;
// 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,
if
(
!
dev
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
;
dma_sync_sg
(
controller
,
sg
,
n_hw_ents
,
...
...
@@ -1386,7 +1395,8 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
if
(
!
dev
||
!
(
bus
=
dev
->
bus
)
||
!
(
controller
=
bus
->
controller
))
||
!
(
controller
=
bus
->
controller
)
||
!
controller
->
dma_mask
)
return
;
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) { }
default: tmp = '?'; break; \
}; 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
hw_curr
;
...
...
@@ -286,26 +305,49 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
unsigned
temp
;
unsigned
size
=
*
sizep
;
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
);
hw_curr
=
cpu_to_le32p
(
&
qh
->
hw_current
)
;
hw_curr
=
(
mark
==
'*'
)
?
cpu_to_le32p
(
&
qh
->
hw_current
)
:
0
;
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
,
speed_char
(
scratch
),
(
scratch
>>
8
)
&
0x000f
,
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
;
next
+=
temp
;
/* hc may be modifying the list as we read it ... */
list_for_each
(
entry
,
&
qh
->
qtd_list
)
{
td
=
list_entry
(
entry
,
struct
ehci_qtd
,
qtd_list
);
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
,
"
\n\t
%std/%p %s len=%d %08x urb %p"
,
(
hw_curr
==
td
->
qtd_dma
)
?
"*"
:
""
,
td
,
({
char
*
tmp
;
"
\n\t
%p%c%s len=%d %08x urb %p"
,
td
,
mark
,
({
char
*
tmp
;
switch
((
scratch
>>
8
)
&
0x03
)
{
case
0
:
tmp
=
"out"
;
break
;
case
1
:
tmp
=
"in"
;
break
;
...
...
@@ -315,13 +357,27 @@ static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
(
scratch
>>
16
)
&
0x7fff
,
scratch
,
td
->
urb
);
if
(
temp
<
0
)
temp
=
0
;
else
if
(
size
<
temp
)
temp
=
size
;
size
-=
temp
;
next
+=
temp
;
if
(
temp
==
size
)
goto
done
;
}
temp
=
snprintf
(
next
,
size
,
"
\n
"
);
*
sizep
=
size
-
temp
;
*
nextp
=
next
+
temp
;
if
(
temp
<
0
)
temp
=
0
;
else
if
(
size
<
temp
)
temp
=
size
;
size
-=
temp
;
next
+=
temp
;
done:
*
sizep
=
size
;
*
nextp
=
next
;
}
static
ssize_t
...
...
@@ -344,14 +400,15 @@ show_async (struct device *dev, char *buf)
* one QH per line, and TDs we know about
*/
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
for
(
qh
=
ehci
->
async
->
qh_next
.
qh
;
qh
;
qh
=
qh
->
qh_next
.
qh
)
qh_lines
(
qh
,
&
next
,
&
size
);
if
(
ehci
->
reclaim
)
{
for
(
qh
=
ehci
->
async
->
qh_next
.
qh
;
size
>
0
&&
qh
;
qh
=
qh
->
qh_next
.
qh
)
qh_lines
(
ehci
,
qh
,
&
next
,
&
size
);
if
(
ehci
->
reclaim
&&
size
>
0
)
{
temp
=
snprintf
(
next
,
size
,
"
\n
reclaim =
\n
"
);
size
-=
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
);
...
...
@@ -421,7 +478,7 @@ show_periodic (struct device *dev, char *buf)
scratch
&
0x007f
,
(
scratch
>>
8
)
&
0x000f
,
p
.
qh
->
usecs
,
p
.
qh
->
c_usecs
,
scratch
>>
16
);
0x7ff
&
(
scratch
>>
16
)
);
/* FIXME TD info too */
...
...
@@ -490,7 +547,8 @@ show_registers (struct device *dev, char *buf)
/* Capability Registers */
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
);
size
-=
temp
;
next
+=
temp
;
...
...
drivers/usb/host/ehci-hcd.c
View file @
20b397bb
...
...
@@ -94,7 +94,7 @@
* 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_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
...
...
@@ -110,10 +110,11 @@ static const char hcd_name [] = "ehci-hcd";
/* magic numbers that can affect system performance */
#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_MULT_HS 1
/* 1-3 transactions/uframe; 4.10.3 */
#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_ASYNC_JIFFIES (HZ/20)
/* async idle timeout */
...
...
@@ -416,13 +417,26 @@ static int ehci_start (struct usb_hcd *hcd)
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 */
temp
=
readl
(
&
ehci
->
regs
->
command
)
&
0xff
;
if
(
log2_irq_thresh
<
0
||
log2_irq_thresh
>
6
)
log2_irq_thresh
=
0
;
temp
|=
1
<<
(
16
+
log2_irq_thresh
);
// 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
),
// Philips, Intel, and maybe others need CMD_RUN before the
// 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)
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
struct
ehci_qh
*
qh
;
unsigned
long
flags
;
int
maybe_irq
=
1
;
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
switch
(
usb_pipetype
(
urb
->
pipe
))
{
...
...
@@ -769,23 +782,23 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
qh
=
(
struct
ehci_qh
*
)
urb
->
hcpriv
;
if
(
!
qh
)
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
&&
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
)
{
s
pin_unlock_irqrestore
(
&
ehci
->
lock
,
flags
)
;
s
truct
ehci_qh
*
last
;
if
(
maybe_irq
)
{
if
(
in_interrupt
())
return
-
EAGAIN
;
maybe_irq
=
0
;
}
/* let pending unlinks complete, so this can start */
wait_ms
(
1
);
for
(
last
=
ehci
->
reclaim
;
last
->
reclaim
;
last
=
last
->
reclaim
)
continue
;
qh
->
qh_state
=
QH_STATE_UNLINK_WAIT
;
last
->
reclaim
=
qh
;
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
}
if
(
!
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
&&
ehci
->
reclaim
)
/* bypass IAA if the hc can't care */
}
else
if
(
!
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
)
&&
ehci
->
reclaim
)
end_unlink_async
(
ehci
,
NULL
);
/* 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)
qtd
=
pci_pool_alloc
(
ehci
->
qtd_pool
,
flags
,
&
dma
);
if
(
qtd
!=
0
)
{
ehci_qtd_init
(
qtd
,
dma
);
if
(
ehci
->
async
)
qtd
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
}
return
qtd
;
}
...
...
drivers/usb/host/ehci-q.c
View file @
20b397bb
...
...
@@ -43,7 +43,8 @@
/* fill a qtd, returning how much of the buffer we were able to queue up */
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
;
u64
addr
=
buf
;
...
...
@@ -69,6 +70,10 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
else
count
=
len
;
}
/* short packets may only terminate transfers */
if
(
count
!=
len
)
count
-=
(
count
%
maxpacket
);
}
qtd
->
hw_token
=
cpu_to_le32
((
count
<<
16
)
|
token
);
qtd
->
length
=
count
;
...
...
@@ -85,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
{
qh
->
hw_current
=
0
;
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 */
wmb
();
...
...
@@ -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)
static
inline
void
qtd_copy_status
(
static
void
qtd_copy_status
(
struct
ehci_hcd
*
ehci
,
struct
urb
*
urb
,
size_t
length
,
...
...
@@ -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
list_head
*
entry
,
*
tmp
;
int
stopped
=
0
;
int
stopped
;
unsigned
count
=
0
;
int
do_status
=
0
;
u8
state
;
if
(
unlikely
(
list_empty
(
&
qh
->
qtd_list
)))
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.
* after faults (including short reads), cleanup this urb
* then let the queue advance.
...
...
@@ -261,7 +278,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
rmb
();
token
=
le32_to_cpu
(
qtd
->
hw_token
);
stopped
=
stopped
||
(
qh
->
qh_state
==
QH_STATE_IDLE
)
||
(
HALT_BIT
&
qh
->
hw_token
)
!=
0
||
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
);
...
...
@@ -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 */
if
(
IS_SHORT_READ
(
token
)
&&
!
(
token
&
QTD_STS_HALT
)
&&
ehci
->
async
->
hw_alt_next
==
qh
->
hw_alt_next
)
&&
(
qh
->
hw_alt_next
&
QTD_MASK
)
==
ehci
->
async
->
hw_alt_next
)
{
stopped
=
1
;
goto
halt
;
}
/* stop scanning when we reach qtds the hc is using */
}
else
if
(
likely
(
!
stopped
))
{
last
=
0
;
break
;
}
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
* its urb was canceled. we may patch qh or qtds.
*/
if
((
token
&
QTD_STS_ACTIVE
)
&&
urb
->
status
==
-
EINPROGRESS
)
{
last
=
0
;
if
(
likely
(
urb
->
status
==
-
EINPROGRESS
))
continue
;
/* issue status after short control reads */
if
(
unlikely
(
do_status
!=
0
)
&&
QTD_PID
(
token
)
==
0
/* OUT */
)
{
do_status
=
0
;
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
)
{
halt:
qh
->
hw_token
|=
HALT_BIT
;
wmb
();
stopped
=
1
;
}
}
/* remove it from the queue */
spin_lock
(
&
urb
->
lock
);
qtd_copy_status
(
ehci
,
urb
,
qtd
->
length
,
token
);
do_status
=
(
urb
->
status
==
-
EREMOTEIO
)
&&
usb_pipecontrol
(
urb
->
pipe
);
spin_unlock
(
&
urb
->
lock
);
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)
ehci_qtd_free
(
ehci
,
last
);
}
/* restore original state; caller must unlink or relink */
qh
->
qh_state
=
state
;
/* update qh after fault cleanup */
if
(
unlikely
((
HALT_BIT
&
qh
->
hw_token
)
!=
0
))
{
qh_update
(
ehci
,
qh
,
...
...
@@ -367,7 +403,7 @@ qh_urb_transaction (
struct
ehci_qtd
*
qtd
,
*
qtd_prev
;
dma_addr_t
buf
;
int
len
,
maxpacket
;
int
is_input
,
status_patch
=
0
;
int
is_input
;
u32
token
;
/*
...
...
@@ -388,7 +424,7 @@ qh_urb_transaction (
if
(
usb_pipecontrol
(
urb
->
pipe
))
{
/* SETUP pid */
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 */
token
^=
QTD_TOGGLE
;
...
...
@@ -399,10 +435,6 @@ qh_urb_transaction (
qtd
->
urb
=
urb
;
qtd_prev
->
hw_next
=
QTD_NEXT
(
qtd
->
qtd_dma
);
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 (
else
buf
=
0
;
// FIXME this 'buf' check break some zlps...
if
(
!
buf
||
is_input
)
token
|=
(
1
/* "in" */
<<
8
);
/* else it's already initted to "out" pid (0 << 8) */
...
...
@@ -427,9 +460,11 @@ qh_urb_transaction (
for
(;;)
{
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
;
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 */
if
((
maxpacket
&
(
this_qtd_len
+
(
maxpacket
-
1
)))
==
0
)
...
...
@@ -447,6 +482,13 @@ qh_urb_transaction (
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;
* bulk ones may need a terminating short packet (zero length).
...
...
@@ -473,23 +515,10 @@ qh_urb_transaction (
list_add_tail
(
&
qtd
->
qtd_list
,
head
);
/* 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 */
if
(
likely
(
!
(
urb
->
transfer_flags
&
URB_NO_INTERRUPT
)))
qtd
->
hw_token
|=
__constant_cpu_to_le32
(
QTD_IOC
);
...
...
@@ -611,7 +640,8 @@ qh_make (
case
USB_SPEED_FULL
:
/* EPS 0 means "full" */
info1
|=
(
EHCI_TUNE_RL_TT
<<
28
);
if
(
type
!=
PIPE_INTERRUPT
)
info1
|=
(
EHCI_TUNE_RL_TT
<<
28
);
if
(
type
==
PIPE_CONTROL
)
{
info1
|=
(
1
<<
27
);
/* for TT */
info1
|=
1
<<
14
;
/* toggle from qtd */
...
...
@@ -628,12 +658,13 @@ qh_make (
case
USB_SPEED_HIGH
:
/* no TT involved */
info1
|=
(
2
<<
12
);
/* EPS "high" */
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
if
(
type
==
PIPE_CONTROL
)
{
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
info1
|=
64
<<
16
;
/* usb2 fixed maxpacket */
info1
|=
1
<<
14
;
/* toggle from qtd */
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
}
else
if
(
type
==
PIPE_BULK
)
{
info1
|=
(
EHCI_TUNE_RL_HS
<<
28
);
info1
|=
512
<<
16
;
/* usb2 fixed maxpacket */
info2
|=
(
EHCI_TUNE_MULT_HS
<<
30
);
}
else
{
/* PIPE_INTERRUPT */
...
...
@@ -769,8 +800,7 @@ static struct ehci_qh *qh_append_tds (
&&
!
usb_pipecontrol
(
urb
->
pipe
))
{
/* "never happens": drivers do stall cleanup right */
if
(
qh
->
qh_state
!=
QH_STATE_IDLE
&&
(
cpu_to_le32
(
QTD_STS_HALT
)
&
qh
->
hw_token
)
==
0
)
&&
qh
->
qh_state
!=
QH_STATE_COMPLETING
)
ehci_warn
(
ehci
,
"clear toggle dev%d "
"ep%d%s: not idle
\n
"
,
usb_pipedevice
(
urb
->
pipe
),
...
...
@@ -809,7 +839,6 @@ static struct ehci_qh *qh_append_tds (
__list_splice
(
qtd_list
,
qh
->
qtd_list
.
prev
);
ehci_qtd_init
(
qtd
,
qtd
->
qtd_dma
);
qtd
->
hw_alt_next
=
ehci
->
async
->
hw_alt_next
;
qh
->
dummy
=
qtd
;
/* hc must see the new dummy at list end */
...
...
@@ -877,9 +906,12 @@ submit_async (
/* 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
)
{
struct
ehci_qh
*
qh
=
ehci
->
reclaim
;
struct
ehci_qh
*
next
;
del_timer
(
&
ehci
->
watchdog
);
...
...
@@ -890,6 +922,10 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
ehci
->
reclaim
=
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
);
if
(
!
list_empty
(
&
qh
->
qtd_list
)
...
...
@@ -909,6 +945,9 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
jiffies
+
EHCI_ASYNC_JIFFIES
);
}
}
if
(
next
)
start_unlink_async
(
ehci
,
next
);
}
/* 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)
#ifdef DEBUG
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
// this macro lies except on SMP compiles
||
!
spin_is_locked
(
&
ehci
->
lock
)
...
...
@@ -953,6 +993,9 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
wmb
();
if
(
unlikely
(
ehci
->
hcd
.
state
==
USB_STATE_HALT
))
{
/* if (unlikely (qh->reclaim != 0))
* this will recurse, probably not much
*/
end_unlink_async
(
ehci
,
NULL
);
return
;
}
...
...
drivers/usb/host/ehci.h
View file @
20b397bb
...
...
@@ -236,12 +236,12 @@ struct ehci_qtd {
/* the rest is HCD-private */
dma_addr_t
qtd_dma
;
/* qtd address */
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 */
size_t
length
;
/* length of buffer */
}
__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 */
...
...
@@ -305,6 +305,7 @@ struct ehci_qh {
union
ehci_shadow
qh_next
;
/* ptr to qh; or periodic */
struct
list_head
qtd_list
;
/* sw qtd list */
struct
ehci_qtd
*
dummy
;
struct
ehci_qh
*
reclaim
;
/* next to reclaim */
atomic_t
refcount
;
unsigned
stamp
;
...
...
@@ -313,6 +314,8 @@ struct ehci_qh {
#define QH_STATE_LINKED 1
/* HC sees this */
#define QH_STATE_UNLINK 2
/* HC may still 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 */
u8
usecs
;
/* intr bandwidth */
...
...
@@ -426,16 +429,6 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
#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)
#ifndef DEBUG
...
...
drivers/usb/host/hc_simple.c
View file @
20b397bb
...
...
@@ -219,7 +219,7 @@ static int hci_unlink_urb (struct urb * urb)
if
(
!
list_empty
(
&
urb
->
urb_list
)
&&
urb
->
status
==
-
EINPROGRESS
)
{
/* URB active? */
if
(
urb
->
transfer_flags
&
(
URB_ASYNC_UNLINK
|
URB_TIMEOUT_KILLED
)
)
{
if
(
urb
->
transfer_flags
&
URB_ASYNC_UNLINK
)
{
/* asynchronous with callback */
/* relink the urb to the del list */
list_move
(
&
urb
->
urb_list
,
&
hci
->
del_list
);
...
...
@@ -388,7 +388,6 @@ static void qu_urb_timeout (unsigned long lurb)
struct
urb
*
urb
=
(
struct
urb
*
)
lurb
;
DBGFUNC
(
"enter qu_urb_timeout
\n
"
);
urb
->
transfer_flags
|=
URB_TIMEOUT_KILLED
;
hci_unlink_urb
(
urb
);
}
#endif
...
...
drivers/usb/host/ohci-hcd.c
View file @
20b397bb
...
...
@@ -203,28 +203,28 @@ static int ohci_urb_enqueue (
return
-
ENOMEM
;
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 */
urb_priv
->
length
=
size
;
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
++
)
{
urb_priv
->
td
[
i
]
=
td_alloc
(
ohci
,
SLAB_ATOMIC
);
urb_priv
->
td
[
i
]
=
td_alloc
(
ohci
,
mem_flags
);
if
(
!
urb_priv
->
td
[
i
])
{
urb_priv
->
length
=
i
;
retval
=
-
ENOMEM
;
goto
fail
;
urb_free_priv
(
ohci
,
urb_priv
)
;
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 */
if
(
ed
->
state
==
ED_IDLE
)
{
retval
=
ed_schedule
(
ohci
,
ed
);
...
...
drivers/usb/host/ohci-mem.c
View file @
20b397bb
...
...
@@ -97,17 +97,11 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
td
=
pci_pool_alloc
(
hc
->
td_cache
,
mem_flags
,
&
dma
);
if
(
td
)
{
int
hash
;
/* in case hc fetches it, make it look dead */
memset
(
td
,
0
,
sizeof
*
td
);
td
->
hwNextTD
=
cpu_to_le32
(
dma
);
td
->
td_dma
=
dma
;
/* hash it for later reverse mapping */
hash
=
TD_HASH_FUNC
(
dma
);
td
->
td_hash
=
hc
->
td_hash
[
hash
];
hc
->
td_hash
[
hash
]
=
td
;
/* hashed in td_fill */
}
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)
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static
void
td_fill
(
unsigned
int
info
,
td_fill
(
struct
ohci_hcd
*
ohci
,
u32
info
,
dma_addr_t
data
,
int
len
,
struct
urb
*
urb
,
int
index
)
{
struct
td
*
td
,
*
td_pt
;
struct
urb_priv
*
urb_priv
=
urb
->
hcpriv
;
int
is_iso
=
info
&
TD_ISO
;
int
hash
;
// ASSERT (index < urb_priv->length);
...
...
@@ -516,11 +517,16 @@ td_fill (unsigned int info,
td
->
hwBE
=
0
;
td
->
hwNextTD
=
cpu_to_le32
(
td_pt
->
td_dma
);
/* HC might read the TD right after we link it ... */
wmb
();
/* append to queue */
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
;
}
...
...
@@ -578,7 +584,7 @@ static void td_submit_urb (
:
TD_T_TOGGLE
|
TD_CC
|
TD_DP_IN
;
/* TDs _could_ transfer up to 8K each */
while
(
data_len
>
4096
)
{
td_fill
(
info
,
data
,
4096
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
data
,
4096
,
urb
,
cnt
);
data
+=
4096
;
data_len
-=
4096
;
cnt
++
;
...
...
@@ -586,11 +592,11 @@ static void td_submit_urb (
/* maybe avoid ED halt on final TD short read */
if
(
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
info
|=
TD_R
;
td_fill
(
info
,
data
,
data_len
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
data
,
data_len
,
urb
,
cnt
);
cnt
++
;
if
((
urb
->
transfer_flags
&
URB_ZERO_PACKET
)
&&
cnt
<
urb_priv
->
length
)
{
td_fill
(
info
,
0
,
0
,
urb
,
cnt
);
td_fill
(
ohci
,
info
,
0
,
0
,
urb
,
cnt
);
cnt
++
;
}
/* maybe kickstart bulk list */
...
...
@@ -605,17 +611,17 @@ static void td_submit_urb (
*/
case
PIPE_CONTROL
:
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
)
{
info
=
TD_CC
|
TD_R
|
TD_T_DATA1
;
info
|=
is_out
?
TD_DP_OUT
:
TD_DP_IN
;
/* 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
?
TD_CC
|
TD_DP_IN
|
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 */
wmb
();
writel
(
OHCI_CLF
,
&
ohci
->
regs
->
cmdstatus
);
...
...
@@ -634,7 +640,7 @@ static void td_submit_urb (
// a 2^16 iso range, vs other HCs max of 2^10)
frame
+=
cnt
*
urb
->
interval
;
frame
&=
0xffff
;
td_fill
(
TD_CC
|
TD_ISO
|
frame
,
td_fill
(
ohci
,
TD_CC
|
TD_ISO
|
frame
,
data
+
urb
->
iso_frame_desc
[
cnt
].
offset
,
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)
tmp
=
tmp
->
next
;
u
->
transfer_flags
|=
URB_TIMEOUT_KILLED
;
uhci_urb_dequeue
(
hcd
,
u
);
}
...
...
drivers/usb/image/scanner.c
View file @
20b397bb
/* -*- 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) 2002, 2003 Henning Meier-Geinitz
*
* 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
* modify it under the terms of the GNU General Public License as
...
...
@@ -300,8 +303,6 @@
* Frank Zago <fzago@greshamstorage.com> and
* 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
* - Added Mustek BearPaw 2400 TA. Thanks to Sergey
* Vlasov <vsu@mivlgu.murom.ru>.
...
...
@@ -332,12 +333,18 @@
* <oliver@neukum.name>.
*
* 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
* of everytime any USB device is plugged in.
* - Removed PV8630 ioctls. Use the standard ioctls instead.
* - Made endpoint detection more generic. Basically, only one bulk-in
* 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
* - Performance
...
...
@@ -360,7 +367,7 @@
* - All the developers that are working on USB SANE backends or other
* applications to use USB scanners.
* - 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:
*
...
...
@@ -369,6 +376,14 @@
* 24 Bit Color ~ 70 secs - 3.6 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>
/*
...
...
@@ -461,7 +476,7 @@ open_scanner(struct inode * inode, struct file * file)
}
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
;
goto
out_error
;
}
...
...
@@ -1047,6 +1062,9 @@ probe_scanner(struct usb_interface *intf,
if
(
scn
->
devfs
==
NULL
)
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
);
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
* 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
* modify it under the terms of the GNU General Public License as
...
...
@@ -19,11 +20,16 @@
* along with this program; if not, write to the Free Software
* 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/kernel.h>
#include <linux/errno.h>
...
...
@@ -45,7 +51,7 @@
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_LICENSE
(
"GPL"
);
...
...
@@ -65,79 +71,90 @@ MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
static
struct
usb_device_id
scanner_device_ids
[]
=
{
/* 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
,
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
,
0x20b0
)
},
/* Benq 4300 */
{
USB_DEVICE
(
0x04a5
,
0x20be
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x20c0
)
},
/* 1240UT, 1240U */
{
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
,
0x20fe
)
},
/* Benq 5300 */
/* Agfa */
{
USB_DEVICE
(
0x06bd
,
0x0001
)
},
/* SnapScan 1212U */
{
USB_DEVICE
(
0x06bd
,
0x0002
)
},
/* SnapScan 1236U */
{
USB_DEVICE
(
0x06bd
,
0x2061
)
},
/* Another SnapScan 1212U (?)*/
{
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
,
0x2093
)
},
/* SnapScan e10*/
{
USB_DEVICE
(
0x06bd
,
0x2095
)
},
/* SnapScan e25 */
{
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
,
0x20ff
)
},
/* SnapScan e42*/
/* Artec */
{
USB_DEVICE
(
0x05d8
,
0x4001
)
},
/* Ultima 2000 */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* Ultima 2000 (GT6801 based) */
/* Benq: see Acer */
/* Canon */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2205
)
},
/* FB1210U */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* CanoScan FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2202
)
},
/* CanoScan FB620U */
{
USB_DEVICE
(
0x04a9
,
0x2204
)
},
/* CanoScan FB630U/FB636U */
{
USB_DEVICE
(
0x04a9
,
0x2205
)
},
/* CanoScan FB1210U */
{
USB_DEVICE
(
0x04a9
,
0x2206
)
},
/* CanoScan N650U/N656U */
{
USB_DEVICE
(
0x04a9
,
0x2207
)
},
/* CanoScan N1220U */
{
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
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
/* Colorado -- See Primax/Colorado below */
/* Compaq */
{
USB_DEVICE
(
0x049f
,
0x0021
)
},
/* S200 */
/* Epson -- See Seiko/Epson below */
/* 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
,
0x2008
)
},
/* ColorPage
-
HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2009
)
},
/* ColorPage
-
HR6A */
{
USB_DEVICE
(
0x0458
,
0x2011
)
},
/* ColorPage
-
Vivid3x */
{
USB_DEVICE
(
0x0458
,
0x2013
)
},
/* ColorPage
-
HR7 */
{
USB_DEVICE
(
0x0458
,
0x2015
)
},
/* ColorPage
-
HR7LE */
{
USB_DEVICE
(
0x0458
,
0x2016
)
},
/* ColorPage
-
HR6X */
{
USB_DEVICE
(
0x0458
,
0x2008
)
},
/* ColorPage
HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2009
)
},
/* ColorPage
HR6A */
{
USB_DEVICE
(
0x0458
,
0x2011
)
},
/* ColorPage
Vivid3x */
{
USB_DEVICE
(
0x0458
,
0x2013
)
},
/* ColorPage
HR7 */
{
USB_DEVICE
(
0x0458
,
0x2015
)
},
/* ColorPage
HR7LE */
{
USB_DEVICE
(
0x0458
,
0x2016
)
},
/* ColorPage
HR6X */
/* Hewlett Packard */
{
USB_DEVICE
(
0x03f0
,
0x0505
)
},
/* ScanJet 2100C */
{
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
,
0x0101
)
},
/* ScanJet 4100C */
{
USB_DEVICE
(
0x03f0
,
0x0102
)
},
/* PhotoSmart S20 */
{
USB_DEVICE
(
0x03f0
,
0x0401
)
},
/* 5200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
{
USB_DEVICE
(
0x03f0
,
0x0201
)
},
/* 6200C */
{
USB_DEVICE
(
0x03f0
,
0x0601
)
},
/* 6300C */
{
USB_DEVICE
(
0x03f0
,
0x0105
)
},
/* ScanJet 4200C */
{
USB_DEVICE
(
0x03f0
,
0x0201
)
},
/* ScanJet 6200C */
{
USB_DEVICE
(
0x03f0
,
0x0205
)
},
/* ScanJet 3300C */
{
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 */
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* 1200U */
/* Lexmark */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
/* Lifetec */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* Lifetec LT9385 */
/* Memorex */
{
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, 0x0094) }, /* Phantom 336CX - C3 */
// { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */
...
...
@@ -146,58 +163,59 @@ static struct usb_device_id scanner_device_ids [] = {
// { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */
// { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */
/* 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 */
/* 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 */
{
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
(
0x0400
,
0x1000
)
},
/* BearPaw 1200 */
{
USB_DEVICE
(
0x055f
,
0x0002
)
},
/* ScanExpress 600 CU */
{
USB_DEVICE
(
0x055f
,
0x0873
)
},
/* ScanExpress 600 USB */
{
USB_DEVICE
(
0x055f
,
0x0003
)
},
/* ScanExpress 1200 USB */
{
USB_DEVICE
(
0x055f
,
0x0006
)
},
/* ScanExpress 1200 UB */
{
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
,
0x0010
)
},
/* BearPaw 1200F */
{
USB_DEVICE
(
0x055f
,
0x0210
)
},
/* ScanExpress A3 USB */
{
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
,
0x021c
)
},
/* BearPaw 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021d
)
},
/* Bearpaw 2400 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021e
)
},
/* BearPaw 1200 TA/CS */
{
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(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */
/* Nikon */
{
USB_DEVICE
(
0x04b0
,
0x4000
)
},
/* Coolscan LS 40 ED */
/* 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
,
0x0007
)
},
/* 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
,
0x0013
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0014
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0015
)
},
/* OpticPro U24 */
{
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 */
/* Primax/Colorado */
{
USB_DEVICE
(
0x0461
,
0x0300
)
},
/* G2-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0380
)
},
/* G2-600 #1 */
{
USB_DEVICE
(
0x0461
,
0x0301
)
},
/* G2E-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0381
)
},
/* ReadyScan 636i */
{
USB_DEVICE
(
0x0461
,
0x0302
)
},
/* G2-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0382
)
},
/* G2-600 #2 */
{
USB_DEVICE
(
0x0461
,
0x0303
)
},
/* G2E-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0383
)
},
/* G2E-600 */
{
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
,
0x0360
)
},
/* Colorado USB 19200 */
{
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 */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
/* Seiko/Epson Corp. */
...
...
@@ -221,17 +239,18 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x04b8
,
0x011c
)
},
/* Perfection 3200 */
{
USB_DEVICE
(
0x04b8
,
0x011d
)
},
/* Perfection 1260 */
{
USB_DEVICE
(
0x04b8
,
0x011e
)
},
/* Perfection 1660 Photo */
{
USB_DEVICE
(
0x04b8
,
0x0801
)
},
/* Stylus CX5200 */
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
/* Umax */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
{
USB_DEVICE
(
0x1606
,
0x0030
)
},
/* Astra 2000U */
{
USB_DEVICE
(
0x1606
,
0x0060
)
},
/* Astra 3400U/3450U */
{
USB_DEVICE
(
0x1606
,
0x0130
)
},
/* Astra 2100U */
{
USB_DEVICE
(
0x1606
,
0x0160
)
},
/* Astra 5400U */
{
USB_DEVICE
(
0x1606
,
0x0160
)
},
/* Astra 5400U */
{
USB_DEVICE
(
0x1606
,
0x0230
)
},
/* Astra 2200U */
/* Visioneer */
{
USB_DEVICE
(
0x04a7
,
0x0221
)
},
/* OneTouch 5300 USB */
{
USB_DEVICE
(
0x04a7
,
0x0211
)
},
/* OneTouch 7600 USB */
{
USB_DEVICE
(
0x04a7
,
0x0221
)
},
/* OneTouch 5300 USB */
{
USB_DEVICE
(
0x04a7
,
0x0231
)
},
/* 6100 USB */
{
USB_DEVICE
(
0x04a7
,
0x0311
)
},
/* 6200 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)
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idProduct
;
...
...
@@ -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_UPS1
,
HID_QUIRK_HIDDEV
},
{
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
}
};
...
...
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)
**
***********************/
/* 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
)
{
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
}
else
{
/* 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
))
==
NULL
)
{
skb_trim
(
skb
,
0
);
}
NULL
)
return
NULL
;
}
}
...
...
drivers/usb/misc/atmsar.h
View file @
20b397bb
...
...
@@ -33,6 +33,7 @@
#define ATMSAR_USE_53BYTE_CELL 0x1L
#define ATMSAR_SET_PTI 0x2L
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
/* types */
#define ATMSAR_TYPE_AAL0 ATM_AAL0
...
...
@@ -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
);
unsigned
int
atmsar_encode
(
struct
atmsar_vcc_data
*
ctx
,
char
*
source
,
char
*
target
,
unsigned
int
pdu_length
);
#endif
/* _ATMSAR_H_ */
drivers/usb/misc/speedtouch.c
View file @
20b397bb
...
...
@@ -46,6 +46,7 @@
*
*/
#include <asm/semaphore.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
...
...
@@ -58,7 +59,6 @@
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include "atmsar.h"
...
...
@@ -106,20 +106,21 @@
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_IN 0x87
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
/* usb_device_id struct */
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
}
/* list terminator
*/
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
}
/* Terminating entry
*/
};
/* not exporting this prevents the depmod from generating the map that causes the modules to be isnserted as driver.
* we do not want this, we want the script run.
MODULE_DEVICE_TABLE ( usb, udsl_usb_ids);
*/
MODULE_DEVICE_TABLE
(
usb
,
udsl_usb_ids
);
/* context declarations */
struct
udsl_data_ctx
{
struct
udsl_receiver
{
struct
list_head
list
;
struct
sk_buff
*
skb
;
struct
urb
*
urb
;
struct
udsl_instance_data
*
instance
;
...
...
@@ -137,25 +138,32 @@ struct udsl_usb_send_data_context {
*/
struct
udsl_instance_data
{
struct
tasklet_struct
recvqueue_tasklet
;
struct
semaphore
serialize
;
/* usb device part */
struct
usb_device
*
usb_dev
;
struct
udsl_data_ctx
*
rcvbufs
;
struct
sk_buff_head
sndqueue
;
struct
udsl_usb_send_data_context
send_ctx
[
UDSL_NUMBER_SND_URBS
];
int
data_start
ed
;
struct
udsl_usb_send_data_context
send_ctx
[
UDSL_NUMBER_SND_URBS
];
int
firmware_load
ed
;
/* atm device part */
struct
atm_dev
*
atm_dev
;
struct
sk_buff_head
recvqueue
;
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
;
spinlock_t
completed_receivers_lock
;
struct
list_head
completed_receivers
;
struct
tasklet_struct
receive_tasklet
;
};
static
DECLARE_MUTEX
(
udsl_usb_ioctl_lock
)
;
static
const
char
udsl_driver_name
[]
=
"Alcatel SpeedTouch USB"
;
#ifdef DEBUG_PACKET
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);
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_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
void
udsl_atm_processqueue
(
unsigned
long
data
);
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
);
static
struct
atmdev_ops
udsl_atm_devops
=
{
.
open
=
udsl_atm_open
,
...
...
@@ -203,6 +210,170 @@ static struct usb_driver udsl_usb_driver = {
.
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 **
************/
...
...
@@ -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
)
{
struct
atm_vcc
*
walk
;
struct
sk_buff
*
skb
;
struct
atm_dev
*
atm_dev
;
if
(
!
instance
->
atm_dev
)
...
...
@@ -241,10 +394,6 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
atm_dev
=
instance
->
atm_dev
;
/* clean queue */
while
((
skb
=
skb_dequeue
(
&
instance
->
recvqueue
)))
dev_kfree_skb
(
skb
);
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
walk
=
atm_dev
->
vccs
;
shutdown_atm_dev
(
atm_dev
);
...
...
@@ -253,16 +402,8 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
wake_up
(
&
walk
->
sleep
);
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
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
;
int
left
=
*
pos
;
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
if
(
!
left
--
)
return
sprintf
(
page
,
"SpeedTouch USB %s-%s (%02x:%02x:%02x:%02x:%02x:%02x)
\n
"
,
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
return
0
;
}
/***************************************************************************
*
* ATM DATA functions
...
...
@@ -325,8 +472,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
PDEBUG
(
"udsl_atm_send called
\n
"
);
if
(
!
dev_data
)
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL data!
\n
"
);
return
-
EINVAL
;
}
if
(
!
instance
->
firmware_loaded
)
return
-
EAGAIN
;
switch
(
vcc
->
qos
.
aal
)
{
case
ATM_AAL5
:
...
...
@@ -350,67 +502,13 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
break
;
default:
return
-
EINVAL
;
}
;
}
PDEBUG
(
"udsl_atm_send unsuccessfull
\n
"
);
return
0
;
nomem:
vcc
->
pop
(
vcc
,
skb
);
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)
* SAR driver entries
*
****************************************************************************/
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
{
struct
udsl_atm_dev_data
*
dev_data
;
...
...
@@ -426,6 +525,11 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
PDEBUG
(
"udsl_atm_open called
\n
"
);
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
/* at the moment only AAL5 support */
if
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
return
-
EINVAL
;
...
...
@@ -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
;
if
(
instance
->
firmware_loaded
)
udsl_fire_receivers
(
instance
);
PDEBUG
(
"udsl_atm_open successfull
\n
"
);
return
0
;
}
...
...
@@ -464,6 +571,11 @@ static void udsl_atm_close (struct atm_vcc *vcc)
PDEBUG
(
"udsl_atm_close called
\n
"
);
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL data!
\n
"
);
return
;
}
/* freeing resources */
/* cancel all sends on this vcc */
udsl_usb_cancelsends
(
instance
,
vcc
);
...
...
@@ -482,7 +594,7 @@ static void udsl_atm_close (struct atm_vcc *vcc)
PDEBUG
(
"udsl_atm_close successfull
\n
"
);
return
;
}
;
}
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:
return
-
ENOIOCTLCMD
;
}
}
;
}
/************
...
...
@@ -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
);
if
(
!
instance
->
data_started
)
return
-
EAGAIN
;
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
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
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
PDEBUG
(
"udsl_usb_send_data: skb (0x%p) queued
\n
"
,
skb
);
return
0
;
}
;
}
/* init context */
urb
=
instance
->
send_ctx
[
i
].
urb
;
...
...
@@ -620,285 +729,264 @@ static int udsl_usb_send_data (struct udsl_instance_data *instance, struct atm_v
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
,
urb
->
actual_length
,
urb
->
status
);
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
ctx
=
urb
->
context
;
if
(
!
ctx
||
!
ctx
->
skb
)
return
;
PDEBUG
(
"udsl_usb_ioctl entered
\n
"
);
instance
=
ctx
->
instance
;
switch
(
urb
->
status
)
{
case
0
:
PDEBUG
(
"udsl_usb_data_receive: processing urb with ctx %p, urb %p (%p), skb %p
\n
"
,
ctx
,
ctx
?
ctx
->
urb
:
NULL
,
urb
,
ctx
?
ctx
->
skb
:
NULL
);
/* update the skb structure */
skb_put
(
ctx
->
skb
,
urb
->
actual_length
);
/* 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
;
case
-
ENOENT
:
/* buffer was unlinked */
case
-
EILSEQ
:
/* unplug or timeout */
case
-
ETIMEDOUT
:
/* unplug or timeout */
/*
* we don't do anything here and we don't resubmit
*/
return
;
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
ENODEV
;
}
usb_fill_bulk_urb
(
urb
,
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
;
};
switch
(
code
)
{
case
UDSL_IOCTL_START
:
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
down
(
&
instance
->
serialize
);
/* vs self */
if
(
!
instance
->
firmware_loaded
)
{
usb_set_interface
(
instance
->
usb_dev
,
1
,
2
);
instance
->
firmware_loaded
=
1
;
}
up
(
&
instance
->
serialize
);
udsl_fire_receivers
(
instance
);
return
0
;
case
UDSL_IOCTL_STOP
:
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
return
0
;
default:
return
-
ENOTTY
;
}
}
static
int
udsl_usb_
data_init
(
struct
udsl_instance_data
*
instance
)
static
int
udsl_usb_
probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
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
)
return
1
;
PDEBUG
(
"Trying device with Vendor=0x%x, Product=0x%x, ifnum %d
\n
"
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
ifnum
)
;
/* set alternate setting 1 on interface 1 */
usb_set_interface
(
instance
->
usb_dev
,
1
,
2
);
if
((
dev
->
descriptor
.
bDeviceClass
!=
USB_CLASS_VENDOR_SPEC
)
||
(
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
,
usb_maxpacket
(
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
0
));
PDEBUG
(
"Device Accepted
\n
"
);
instance
->
rcvbufs
=
kmalloc
(
sizeof
(
struct
udsl_data_ctx
)
*
UDSL_NUMBER_RCV_URBS
,
GFP_KERNEL
);
if
(
!
instance
->
rcvbufs
)
return
-
ENOMEM
;
/* instance init */
if
(
!
(
instance
=
kmalloc
(
sizeof
(
struct
udsl_instance_data
),
GFP_KERNEL
)))
{
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
++
)
{
struct
udsl_data_ctx
*
ctx
=
&
(
instance
->
rcvbufs
[
i
]);
instance
->
usb_dev
=
dev
;
ctx
->
urb
=
NULL
;
ctx
->
skb
=
dev_alloc_skb
(
UDSL_RECEIVE_BUFFER_SIZE
);
if
(
!
ctx
->
skb
)
continue
;
spin_lock_init
(
&
instance
->
spare_receivers_lock
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
ctx
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
ctx
->
urb
)
{
kfree_skb
(
ctx
->
skb
);
ctx
->
skb
=
NULL
;
break
;
};
spin_lock_init
(
&
instance
->
completed_receivers_lock
);
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
usb_fill_bulk_urb
(
ctx
->
urb
,
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
);
tasklet_init
(
&
instance
->
receive_tasklet
,
udsl_process_receive
,
(
unsigned
long
)
instance
);
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
"
,
ctx
->
skb
->
truesize
,
UDSL_RECEIVE_BUFFER_SIZE
);
if
(
!
(
rcv
->
skb
=
dev_alloc_skb
(
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
)
PDEBUG
(
"
udsl_usb_data_init: Submit failed, loosing urb.
\n
"
);
else
succes
++
;
}
if
(
!
(
rcv
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
PDEBUG
(
"
No memory for receive urb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
}
PDEBUG
(
"udsl_usb_data_init %d urb%s queued for receive
\n
"
,
succes
,
(
succes
!=
1
)
?
"s"
:
""
);
rcv
->
instance
=
instance
;
for
(
i
=
0
,
succes
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
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
++
;
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
PDEBUG
(
"skb->truesize = %d (asked for %d)
\n
"
,
rcv
->
skb
->
truesize
,
UDSL_RECEIVE_BUFFER_SIZE
);
}
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
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
if
(
!
(
snd
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
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
)
{
int
i
;
/* atm init */
if
(
!
(
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
&
udsl_atm_devops
,
-
1
,
0
)))
{
PDEBUG
(
"failed to register ATM device!
\n
"
);
err
=
-
ENOMEM
;
goto
fail_atm
;
}
if
(
!
instance
->
data_started
)
return
0
;
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
;
if
(
!
instance
->
rcvbufs
)
return
0
;
/* tmp init atm device, set to 128kbit */
instance
->
atm_dev
->
link_rate
=
128
*
1000
/
424
;
/* destroy urbs */
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_data_ctx
*
ctx
=
&
(
instance
->
rcvbufs
[
i
]);
/* set MAC address, it is stored in the serial number */
usb_string
(
instance
->
usb_dev
,
instance
->
usb_dev
->
descriptor
.
iSerialNumber
,
mac_str
,
13
);
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
))
continue
;
PDEBUG
(
"MAC is %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]);
usb_unlink_urb
(
ctx
->
urb
);
memcpy
(
instance
->
atm_dev
->
esi
,
mac
,
6
);
usb_free_urb
(
ctx
->
urb
);
kfree_skb
(
ctx
->
skb
);
ctx
->
skb
=
NULL
;
}
wmb
();
tasklet_kill
(
&
instance
->
recvqueue_tasklet
)
;
instance
->
atm_dev
->
dev_data
=
instance
;
usb_set_intfdata
(
intf
,
instance
);
return
0
;
fail_atm:
fail_urbs:
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
)
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
ctx
->
skb
=
NULL
;
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
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 */
kfree
(
instance
->
rcvbufs
);
instance
->
rcvbufs
=
NULL
;
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
)
{
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
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
PDEBUG
(
"disconnecting
\n
"
);
return
0
;
};
usb_set_intfdata
(
intf
,
NULL
);
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
;
}
/***************************************************************************
*
* usb driver entries
*
****************************************************************************/
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
tasklet_disable
(
&
instance
->
receive_tasklet
);
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
)
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
int
retval
;
PDEBUG
(
"udsl_usb_disconnect: flushed %u spare receivers
\n
"
,
count
);
down
(
&
udsl_usb_ioctl_lock
);
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
;
}
count
=
UDSL_NUMBER_RCV_URBS
-
count
;
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
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
;
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
usb_unlink_urb
(
instance
->
all_receivers
[
i
].
urb
);
PDEBUG
(
"Trying device with Vendor=0x%x, Product=0x%x, ifnum %d
\n
"
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
ifnum
);
/* wait for completion handlers to finish */
do
{
unsigned
int
completed
=
0
;
if
((
dev
->
descriptor
.
bDeviceClass
!=
USB_CLASS_VENDOR_SPEC
)
||
(
dev
->
descriptor
.
idVendor
!=
SPEEDTOUCH_VENDORID
)
||
(
dev
->
descriptor
.
idProduct
!=
SPEEDTOUCH_PRODUCTID
)
||
(
ifnum
!=
1
))
return
-
ENODEV
;
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
list_for_each
(
pos
,
&
instance
->
completed_receivers
)
if
(
++
completed
>
count
)
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 */
instance
=
kmalloc
(
sizeof
(
struct
udsl_instance_data
),
GFP_KERNEL
);
if
(
!
instance
)
{
PDEBUG
(
"No memory for Instance data!
\n
"
);
return
-
ENOMEM
;
}
/* not all urbs completed */
yield
();
}
while
(
1
);
/* initialize structure */
memset
(
instance
,
0
,
sizeof
(
struct
udsl_instance_data
));
instance
->
usb_dev
=
dev
;
instance
->
rcvbufs
=
NULL
;
tasklet_init
(
&
instance
->
recvqueue_tasklet
,
udsl_atm_processqueue
,
(
unsigned
long
)
instance
);
PDEBUG
(
"udsl_usb_disconnect: flushing %u completed receivers
\n
"
,
count
);
/* no need to take the spinlock - no completion handlers running */
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
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 */
usb_string
(
instance
->
usb_dev
,
instance
->
usb_dev
->
descriptor
.
iSerialNumber
,
mac_str
,
13
);
for
(
i
=
0
;
i
<
6
;
i
++
)
mac
[
i
]
=
(
hex2int
(
mac_str
[
i
*
2
])
*
16
)
+
(
hex2int
(
mac_str
[
i
*
2
+
1
]));
PDEBUG
(
"udsl_usb_disconnect: freeing receivers
\n
"
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
PDEBUG
(
"MAC is %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]
);
udsl_atm_set_mac
(
instance
,
mac
);
usb_free_urb
(
rcv
->
urb
);
kfree_skb
(
rcv
->
skb
);
}
usb_set_intfdata
(
intf
,
instance
);
return
0
;
}
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_usb_send_data_context
*
ctx
=
&
(
instance
->
send_ctx
[
i
]);
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
usb_unlink_urb
(
ctx
->
urb
);
PDEBUG
(
"disconnecting
\n
"
);
if
(
ctx
->
skb
)
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
ctx
->
skb
=
NULL
;
usb_set_intfdata
(
intf
,
NULL
);
if
(
instance
)
{
/* unlinking receive buffers */
udsl_usb_data_exit
(
instance
);
usb_free_urb
(
ctx
->
urb
);
/* removing atm device */
if
(
instance
->
atm_dev
)
udsl_atm_stopdevice
(
instance
);
}
kfree
(
instance
);
MOD_DEC_USE_COUNT
;
}
/* removing atm device */
if
(
instance
->
atm_dev
)
udsl_atm_stopdevice
(
instance
);
kfree
(
instance
);
}
/***************************************************************************
*
* Driver Init
...
...
@@ -907,18 +995,25 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
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
);
}
static
void
__exit
udsl_usb_cleanup
(
void
)
{
PDEBUG
(
"udsl_usb_cleanup
\n
"
);
usb_deregister
(
&
udsl_usb_driver
);
}
module_init
(
udsl_usb_init
);
module_exit
(
udsl_usb_cleanup
);
module_init
(
udsl_usb_init
);
module_exit
(
udsl_usb_cleanup
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG_PACKET
/*******************************************************************************
...
...
@@ -929,7 +1024,7 @@ module_exit(udsl_usb_cleanup);
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
)
{
unsigned
char
buffer
[
256
];
unsigned
char
buffer
[
256
];
int
i
=
0
,
j
=
0
;
for
(
i
=
0
;
i
<
len
;)
{
...
...
@@ -941,10 +1036,6 @@ static int udsl_print_packet (const unsigned char *data, int len)
PDEBUG
(
"%s
\n
"
,
buffer
);
}
return
i
;
}
;
}
#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 [] = {
static
struct
usb_device_id
id_table_8U232AM
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_RELAIS_PID
)
},
{
USB_DEVICE
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
)
},
{
}
/* Terminating entry */
};
...
...
@@ -143,6 +144,7 @@ static struct usb_device_id id_table_8U232AM [] = {
static
struct
usb_device_id
id_table_combined
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_SIO_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
)
},
{
}
/* Terminating entry */
};
...
...
drivers/usb/serial/ftdi_sio.h
View file @
20b397bb
...
...
@@ -17,11 +17,14 @@
* Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the
* 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_SIO_PID 0x8372
/* Product Id SIO application of 8U100AX */
#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_PID 0x0001
/* Product Id */
...
...
drivers/usb/serial/ipaq.c
View file @
20b397bb
...
...
@@ -106,6 +106,7 @@ static struct usb_device_id ipaq_id_table [] = {
{
USB_DEVICE
(
CASIO_VENDOR_ID
,
CASIO_EM500_ID
)
},
{
USB_DEVICE
(
COMPAQ_VENDOR_ID
,
COMPAQ_IPAQ_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_568_ID
)
},
{
USB_DEVICE
(
HP_VENDOR_ID
,
HP_2016_ID
)
},
...
...
@@ -126,6 +127,7 @@ static struct usb_device_id ipaq_id_table [] = {
{
USB_DEVICE
(
SAGEM_VENDOR_ID
,
SAGEM_WIRELESS_ID
)
},
{
USB_DEVICE
(
SOCKET_VENDOR_ID
,
SOCKET_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
(
NEC_VENDOR_ID
,
NEC_PRODUCT_ID
)
},
{
}
/* Terminating entry */
...
...
drivers/usb/serial/ipaq.h
View file @
20b397bb
...
...
@@ -30,6 +30,9 @@
#define COMPAQ_IPAQ_ID 0x0003
#define COMPAQ_0032_ID 0x0032
#define DELL_VENDOR_ID 0x413c
#define DELL_AXIM_ID 0x4001
#define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
...
...
@@ -63,6 +66,7 @@
#define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_PRODUCT_ID 0x0700
#define TOSHIBA_E740_ID 0x0706
#define HTC_VENDOR_ID 0x0bb4
#define HTC_PRODUCT_ID 0x00ce
...
...
drivers/usb/serial/pl2303.c
View file @
20b397bb
...
...
@@ -74,6 +74,7 @@ static struct usb_device_id id_table [] = {
{
USB_DEVICE
(
ITEGNO_VENDOR_ID
,
ITEGNO_PRODUCT_ID
)
},
{
USB_DEVICE
(
MA620_VENDOR_ID
,
MA620_PRODUCT_ID
)
},
{
USB_DEVICE
(
RATOC_VENDOR_ID
,
RATOC_PRODUCT_ID
)
},
{
USB_DEVICE
(
TRIPP_VENDOR_ID
,
TRIPP_PRODUCT_ID
)
},
{
}
/* Terminating entry */
};
...
...
drivers/usb/serial/pl2303.h
View file @
20b397bb
...
...
@@ -28,3 +28,6 @@
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID 0xb000
#define TRIPP_VENDOR_ID 0x2478
#define TRIPP_PRODUCT_ID 0x2008
drivers/usb/storage/datafab.h
View file @
20b397bb
...
...
@@ -27,14 +27,14 @@
extern
int
datafab_transport
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
);
struct
datafab_info
{
unsigned
long
sectors
;
// total sector count
unsigned
long
ssize
;
// sector size in bytes
char
lun
;
// used for dual-slot readers
// the following aren't used yet
unsigned
long
sectors
;
// total sector count
unsigned
long
ssize
;
// sector size in bytes
char
lun
;
// used for dual-slot readers
// the following aren't used yet
unsigned
char
sense_key
;
unsigned
long
sense_asc
;
// additional sense code
unsigned
long
sense_ascq
;
// additional sense code qualifier
unsigned
long
sense_asc
;
// additional sense code
unsigned
long
sense_ascq
;
// additional sense code qualifier
};
#endif
drivers/usb/storage/freecom.c
View file @
20b397bb
...
...
@@ -45,42 +45,42 @@ static void pdump (void *, int);
#define DRQ_STAT 0x08
struct
freecom_udata
{
u8
buffer
[
64
];
/* Common command block. */
u8
buffer
[
64
];
/* Common command block. */
};
typedef
struct
freecom_udata
*
freecom_udata_t
;
/* All of the outgoing packets are 64 bytes long. */
struct
freecom_cb_wrap
{
u8
Type
;
/* Command type. */
u8
Timeout
;
/* Timeout in seconds. */
u8
Atapi
[
12
];
/* An ATAPI packet. */
u8
Filler
[
50
];
/* Padding Data. */
u8
Type
;
/* Command type. */
u8
Timeout
;
/* Timeout in seconds. */
u8
Atapi
[
12
];
/* An ATAPI packet. */
u8
Filler
[
50
];
/* Padding Data. */
};
struct
freecom_xfer_wrap
{
u8
Type
;
/* Command type. */
u8
Timeout
;
/* Timeout in seconds. */
u32
Count
;
/* Number of bytes to transfer. */
u8
Pad
[
58
];
u8
Type
;
/* Command type. */
u8
Timeout
;
/* Timeout in seconds. */
u32
Count
;
/* Number of bytes to transfer. */
u8
Pad
[
58
];
}
__attribute__
((
packed
));
struct
freecom_ide_out
{
u8
Type
;
/* Type + IDE register. */
u8
Pad
;
u16
Value
;
/* Value to write. */
u8
Pad2
[
60
];
u8
Type
;
/* Type + IDE register. */
u8
Pad
;
u16
Value
;
/* Value to write. */
u8
Pad2
[
60
];
};
struct
freecom_ide_in
{
u8
Type
;
/* Type | IDE register. */
u8
Pad
[
63
];
u8
Type
;
/* Type | IDE register. */
u8
Pad
[
63
];
};
struct
freecom_status
{
u8
Status
;
u8
Reason
;
u16
Count
;
u8
Pad
[
60
];
u8
Status
;
u8
Reason
;
u16
Count
;
u8
Pad
[
60
];
};
/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
...
...
@@ -110,32 +110,32 @@ struct freecom_status {
static
int
freecom_readdata
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
,
unsigned
int
ipipe
,
unsigned
int
opipe
,
int
count
)
unsigned
int
ipipe
,
unsigned
int
opipe
,
int
count
)
{
freecom_udata_t
extra
=
(
freecom_udata_t
)
us
->
extra
;
struct
freecom_xfer_wrap
*
fxfr
=
(
struct
freecom_xfer_wrap
*
)
extra
->
buffer
;
int
result
;
fxfr
->
Type
=
FCM_PACKET_INPUT
|
0x00
;
fxfr
->
Timeout
=
0
;
/* Short timeout for debugging. */
fxfr
->
Count
=
cpu_to_le32
(
count
);
memset
(
fxfr
->
Pad
,
0
,
sizeof
(
fxfr
->
Pad
));
US_DEBUGP
(
"Read data Freecom! (c=%d)
\n
"
,
count
);
/* Issue the transfer command. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fxfr
,
FCM_PACKET_LENGTH
,
NULL
);
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"Freecom readdata transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* Now transfer all of our blocks. */
freecom_udata_t
extra
=
(
freecom_udata_t
)
us
->
extra
;
struct
freecom_xfer_wrap
*
fxfr
=
(
struct
freecom_xfer_wrap
*
)
extra
->
buffer
;
int
result
;
fxfr
->
Type
=
FCM_PACKET_INPUT
|
0x00
;
fxfr
->
Timeout
=
0
;
/* Short timeout for debugging. */
fxfr
->
Count
=
cpu_to_le32
(
count
);
memset
(
fxfr
->
Pad
,
0
,
sizeof
(
fxfr
->
Pad
));
US_DEBUGP
(
"Read data Freecom! (c=%d)
\n
"
,
count
);
/* Issue the transfer command. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fxfr
,
FCM_PACKET_LENGTH
,
NULL
);
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"Freecom readdata transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* Now transfer all of our blocks. */
US_DEBUGP
(
"Start of read
\n
"
);
result
=
usb_stor_bulk_transfer_srb
(
us
,
ipipe
,
srb
,
count
);
US_DEBUGP
(
"freecom_readdata done!
\n
"
);
US_DEBUGP
(
"freecom_readdata done!
\n
"
);
if
(
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
...
...
@@ -144,33 +144,33 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
static
int
freecom_writedata
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
,
int
unsigned
ipipe
,
unsigned
int
opipe
,
int
count
)
int
unsigned
ipipe
,
unsigned
int
opipe
,
int
count
)
{
freecom_udata_t
extra
=
(
freecom_udata_t
)
us
->
extra
;
struct
freecom_xfer_wrap
*
fxfr
=
(
struct
freecom_xfer_wrap
*
)
extra
->
buffer
;
int
result
;
fxfr
->
Type
=
FCM_PACKET_OUTPUT
|
0x00
;
fxfr
->
Timeout
=
0
;
/* Short timeout for debugging. */
fxfr
->
Count
=
cpu_to_le32
(
count
);
memset
(
fxfr
->
Pad
,
0
,
sizeof
(
fxfr
->
Pad
));
US_DEBUGP
(
"Write data Freecom! (c=%d)
\n
"
,
count
);
/* Issue the transfer command. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fxfr
,
FCM_PACKET_LENGTH
,
NULL
);
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"Freecom writedata transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* Now transfer all of our blocks. */
freecom_udata_t
extra
=
(
freecom_udata_t
)
us
->
extra
;
struct
freecom_xfer_wrap
*
fxfr
=
(
struct
freecom_xfer_wrap
*
)
extra
->
buffer
;
int
result
;
fxfr
->
Type
=
FCM_PACKET_OUTPUT
|
0x00
;
fxfr
->
Timeout
=
0
;
/* Short timeout for debugging. */
fxfr
->
Count
=
cpu_to_le32
(
count
);
memset
(
fxfr
->
Pad
,
0
,
sizeof
(
fxfr
->
Pad
));
US_DEBUGP
(
"Write data Freecom! (c=%d)
\n
"
,
count
);
/* Issue the transfer command. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fxfr
,
FCM_PACKET_LENGTH
,
NULL
);
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"Freecom writedata transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* Now transfer all of our blocks. */
US_DEBUGP
(
"Start of write
\n
"
);
result
=
usb_stor_bulk_transfer_srb
(
us
,
opipe
,
srb
,
count
);
US_DEBUGP
(
"freecom_writedata done!
\n
"
);
US_DEBUGP
(
"freecom_writedata done!
\n
"
);
if
(
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_GOOD
;
...
...
@@ -182,54 +182,54 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
*/
int
freecom_transport
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
)
{
struct
freecom_cb_wrap
*
fcb
;
struct
freecom_status
*
fst
;
unsigned
int
ipipe
,
opipe
;
/* We need both pipes. */
int
result
;
struct
freecom_cb_wrap
*
fcb
;
struct
freecom_status
*
fst
;
unsigned
int
ipipe
,
opipe
;
/* We need both pipes. */
int
result
;
unsigned
int
partial
;
int
length
;
freecom_udata_t
extra
;
int
length
;
freecom_udata_t
extra
;
extra
=
(
freecom_udata_t
)
us
->
extra
;
extra
=
(
freecom_udata_t
)
us
->
extra
;
fcb
=
(
struct
freecom_cb_wrap
*
)
extra
->
buffer
;
fst
=
(
struct
freecom_status
*
)
extra
->
buffer
;
fcb
=
(
struct
freecom_cb_wrap
*
)
extra
->
buffer
;
fst
=
(
struct
freecom_status
*
)
extra
->
buffer
;
US_DEBUGP
(
"Freecom TRANSPORT STARTED
\n
"
);
US_DEBUGP
(
"Freecom TRANSPORT STARTED
\n
"
);
/* Get handles for both transports. */
opipe
=
us
->
send_bulk_pipe
;
ipipe
=
us
->
recv_bulk_pipe
;
/* Get handles for both transports. */
opipe
=
us
->
send_bulk_pipe
;
ipipe
=
us
->
recv_bulk_pipe
;
/* The ATAPI Command always goes out first. */
fcb
->
Type
=
FCM_PACKET_ATAPI
|
0x00
;
fcb
->
Timeout
=
0
;
memcpy
(
fcb
->
Atapi
,
srb
->
cmnd
,
12
);
memset
(
fcb
->
Filler
,
0
,
sizeof
(
fcb
->
Filler
));
/* The ATAPI Command always goes out first. */
fcb
->
Type
=
FCM_PACKET_ATAPI
|
0x00
;
fcb
->
Timeout
=
0
;
memcpy
(
fcb
->
Atapi
,
srb
->
cmnd
,
12
);
memset
(
fcb
->
Filler
,
0
,
sizeof
(
fcb
->
Filler
));
US_DEBUG
(
pdump
(
srb
->
cmnd
,
12
));
US_DEBUG
(
pdump
(
srb
->
cmnd
,
12
));
/* Send it out. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fcb
,
FCM_PACKET_LENGTH
,
NULL
);
/* Send it out. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fcb
,
FCM_PACKET_LENGTH
,
NULL
);
/* The Freecom device will only fail if there is something wrong in
* USB land. It returns the status in its own registers, which
* come back in the bulk pipe. */
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"freecom transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* The Freecom device will only fail if there is something wrong in
* USB land. It returns the status in its own registers, which
* come back in the bulk pipe. */
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
US_DEBUGP
(
"freecom transport error
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
/* There are times we can optimize out this status read, but it
* doesn't hurt us to always do it now. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
US_DEBUGP
(
"foo Status result %d %u
\n
"
,
result
,
partial
);
/* There are times we can optimize out this status read, but it
* doesn't hurt us to always do it now. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
US_DEBUGP
(
"foo Status result %d %u
\n
"
,
result
,
partial
);
if
(
result
!=
USB_STOR_XFER_GOOD
)
return
USB_STOR_TRANSPORT_ERROR
;
US_DEBUG
(
pdump
((
void
*
)
fst
,
partial
));
US_DEBUG
(
pdump
((
void
*
)
fst
,
partial
));
/* The firmware will time-out commands after 20 seconds. Some commands
* can legitimately take longer than this, so we use a different
...
...
@@ -249,7 +249,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
memset
(
fcb
->
Atapi
,
0
,
sizeof
(
fcb
->
Atapi
));
memset
(
fcb
->
Filler
,
0
,
sizeof
(
fcb
->
Filler
));
/* Send it out. */
/* Send it out. */
result
=
usb_stor_bulk_transfer_buf
(
us
,
opipe
,
fcb
,
FCM_PACKET_LENGTH
,
NULL
);
...
...
@@ -263,31 +263,31 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* get the data */
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
US_DEBUGP
(
"bar Status result %d %u
\n
"
,
result
,
partial
);
if
(
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
US_DEBUG
(
pdump
((
void
*
)
fst
,
partial
));
}
if
(
partial
!=
4
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
1
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
/* The device might not have as much data available as we
* requested. If you ask for more than the device has, this reads
* and such will hang. */
US_DEBUGP
(
"Device indicates that it has %d bytes available
\n
"
,
le16_to_cpu
(
fst
->
Count
));
US_DEBUGP
(
"SCSI requested %d
\n
"
,
srb
->
request_bufflen
);
/* Find the length we desire to read. */
if
(
partial
!=
4
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
1
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
/* The device might not have as much data available as we
* requested. If you ask for more than the device has, this reads
* and such will hang. */
US_DEBUGP
(
"Device indicates that it has %d bytes available
\n
"
,
le16_to_cpu
(
fst
->
Count
));
US_DEBUGP
(
"SCSI requested %d
\n
"
,
srb
->
request_bufflen
);
/* Find the length we desire to read. */
switch
(
srb
->
cmnd
[
0
])
{
case
INQUIRY
:
case
REQUEST_SENSE
:
/* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
...
...
@@ -305,97 +305,97 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP
(
"Truncating request to match buffer length: %d
\n
"
,
length
);
}
/* What we do now depends on what direction the data is supposed to
* move in. */
switch
(
us
->
srb
->
sc_data_direction
)
{
case
SCSI_DATA_READ
:
/* Make sure that the status indicates that the device
* wants data as well. */
if
((
fst
->
Status
&
DRQ_STAT
)
==
0
||
(
fst
->
Reason
&
3
)
!=
2
)
{
US_DEBUGP
(
"SCSI wants data, drive doesn't have any
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
result
=
freecom_readdata
(
srb
,
us
,
ipipe
,
opipe
,
length
);
if
(
result
!=
USB_STOR_TRANSPORT_GOOD
)
return
result
;
US_DEBUGP
(
"FCM: Waiting for status
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
/* What we do now depends on what direction the data is supposed to
* move in. */
switch
(
us
->
srb
->
sc_data_direction
)
{
case
SCSI_DATA_READ
:
/* Make sure that the status indicates that the device
* wants data as well. */
if
((
fst
->
Status
&
DRQ_STAT
)
==
0
||
(
fst
->
Reason
&
3
)
!=
2
)
{
US_DEBUGP
(
"SCSI wants data, drive doesn't have any
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
result
=
freecom_readdata
(
srb
,
us
,
ipipe
,
opipe
,
length
);
if
(
result
!=
USB_STOR_TRANSPORT_GOOD
)
return
result
;
US_DEBUGP
(
"FCM: Waiting for status
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
US_DEBUG
(
pdump
((
void
*
)
fst
,
partial
));
if
(
partial
!=
4
||
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
ERR_STAT
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
if
((
fst
->
Reason
&
3
)
!=
3
)
{
US_DEBUGP
(
"Drive seems still hungry
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
US_DEBUGP
(
"Transfer happy
\n
"
);
break
;
case
SCSI_DATA_WRITE
:
/* Make sure the status indicates that the device wants to
* send us data. */
/* !!IMPLEMENT!! */
result
=
freecom_writedata
(
srb
,
us
,
ipipe
,
opipe
,
length
);
if
(
result
!=
USB_STOR_TRANSPORT_GOOD
)
return
result
;
US_DEBUGP
(
"FCM: Waiting for status
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
if
(
partial
!=
4
||
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
ERR_STAT
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
if
((
fst
->
Reason
&
3
)
!=
3
)
{
US_DEBUGP
(
"Drive seems still hungry
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
US_DEBUGP
(
"Transfer happy
\n
"
);
break
;
case
SCSI_DATA_NONE
:
/* Easy, do nothing. */
break
;
default:
US_DEBUGP
(
"freecom unimplemented direction: %d
\n
"
,
us
->
srb
->
sc_data_direction
);
// Return fail, SCSI seems to handle this better.
return
USB_STOR_TRANSPORT_FAILED
;
break
;
}
return
USB_STOR_TRANSPORT_GOOD
;
if
(
partial
!=
4
||
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
ERR_STAT
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
if
((
fst
->
Reason
&
3
)
!=
3
)
{
US_DEBUGP
(
"Drive seems still hungry
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
US_DEBUGP
(
"Transfer happy
\n
"
);
break
;
case
SCSI_DATA_WRITE
:
/* Make sure the status indicates that the device wants to
* send us data. */
/* !!IMPLEMENT!! */
result
=
freecom_writedata
(
srb
,
us
,
ipipe
,
opipe
,
length
);
if
(
result
!=
USB_STOR_TRANSPORT_GOOD
)
return
result
;
US_DEBUGP
(
"FCM: Waiting for status
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
ipipe
,
fst
,
FCM_PACKET_LENGTH
,
&
partial
);
if
(
partial
!=
4
||
result
>
USB_STOR_XFER_SHORT
)
return
USB_STOR_TRANSPORT_ERROR
;
if
((
fst
->
Status
&
ERR_STAT
)
!=
0
)
{
US_DEBUGP
(
"operation failed
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
if
((
fst
->
Reason
&
3
)
!=
3
)
{
US_DEBUGP
(
"Drive seems still hungry
\n
"
);
return
USB_STOR_TRANSPORT_FAILED
;
}
US_DEBUGP
(
"Transfer happy
\n
"
);
break
;
case
SCSI_DATA_NONE
:
/* Easy, do nothing. */
break
;
default:
US_DEBUGP
(
"freecom unimplemented direction: %d
\n
"
,
us
->
srb
->
sc_data_direction
);
// Return fail, SCSI seems to handle this better.
return
USB_STOR_TRANSPORT_FAILED
;
break
;
}
return
USB_STOR_TRANSPORT_GOOD
;
}
int
freecom_init
(
struct
us_data
*
us
)
{
int
result
;
int
result
;
char
buffer
[
33
];
/* Allocate a buffer for us. The upper usb transport code will
* free this for us when cleaning up. */
if
(
us
->
extra
==
NULL
)
{
us
->
extra
=
kmalloc
(
sizeof
(
struct
freecom_udata
),
GFP_KERNEL
);
if
(
us
->
extra
==
NULL
)
{
US_DEBUGP
(
"Out of memory
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
}
/* Allocate a buffer for us. The upper usb transport code will
* free this for us when cleaning up. */
if
(
us
->
extra
==
NULL
)
{
us
->
extra
=
kmalloc
(
sizeof
(
struct
freecom_udata
),
GFP_KERNEL
);
if
(
us
->
extra
==
NULL
)
{
US_DEBUGP
(
"Out of memory
\n
"
);
return
USB_STOR_TRANSPORT_ERROR
;
}
}
result
=
usb_control_msg
(
us
->
pusb_dev
,
us
->
recv_ctrl_pipe
,
0x4c
,
0xc0
,
0x4346
,
0x0
,
buffer
,
0x20
,
3
*
HZ
);
...
...
@@ -424,15 +424,15 @@ freecom_init (struct us_data *us)
/* wait 3 seconds */
mdelay
(
3
*
1000
);
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
}
int
usb_stor_freecom_reset
(
struct
us_data
*
us
)
{
printk
(
KERN_CRIT
"freecom reset called
\n
"
);
printk
(
KERN_CRIT
"freecom reset called
\n
"
);
/* We don't really have this feature. */
return
FAILED
;
/* We don't really have this feature. */
return
FAILED
;
}
#ifdef CONFIG_USB_STORAGE_DEBUG
...
...
drivers/usb/storage/isd200.c
View file @
20b397bb
...
...
@@ -34,11 +34,11 @@
* 2002-10-19: Removed the specialized transfer routines.
* (Alan Stern <stern@rowland.harvard.edu>)
* 2001-02-24: Removed lots of duplicate code and simplified the structure.
*
(bjorn@haxx.se)
*
(bjorn@haxx.se)
* 2002-01-16: Fixed endianness bug so it works on the ppc arch.
*
(Luc Saillard <luc@saillard.org>)
*
(Luc Saillard <luc@saillard.org>)
* 2002-01-17: All bitfields removed.
*
(bjorn@haxx.se)
*
(bjorn@haxx.se)
*/
...
...
@@ -59,14 +59,14 @@
/* Timeout defines (in Seconds) */
#define ISD200_ENUM_BSY_TIMEOUT
35
#define ISD200_ENUM_BSY_TIMEOUT
35
#define ISD200_ENUM_DETECT_TIMEOUT 30
#define ISD200_DEFAULT_TIMEOUT
30
#define ISD200_DEFAULT_TIMEOUT
30
/* device flags */
#define DF_ATA_DEVICE
0x0001
#define DF_MEDIA_STATUS_ENABLED
0x0002
#define DF_REMOVABLE_MEDIA
0x0004
#define DF_ATA_DEVICE
0x0001
#define DF_MEDIA_STATUS_ENABLED
0x0002
#define DF_REMOVABLE_MEDIA
0x0004
/* capability bit definitions */
#define CAPABILITY_DMA 0x01
...
...
@@ -82,46 +82,46 @@
#define ATA_ADDRESS_DEVHEAD_SLAVE 0x10
/* Action Select bits */
#define ACTION_SELECT_0
0x01
#define ACTION_SELECT_1
0x02
#define ACTION_SELECT_2
0x04
#define ACTION_SELECT_3
0x08
#define ACTION_SELECT_4
0x10
#define ACTION_SELECT_5
0x20
#define ACTION_SELECT_6
0x40
#define ACTION_SELECT_7
0x80
#define ACTION_SELECT_0
0x01
#define ACTION_SELECT_1
0x02
#define ACTION_SELECT_2
0x04
#define ACTION_SELECT_3
0x08
#define ACTION_SELECT_4
0x10
#define ACTION_SELECT_5
0x20
#define ACTION_SELECT_6
0x40
#define ACTION_SELECT_7
0x80
/* Register Select bits */
#define REG_ALTERNATE_STATUS
0x01
#define REG_DEVICE_CONTROL
0x01
#define REG_ERROR
0x02
#define REG_FEATURES
0x02
#define REG_SECTOR_COUNT
0x04
#define REG_SECTOR_NUMBER
0x08
#define REG_CYLINDER_LOW
0x10
#define REG_CYLINDER_HIGH
0x20
#define REG_DEVICE_HEAD
0x40
#define REG_STATUS
0x80
#define REG_COMMAND
0x80
#define REG_ALTERNATE_STATUS
0x01
#define REG_DEVICE_CONTROL
0x01
#define REG_ERROR
0x02
#define REG_FEATURES
0x02
#define REG_SECTOR_COUNT
0x04
#define REG_SECTOR_NUMBER
0x08
#define REG_CYLINDER_LOW
0x10
#define REG_CYLINDER_HIGH
0x20
#define REG_DEVICE_HEAD
0x40
#define REG_STATUS
0x80
#define REG_COMMAND
0x80
/* ATA error definitions not in <linux/hdreg.h> */
#define ATA_ERROR_MEDIA_CHANGE
0x20
#define ATA_ERROR_MEDIA_CHANGE
0x20
/* ATA command definitions not in <linux/hdreg.h> */
#define ATA_COMMAND_GET_MEDIA_STATUS
0xDA
#define ATA_COMMAND_MEDIA_EJECT
0xED
#define ATA_COMMAND_GET_MEDIA_STATUS
0xDA
#define ATA_COMMAND_MEDIA_EJECT
0xED
/* ATA drive control definitions */
#define ATA_DC_DISABLE_INTERRUPTS
0x02
#define ATA_DC_RESET_CONTROLLER
0x04
#define ATA_DC_REENABLE_CONTROLLER
0x00
#define ATA_DC_DISABLE_INTERRUPTS
0x02
#define ATA_DC_RESET_CONTROLLER
0x04
#define ATA_DC_REENABLE_CONTROLLER
0x00
/*
* General purpose return codes
*/
#define ISD200_ERROR
-1
#define ISD200_GOOD
0
#define ISD200_ERROR
-1
#define ISD200_GOOD
0
/*
* Transport return codes
...
...
@@ -162,7 +162,7 @@ union ata_cdb {
unsigned
char
WriteData1F7
;
unsigned
char
Reserved
[
3
];
}
generic
;
struct
{
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte1
;
...
...
@@ -180,7 +180,7 @@ union ata_cdb {
unsigned
char
Reserved
[
3
];
}
read
;
struct
{
struct
{
unsigned
char
SignatureByte0
;
unsigned
char
SignatureByte1
;
unsigned
char
ActionSelect
;
...
...
@@ -211,8 +211,8 @@ union ata_cdb {
/*
* DeviceType field
*/
#define DIRECT_ACCESS_DEVICE
0x00
/* disks */
#define DEVICE_REMOVABLE
0x80
#define DIRECT_ACCESS_DEVICE
0x00
/* disks */
#define DEVICE_REMOVABLE
0x80
struct
inquiry_data
{
unsigned
char
DeviceType
;
...
...
@@ -240,9 +240,9 @@ struct inquiry_data {
* ISD200 CONFIG data struct
*/
#define ATACFG_TIMING
0x0f
#define ATACFG_TIMING
0x0f
#define ATACFG_ATAPI_RESET 0x10
#define ATACFG_MASTER
0x20
#define ATACFG_MASTER
0x20
#define ATACFG_BLOCKSIZE 0xa0
#define ATACFGE_LAST_LUN 0x07
...
...
@@ -255,12 +255,12 @@ struct inquiry_data {
#define CFG_CAPABILITY_SRST 0x01
struct
isd200_config
{
unsigned
char
EventNotification
;
unsigned
char
ExternalClock
;
unsigned
char
ATAInitTimeout
;
unsigned
char
EventNotification
;
unsigned
char
ExternalClock
;
unsigned
char
ATAInitTimeout
;
unsigned
char
ATAConfig
;
unsigned
char
ATAMajorCommand
;
unsigned
char
ATAMinorCommand
;
unsigned
char
ATAMajorCommand
;
unsigned
char
ATAMinorCommand
;
unsigned
char
ATAExtraConfig
;
unsigned
char
Capability
;
}
__attribute__
((
packed
));
...
...
@@ -309,7 +309,7 @@ struct read_block_limits {
* Sense Data Format
*/
#define SENSE_ERRCODE
0x7f
#define SENSE_ERRCODE
0x7f
#define SENSE_ERRCODE_VALID 0x80
#define SENSE_FLAG_SENSE_KEY 0x0f
#define SENSE_FLAG_BAD_LENGTH 0x20
...
...
@@ -319,13 +319,13 @@ struct sense_data {
unsigned
char
ErrorCode
;
unsigned
char
SegmentNumber
;
unsigned
char
Flags
;
unsigned
char
Information
[
4
];
unsigned
char
AdditionalSenseLength
;
unsigned
char
CommandSpecificInformation
[
4
];
unsigned
char
AdditionalSenseCode
;
unsigned
char
AdditionalSenseCodeQualifier
;
unsigned
char
FieldReplaceableUnitCode
;
unsigned
char
SenseKeySpecific
[
3
];
unsigned
char
Information
[
4
];
unsigned
char
AdditionalSenseLength
;
unsigned
char
CommandSpecificInformation
[
4
];
unsigned
char
AdditionalSenseCode
;
unsigned
char
AdditionalSenseCodeQualifier
;
unsigned
char
FieldReplaceableUnitCode
;
unsigned
char
SenseKeySpecific
[
3
];
}
__attribute__
((
packed
));
/*
...
...
@@ -340,18 +340,18 @@ struct sense_data {
/**************************************************************************
* isd200_build_sense
*
*
* Builds an artificial sense buffer to report the results of a
* failed command.
*
*
* RETURNS:
* void
*/
*/
void
isd200_build_sense
(
struct
us_data
*
us
,
Scsi_Cmnd
*
srb
)
{
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
struct
sense_data
*
buf
=
(
struct
sense_data
*
)
&
srb
->
sense_buffer
[
0
];
unsigned
char
error
=
info
->
ATARegs
[
IDE_ERROR_OFFSET
];
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
struct
sense_data
*
buf
=
(
struct
sense_data
*
)
&
srb
->
sense_buffer
[
0
];
unsigned
char
error
=
info
->
ATARegs
[
IDE_ERROR_OFFSET
];
if
(
error
&
ATA_ERROR_MEDIA_CHANGE
)
{
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
...
...
@@ -359,31 +359,31 @@ void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
buf
->
Flags
=
UNIT_ATTENTION
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
MCR_ERR
)
{
}
else
if
(
error
&
MCR_ERR
)
{
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
Flags
=
UNIT_ATTENTION
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
TRK0_ERR
)
{
}
else
if
(
error
&
TRK0_ERR
)
{
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
Flags
=
NOT_READY
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
if
(
error
&
ECC_ERR
)
{
}
else
if
(
error
&
ECC_ERR
)
{
buf
->
ErrorCode
=
0x70
|
SENSE_ERRCODE_VALID
;
buf
->
AdditionalSenseLength
=
0xb
;
buf
->
Flags
=
DATA_PROTECT
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
else
{
}
else
{
buf
->
ErrorCode
=
0
;
buf
->
AdditionalSenseLength
=
0
;
buf
->
Flags
=
0
;
buf
->
AdditionalSenseCode
=
0
;
buf
->
AdditionalSenseCodeQualifier
=
0
;
}
}
}
...
...
@@ -430,8 +430,8 @@ static int isd200_action( struct us_data *us, int action,
case
ACTION_ENUM
:
US_DEBUGP
(
" isd200_action(ENUM,0x%02x)
\n
"
,
value
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
|
ACTION_SELECT_5
;
ACTION_SELECT_3
|
ACTION_SELECT_4
|
ACTION_SELECT_5
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_HEAD
;
ata
.
write
.
DeviceHeadByte
=
value
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
...
...
@@ -440,7 +440,7 @@ static int isd200_action( struct us_data *us, int action,
case
ACTION_RESET
:
US_DEBUGP
(
" isd200_action(RESET)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_CONTROL
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_RESET_CONTROLLER
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
...
...
@@ -449,7 +449,7 @@ static int isd200_action( struct us_data *us, int action,
case
ACTION_REENABLE
:
US_DEBUGP
(
" isd200_action(REENABLE)
\n
"
);
ata
.
generic
.
ActionSelect
=
ACTION_SELECT_1
|
ACTION_SELECT_2
|
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ACTION_SELECT_3
|
ACTION_SELECT_4
;
ata
.
generic
.
RegisterSelect
=
REG_DEVICE_CONTROL
;
ata
.
write
.
DeviceControlByte
=
ATA_DC_REENABLE_CONTROLLER
;
srb
.
sc_data_direction
=
SCSI_DATA_NONE
;
...
...
@@ -493,12 +493,12 @@ static int isd200_action( struct us_data *us, int action,
/**************************************************************************
* isd200_read_regs
*
*
* Read ATA Registers
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_read_regs
(
struct
us_data
*
us
)
{
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
...
...
@@ -512,10 +512,10 @@ int isd200_read_regs( struct us_data *us )
if
(
transferStatus
!=
ISD200_TRANSPORT_GOOD
)
{
US_DEBUGP
(
" Error reading ATA registers
\n
"
);
retStatus
=
ISD200_ERROR
;
}
else
{
}
else
{
US_DEBUGP
(
" Got ATA Register[IDE_ERROR_OFFSET] = 0x%x
\n
"
,
info
->
ATARegs
[
IDE_ERROR_OFFSET
]);
}
}
return
retStatus
;
}
...
...
@@ -649,12 +649,12 @@ static void isd200_log_config( struct isd200_info* info )
/**************************************************************************
* isd200_write_config
*
*
* Write the ISD200 Configuraton data
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_write_config
(
struct
us_data
*
us
)
{
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
...
...
@@ -669,21 +669,21 @@ int isd200_write_config( struct us_data *us )
/* let's send the command via the control pipe */
result
=
usb_stor_ctrl_transfer
(
us
,
us
->
send_ctrl_pipe
,
0x01
,
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
|
USB_DIR_OUT
,
0x0000
,
0x0002
,
(
void
*
)
&
info
->
ConfigData
,
sizeof
(
info
->
ConfigData
));
us
,
us
->
send_ctrl_pipe
,
0x01
,
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
|
USB_DIR_OUT
,
0x0000
,
0x0002
,
(
void
*
)
&
info
->
ConfigData
,
sizeof
(
info
->
ConfigData
));
if
(
result
>=
0
)
{
US_DEBUGP
(
" ISD200 Config Data was written successfully
\n
"
);
}
else
{
}
else
{
US_DEBUGP
(
" Request to write ISD200 Config Data failed!
\n
"
);
retStatus
=
ISD200_ERROR
;
}
}
US_DEBUGP
(
"Leaving isd200_write_config %08X
\n
"
,
retStatus
);
return
retStatus
;
...
...
@@ -692,12 +692,12 @@ int isd200_write_config( struct us_data *us )
/**************************************************************************
* isd200_read_config
*
*
* Reads the ISD200 Configuraton data
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_read_config
(
struct
us_data
*
us
)
{
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
...
...
@@ -707,17 +707,17 @@ int isd200_read_config( struct us_data *us )
US_DEBUGP
(
"Entering isd200_read_config
\n
"
);
/* read the configuration information from ISD200. Use this to */
/* determine what the special ATA CDB bytes are.
*/
/* determine what the special ATA CDB bytes are.
*/
result
=
usb_stor_ctrl_transfer
(
us
,
us
->
recv_ctrl_pipe
,
0x02
,
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
|
USB_DIR_IN
,
0x0000
,
0x0002
,
(
void
*
)
&
info
->
ConfigData
,
sizeof
(
info
->
ConfigData
));
us
,
us
->
recv_ctrl_pipe
,
0x02
,
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
|
USB_DIR_IN
,
0x0000
,
0x0002
,
(
void
*
)
&
info
->
ConfigData
,
sizeof
(
info
->
ConfigData
));
if
(
result
>=
0
)
{
...
...
@@ -725,10 +725,10 @@ int isd200_read_config( struct us_data *us )
#ifdef CONFIG_USB_STORAGE_DEBUG
isd200_log_config
(
info
);
#endif
}
else
{
}
else
{
US_DEBUGP
(
" Request to get ISD200 Config Data failed!
\n
"
);
retStatus
=
ISD200_ERROR
;
}
}
US_DEBUGP
(
"Leaving isd200_read_config %08X
\n
"
,
retStatus
);
return
retStatus
;
...
...
@@ -737,12 +737,12 @@ int isd200_read_config( struct us_data *us )
/**************************************************************************
* isd200_atapi_soft_reset
*
*
* Perform an Atapi Soft Reset on the device
*
* RETURNS:
* NT status code
*/
*/
int
isd200_atapi_soft_reset
(
struct
us_data
*
us
)
{
int
retStatus
=
ISD200_GOOD
;
...
...
@@ -754,7 +754,7 @@ int isd200_atapi_soft_reset( struct us_data *us )
if
(
transferStatus
!=
ISD200_TRANSPORT_GOOD
)
{
US_DEBUGP
(
" Error issuing Atapi Soft Reset
\n
"
);
retStatus
=
ISD200_ERROR
;
}
}
US_DEBUGP
(
"Leaving isd200_atapi_soft_reset %08X
\n
"
,
retStatus
);
return
retStatus
;
...
...
@@ -763,12 +763,12 @@ int isd200_atapi_soft_reset( struct us_data *us )
/**************************************************************************
* isd200_srst
*
*
* Perform an SRST on the device
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_srst
(
struct
us_data
*
us
)
{
int
retStatus
=
ISD200_GOOD
;
...
...
@@ -782,7 +782,7 @@ int isd200_srst( struct us_data *us )
if
(
transferStatus
!=
ISD200_TRANSPORT_GOOD
)
{
US_DEBUGP
(
" Error issuing SRST
\n
"
);
retStatus
=
ISD200_ERROR
;
}
else
{
}
else
{
/* delay 10ms to give the drive a chance to see it */
wait_ms
(
10
);
...
...
@@ -794,7 +794,7 @@ int isd200_srst( struct us_data *us )
/* delay 50ms to give the drive a chance to recover after SRST */
wait_ms
(
50
);
}
}
}
US_DEBUGP
(
"Leaving isd200_srst %08X
\n
"
,
retStatus
);
return
retStatus
;
...
...
@@ -803,13 +803,13 @@ int isd200_srst( struct us_data *us )
/**************************************************************************
* isd200_try_enum
*
*
* Helper function for isd200_manual_enum(). Does ENUM and READ_STATUS
* and tries to analyze the status registers
*
* RETURNS:
* ISD status code
*/
*/
static
int
isd200_try_enum
(
struct
us_data
*
us
,
unsigned
char
master_slave
,
int
detect
)
{
...
...
@@ -908,13 +908,13 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/**************************************************************************
* isd200_manual_enum
*
*
* Determines if the drive attached is an ATA or ATAPI and if it is a
* master or slave.
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_manual_enum
(
struct
us_data
*
us
)
{
struct
isd200_info
*
info
=
(
struct
isd200_info
*
)
us
->
extra
;
...
...
@@ -1078,15 +1078,15 @@ int isd200_get_inquiry_data( struct us_data *us )
us
->
proto_handler
=
usb_stor_transparent_scsi_command
;
US_DEBUGP
(
"Protocol changed to: %s
\n
"
,
us
->
protocol_name
);
/* Free driver structure */
/* Free driver structure */
if
(
us
->
extra
!=
NULL
)
{
kfree
(
us
->
extra
);
us
->
extra
=
NULL
;
us
->
extra_destructor
=
NULL
;
}
}
}
}
US_DEBUGP
(
"Leaving isd200_get_inquiry_data %08X
\n
"
,
retStatus
);
...
...
@@ -1096,12 +1096,12 @@ int isd200_get_inquiry_data( struct us_data *us )
/**************************************************************************
* isd200_data_copy
*
*
* Copy data into the srb request buffer. Use scatter gather if required.
*
* RETURNS:
* void
*/
*/
void
isd200_data_copy
(
Scsi_Cmnd
*
srb
,
char
*
src
,
int
length
)
{
unsigned
int
len
=
length
;
...
...
@@ -1150,13 +1150,13 @@ void isd200_data_copy(Scsi_Cmnd *srb, char * src, int length)
/**************************************************************************
* isd200_scsi_to_ata
*
*
* Translate SCSI commands to ATA commands.
*
* RETURNS:
* TRUE if the command needs to be sent to the transport layer
* FALSE otherwise
*/
*/
int
isd200_scsi_to_ata
(
Scsi_Cmnd
*
srb
,
struct
us_data
*
us
,
union
ata_cdb
*
ataCdb
)
{
...
...
@@ -1321,7 +1321,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
if
(
info
->
DeviceFlags
&
DF_REMOVABLE_MEDIA
)
{
US_DEBUGP
(
" srb->cmnd[4] = 0x%X
\n
"
,
srb
->
cmnd
[
4
]);
ataCdb
->
generic
.
SignatureByte0
=
info
->
ConfigData
.
ATAMajorCommand
;
ataCdb
->
generic
.
SignatureByte1
=
info
->
ConfigData
.
ATAMinorCommand
;
ataCdb
->
generic
.
TransferBlockSize
=
1
;
...
...
@@ -1378,12 +1378,12 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
/**************************************************************************
* isd200_init_info
*
*
* Allocates (if necessary) and initializes the driver structure.
*
* RETURNS:
* ISD status code
*/
*/
int
isd200_init_info
(
struct
us_data
*
us
)
{
int
retStatus
=
ISD200_GOOD
;
...
...
@@ -1394,11 +1394,11 @@ int isd200_init_info(struct us_data *us)
US_DEBUGP
(
"ERROR - kmalloc failure
\n
"
);
retStatus
=
ISD200_ERROR
;
}
}
}
if
(
retStatus
==
ISD200_GOOD
)
{
memset
(
us
->
extra
,
0
,
sizeof
(
struct
isd200_info
));
}
}
return
(
retStatus
);
}
...
...
@@ -1415,14 +1415,14 @@ int isd200_Initialization(struct us_data *us)
if
(
isd200_init_info
(
us
)
==
ISD200_ERROR
)
{
US_DEBUGP
(
"ERROR Initializing ISD200 Info struct
\n
"
);
}
else
{
}
else
{
/* Get device specific data */
if
(
isd200_get_inquiry_data
(
us
)
!=
ISD200_GOOD
)
US_DEBUGP
(
"ISD200 Initialization Failure
\n
"
);
else
US_DEBUGP
(
"ISD200 Initialization complete
\n
"
);
}
}
return
0
;
}
...
...
drivers/usb/storage/protocol.h
View file @
20b397bb
...
...
@@ -53,7 +53,7 @@
#define US_SC_UFI 0x04
/* Floppy */
#define US_SC_8070 0x05
/* Removable media */
#define US_SC_SCSI 0x06
/* Transparent */
#define US_SC_ISD200 0x07
/* ISD200 ATA */
#define US_SC_ISD200 0x07
/* ISD200 ATA */
#define US_SC_MIN US_SC_RBC
#define US_SC_MAX US_SC_ISD200
...
...
drivers/usb/storage/scsiglue.c
View file @
20b397bb
...
...
@@ -50,23 +50,25 @@
#include "transport.h"
#include <linux/slab.h>
#include <linux/module.h>
/***********************************************************************
* 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"
;
}
#if 0
/* detect a virtual adapter (always works)
* Synchronization: 2.4: with the io_request_lock
* 2.5: no locks.
* fortunately we don't care.
* */
static
int
detect
(
struct
SHT
*
sht
)
static int
usb_storage_
detect(struct SHT *sht)
{
struct us_data *us;
char local_name[32];
...
...
@@ -109,7 +111,7 @@ static int detect(struct SHT *sht)
* the driver and we're doing each virtual host in turn, not in parallel
* 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];
...
...
@@ -132,18 +134,11 @@ static int release(struct Scsi_Host *psh)
/* we always have a successful release */
return 0;
}
/* run command */
static
int
command
(
Scsi_Cmnd
*
srb
)
{
US_DEBUGP
(
"Bad use of us_command
\n
"
);
return
DID_BAD_TARGET
<<
16
;
}
#endif
/* queue a command */
/* 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
];
...
...
@@ -168,7 +163,7 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
/* Command abort */
/* 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
];
...
...
@@ -187,7 +182,7 @@ static int command_abort( Scsi_Cmnd *srb )
/* This invokes the transport reset mechanism to reset the state of the
* device */
/* 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
];
int
result
;
...
...
@@ -202,11 +197,10 @@ static int device_reset( Scsi_Cmnd *srb )
/* lock the device pointers */
down
(
&
(
us
->
dev_semaphore
));
/* if the device was removed, then we're already reset */
if
(
!
(
us
->
flags
&
US_FL_DEV_ATTACHED
))
result
=
SUCCESS
;
else
result
=
us
->
transport_reset
(
us
);
/* do the reset */
result
=
us
->
transport_reset
(
us
);
/* unlock */
up
(
&
(
us
->
dev_semaphore
));
/* lock access to the state and clear it */
...
...
@@ -219,31 +213,26 @@ static int device_reset( Scsi_Cmnd *srb )
* disconnect/reconnect for all drivers which have claimed
* interfaces, including ourself. */
/* 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
result
;
struct
usb_device
*
pusb_dev_save
;
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP
(
"bus_reset() called
\n
"
);
scsi_unlock
(
srb
->
device
->
host
);
/* 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
);
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
/* 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
);
if
(
result
<
0
)
{
scsi_lock
(
srb
->
device
->
host
);
...
...
@@ -253,9 +242,9 @@ static int bus_reset( Scsi_Cmnd *srb )
/* FIXME: This needs to lock out driver probing while it's working
* or we can have race conditions */
/* 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
=
&
pusb_dev_save
->
actconfig
->
interface
[
i
];
&
us
->
pusb_dev
->
actconfig
->
interface
[
i
];
/* if this is an unclaimed interface, skip it */
if
(
!
intf
->
driver
)
{
...
...
@@ -274,14 +263,6 @@ static int bus_reset( Scsi_Cmnd *srb )
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
***********************************************************************/
...
...
@@ -291,29 +272,23 @@ static int host_reset( Scsi_Cmnd *srb )
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
static
int
proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
)
static
int
usb_storage_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
)
{
struct
us_data
*
us
;
char
*
pos
=
buffer
;
struct
Scsi_Host
*
hostptr
;
/* if someone is sending us data, just throw it away */
if
(
inout
)
return
length
;
/* lock the data structures */
down
(
&
us_list_semaphore
);
/* find our data from hostno */
us
=
us_list
;
while
(
us
)
{
if
(
us
->
host_no
==
hostno
)
break
;
us
=
us
->
next
;
/* find our data from the given hostno */
hostptr
=
scsi_host_hn_get
(
hostno
);
if
(
!
hostptr
)
{
/* if we couldn't find it, we return an error */
return
-
ESRCH
;
}
/* release our lock on the data structures */
up
(
&
us_list_semaphore
);
us
=
(
struct
us_data
*
)
hostptr
->
hostdata
[
0
];
/* if we couldn't find it, we return an error */
if
(
!
us
)
{
...
...
@@ -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
(
" Transport: %s
\n
"
,
us
->
transport_name
);
/* show the GUID of the device */
SPRINTF
(
" GUID: "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
us
->
guid
));
SPRINTF
(
" Attached: %s
\n
"
,
(
us
->
flags
&
US_FL_DEV_ATTACHED
?
"Yes"
:
"No"
));
/* release the reference count on this host */
scsi_host_put
(
hostptr
);
/*
* 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,
}
/*
* this defines our
'host'
* this defines our
host template, with which we'll allocate hosts
*/
Scsi_Host_Template
usb_stor_host_template
=
{
.
name
=
"usb-storage"
,
.
proc_info
=
proc_info
,
.
info
=
host_info
,
.
detect
=
detect
,
.
release
=
release
,
.
command
=
command
,
.
queuecommand
=
queuecommand
,
.
eh_abort_handler
=
command_abort
,
.
eh_device_reset_handler
=
device_reset
,
.
eh_bus_reset_handler
=
bus_reset
,
.
eh_host_reset_handler
=
host_reset
,
.
can_queue
=
1
,
.
this_id
=
-
1
,
.
sg_tablesize
=
SG_ALL
,
.
cmd_per_lun
=
1
,
.
present
=
0
,
.
unchecked_isa_dma
=
FALSE
,
.
use_clustering
=
TRUE
,
.
emulated
=
TRUE
struct
SHT
usb_stor_host_template
=
{
/* basic userland interface stuff */
.
name
=
"usb-storage"
,
.
proc_name
=
"usb-storage"
,
.
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
,
/* unknown initiator id */
.
this_id
=
-
1
,
/* no limit on commands */
.
max_sectors
=
0
,
/* pre- and post- device scan functions */
.
slave_alloc
=
NULL
,
.
slave_configure
=
NULL
,
.
slave_destroy
=
NULL
,
/* lots of sg segments can be handled */
.
sg_tablesize
=
SG_ALL
,
/* use 32-bit address space for DMA */
.
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
,
/* 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" */
...
...
drivers/usb/storage/scsiglue.h
View file @
20b397bb
...
...
@@ -47,7 +47,7 @@
extern
unsigned
char
usb_stor_sense_notready
[
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_scsiSense6to10
(
Scsi_Cmnd
*
);
...
...
drivers/usb/storage/transport.h
View file @
20b397bb
...
...
@@ -55,8 +55,7 @@
#define US_PR_SCM_ATAPI 0x80
/* SCM-ATAPI bridge */
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
#define US_PR_EUSB_SDDR09 0x81
/* SCM-SCSI bridge for
SDDR-09 */
#define US_PR_EUSB_SDDR09 0x81
/* SCM-SCSI bridge for SDDR-09 */
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
#define US_PR_SDDR55 0x82
/* SDDR-55 (made up) */
...
...
@@ -64,15 +63,15 @@
#define US_PR_DPCM_USB 0xf0
/* Combination CB/SDDR09 */
#ifdef CONFIG_USB_STORAGE_FREECOM
#define US_PR_FREECOM 0xf1
/* Freecom */
#define US_PR_FREECOM 0xf1
/* Freecom */
#endif
#ifdef CONFIG_USB_STORAGE_DATAFAB
#define US_PR_DATAFAB 0xf2
/* Datafab chipsets */
#define US_PR_DATAFAB 0xf2
/* Datafab chipsets */
#endif
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
#define US_PR_JUMPSHOT 0xf3
/* Lexar Jumpshot */
#define US_PR_JUMPSHOT 0xf3
/* Lexar Jumpshot */
#endif
/*
...
...
@@ -118,10 +117,10 @@ struct bulk_cs_wrap {
* usb_stor_bulk_transfer_xxx() return codes, in order of severity
*/
#define USB_STOR_XFER_GOOD
0
/* good transfer */
#define USB_STOR_XFER_SHORT
1
/* transfered less than expected */
#define USB_STOR_XFER_STALLED
2
/* endpoint stalled
*/
#define USB_STOR_XFER_ERROR
3
/* transfer died in the middle */
#define USB_STOR_XFER_GOOD
0
/* good transfer */
#define USB_STOR_XFER_SHORT
1
/* transfered less than expected */
#define USB_STOR_XFER_STALLED
2
/* endpoint stalled
*/
#define USB_STOR_XFER_ERROR
3
/* transfer died in the middle */
/*
* Transport return codes
...
...
drivers/usb/storage/unusual_devs.h
View file @
20b397bb
...
...
@@ -264,7 +264,7 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
/* Submitted by Nathan Babb <nathan@lexi.com> */
UNUSUAL_DEV
(
0x054c
,
0x006d
,
0x0000
,
0x9999
,
"Sony"
,
"Sony"
,
"PEG Mass Storage"
,
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
...
...
@@ -546,10 +546,10 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
/* aeb */
UNUSUAL_DEV
(
0x090c
,
0x1132
,
0x0000
,
0xffff
,
"Feiya"
,
"5-in-1 Card Reader"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_CAPACITY
),
"Feiya"
,
"5-in-1 Card Reader"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_CAPACITY
),
UNUSUAL_DEV
(
0x097a
,
0x0001
,
0x0000
,
0x0001
,
"Minds@Work"
,
...
...
drivers/usb/storage/usb.c
View file @
20b397bb
...
...
@@ -93,16 +93,6 @@ MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
MODULE_DESCRIPTION
(
"USB Mass Storage driver for Linux"
);
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
,
const
struct
usb_device_id
*
id
);
...
...
@@ -319,7 +309,7 @@ static int usb_stor_control_thread(void * __us)
spin_unlock_irq
(
&
current
->
sig
->
siglock
);
/* set our name for identification purposes */
sprintf
(
current
->
comm
,
"usb-storage
-%d"
,
us
->
host_number
);
sprintf
(
current
->
comm
,
"usb-storage
"
);
unlock_kernel
();
...
...
@@ -395,35 +385,6 @@ static int usb_stor_control_thread(void * __us)
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
* their inquiry data */
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
...
...
@@ -547,7 +508,6 @@ static void usb_stor_deallocate_urbs(struct us_data *ss)
}
/* mark the device as gone */
ss
->
flags
&=
~
US_FL_DEV_ATTACHED
;
usb_put_dev
(
ss
->
pusb_dev
);
ss
->
pusb_dev
=
NULL
;
}
...
...
@@ -563,12 +523,10 @@ static int storage_probe(struct usb_interface *intf,
char
mf
[
USB_STOR_STRING_LEN
];
/* manufacturer */
char
prod
[
USB_STOR_STRING_LEN
];
/* product */
char
serial
[
USB_STOR_STRING_LEN
];
/* serial number */
GUID
(
guid
);
/* Global Unique Identifier */
unsigned
int
flags
;
struct
us_unusual_dev
*
unusual_dev
;
struct
us_data
*
ss
=
NULL
;
int
result
;
int
new_device
=
0
;
/* these are temporary copies -- we test on these, then put them
* in the us-data structure
...
...
@@ -676,8 +634,7 @@ static int storage_probe(struct usb_interface *intf,
/* At this point, we've decided to try to use the device */
usb_get_dev
(
dev
);
/* clear the GUID and fetch the strings */
GUID_CLEAR
(
guid
);
/* fetch the strings */
if
(
dev
->
descriptor
.
iManufacturer
)
usb_string
(
dev
,
dev
->
descriptor
.
iManufacturer
,
mf
,
sizeof
(
mf
));
...
...
@@ -688,346 +645,277 @@ static int storage_probe(struct usb_interface *intf,
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
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"
);
/* New device -- allocate memory and initialize */
if
((
ss
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
struct
us_data
),
GFP_KERNEL
))
==
NULL
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
usb_put_dev
(
dev
);
return
-
ENOMEM
;
}
/*
* 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
&
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
/* Initialize the mutexes only when the struct is new */
init_completion
(
&
(
ss
->
notify
));
init_MUTEX_LOCKED
(
&
(
ss
->
dev_semaphore
));
/* copy over the subclass and protocol data */
ss
->
subclass
=
subclass
;
ss
->
protocol
=
protocol
;
ss
->
flags
=
flags
;
ss
->
unusual_dev
=
unusual_dev
;
/* 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_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
;
}
ss
->
ep_bInterval
=
ep_int
->
bInterval
;
}
else
ss
->
ep_int
=
ss
->
ep_bInterval
=
0
;
/* establish the connection to the new device */
ss
->
ifnum
=
ifnum
;
ss
->
pusb_dev
=
dev
;
/* copy over the identifiying strings */
strncpy
(
ss
->
vendor
,
mf
,
USB_STOR_STRING_LEN
);
strncpy
(
ss
->
product
,
prod
,
USB_STOR_STRING_LEN
);
strncpy
(
ss
->
serial
,
serial
,
USB_STOR_STRING_LEN
);
if
(
strlen
(
ss
->
vendor
)
==
0
)
{
if
(
unusual_dev
->
vendorName
)
strncpy
(
ss
->
vendor
,
unusual_dev
->
vendorName
,
USB_STOR_STRING_LEN
);
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 */
US_DEBUGP
(
"New GUID "
GUID_FORMAT
"
\n
"
,
GUID_ARGS
(
guid
));
if
((
ss
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
struct
us_data
),
GFP_KERNEL
))
==
NULL
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
usb_put_dev
(
dev
);
return
-
ENOMEM
;
}
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
new_device
=
1
;
/* Initialize the mutexes only when the struct is new */
init_completion
(
&
(
ss
->
notify
));
init_MUTEX_LOCKED
(
&
(
ss
->
dev_semaphore
));
/* copy over the subclass and protocol data */
ss
->
subclass
=
subclass
;
ss
->
protocol
=
protocol
;
ss
->
flags
=
flags
|
US_FL_DEV_ATTACHED
;
ss
->
unusual_dev
=
unusual_dev
;
/* 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
;
}
strncpy
(
ss
->
vendor
,
"Unknown"
,
USB_STOR_STRING_LEN
);
}
if
(
strlen
(
ss
->
product
)
==
0
)
{
if
(
unusual_dev
->
productName
)
strncpy
(
ss
->
product
,
unusual_dev
->
productName
,
USB_STOR_STRING_LEN
);
else
ss
->
ep_int
=
ss
->
ep_bInterval
=
0
;
/* establish the connection to the new device */
ss
->
ifnum
=
ifnum
;
ss
->
pusb_dev
=
dev
;
/* copy over the identifiying strings */
strncpy
(
ss
->
vendor
,
mf
,
USB_STOR_STRING_LEN
);
strncpy
(
ss
->
product
,
prod
,
USB_STOR_STRING_LEN
);
strncpy
(
ss
->
serial
,
serial
,
USB_STOR_STRING_LEN
);
if
(
strlen
(
ss
->
vendor
)
==
0
)
{
if
(
unusual_dev
->
vendorName
)
strncpy
(
ss
->
vendor
,
unusual_dev
->
vendorName
,
USB_STOR_STRING_LEN
);
else
strncpy
(
ss
->
vendor
,
"Unknown"
,
USB_STOR_STRING_LEN
);
}
if
(
strlen
(
ss
->
product
)
==
0
)
{
if
(
unusual_dev
->
productName
)
strncpy
(
ss
->
product
,
unusual_dev
->
productName
,
USB_STOR_STRING_LEN
);
else
strncpy
(
ss
->
product
,
"Unknown"
,
USB_STOR_STRING_LEN
);
}
if
(
strlen
(
ss
->
serial
)
==
0
)
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
* Again, this data is persistant across reattachments
*/
switch
(
ss
->
protocol
)
{
case
US_PR_CB
:
ss
->
transport_name
=
"Control/Bulk"
;
ss
->
transport
=
usb_stor_CB_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
7
;
break
;
case
US_PR_CBI
:
ss
->
transport_name
=
"Control/Bulk/Interrupt"
;
ss
->
transport
=
usb_stor_CBI_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
7
;
break
;
strncpy
(
ss
->
product
,
"Unknown"
,
USB_STOR_STRING_LEN
);
}
if
(
strlen
(
ss
->
serial
)
==
0
)
strncpy
(
ss
->
serial
,
"None"
,
USB_STOR_STRING_LEN
);
case
US_PR_BULK
:
ss
->
transport_name
=
"Bulk"
;
ss
->
transport
=
usb_stor_Bulk_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
usb_stor_Bulk_max_lun
(
ss
);
break
;
/*
* Set the handler pointers based on the protocol
* Again, this data is persistant across reattachments
*/
switch
(
ss
->
protocol
)
{
case
US_PR_CB
:
ss
->
transport_name
=
"Control/Bulk"
;
ss
->
transport
=
usb_stor_CB_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
7
;
break
;
case
US_PR_CBI
:
ss
->
transport_name
=
"Control/Bulk/Interrupt"
;
ss
->
transport
=
usb_stor_CBI_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
7
;
break
;
case
US_PR_BULK
:
ss
->
transport_name
=
"Bulk"
;
ss
->
transport
=
usb_stor_Bulk_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
usb_stor_Bulk_max_lun
(
ss
);
break
;
#ifdef CONFIG_USB_STORAGE_HP8200e
case
US_PR_SCM_ATAPI
:
ss
->
transport_name
=
"SCM/ATAPI"
;
ss
->
transport
=
hp8200e_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
1
;
break
;
case
US_PR_SCM_ATAPI
:
ss
->
transport_name
=
"SCM/ATAPI"
;
ss
->
transport
=
hp8200e_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
1
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
case
US_PR_EUSB_SDDR09
:
ss
->
transport_name
=
"EUSB/SDDR09"
;
ss
->
transport
=
sddr09_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
0
;
break
;
case
US_PR_EUSB_SDDR09
:
ss
->
transport_name
=
"EUSB/SDDR09"
;
ss
->
transport
=
sddr09_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
0
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
case
US_PR_SDDR55
:
ss
->
transport_name
=
"SDDR55"
;
ss
->
transport
=
sddr55_transport
;
ss
->
transport_reset
=
sddr55_reset
;
ss
->
max_lun
=
0
;
break
;
case
US_PR_SDDR55
:
ss
->
transport_name
=
"SDDR55"
;
ss
->
transport
=
sddr55_transport
;
ss
->
transport_reset
=
sddr55_reset
;
ss
->
max_lun
=
0
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_DPCM
case
US_PR_DPCM_USB
:
ss
->
transport_name
=
"Control/Bulk-EUSB/SDDR09"
;
ss
->
transport
=
dpcm_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
1
;
break
;
case
US_PR_DPCM_USB
:
ss
->
transport_name
=
"Control/Bulk-EUSB/SDDR09"
;
ss
->
transport
=
dpcm_transport
;
ss
->
transport_reset
=
usb_stor_CB_reset
;
ss
->
max_lun
=
1
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_FREECOM
case
US_PR_FREECOM
:
ss
->
transport_name
=
"Freecom"
;
ss
->
transport
=
freecom_transport
;
ss
->
transport_reset
=
usb_stor_freecom_reset
;
ss
->
max_lun
=
0
;
break
;
case
US_PR_FREECOM
:
ss
->
transport_name
=
"Freecom"
;
ss
->
transport
=
freecom_transport
;
ss
->
transport_reset
=
usb_stor_freecom_reset
;
ss
->
max_lun
=
0
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_DATAFAB
case
US_PR_DATAFAB
:
ss
->
transport_name
=
"Datafab Bulk-Only"
;
ss
->
transport
=
datafab_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
1
;
break
;
case
US_PR_DATAFAB
:
ss
->
transport_name
=
"Datafab Bulk-Only"
;
ss
->
transport
=
datafab_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
1
;
break
;
#endif
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
case
US_PR_JUMPSHOT
:
ss
->
transport_name
=
"Lexar Jumpshot Control/Bulk"
;
ss
->
transport
=
jumpshot_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
1
;
break
;
case
US_PR_JUMPSHOT
:
ss
->
transport_name
=
"Lexar Jumpshot Control/Bulk"
;
ss
->
transport
=
jumpshot_transport
;
ss
->
transport_reset
=
usb_stor_Bulk_reset
;
ss
->
max_lun
=
1
;
break
;
#endif
default:
/* ss->transport_name = "Unknown"; */
goto
BadDevice
;
}
US_DEBUGP
(
"Transport: %s
\n
"
,
ss
->
transport_name
);
/* fix for single-lun devices */
if
(
ss
->
flags
&
US_FL_SINGLE_LUN
)
ss
->
max_lun
=
0
;
switch
(
ss
->
subclass
)
{
case
US_SC_RBC
:
ss
->
protocol_name
=
"Reduced Block Commands (RBC)"
;
ss
->
proto_handler
=
usb_stor_transparent_scsi_command
;
break
;
default:
/* ss->transport_name = "Unknown"; */
goto
BadDevice
;
}
US_DEBUGP
(
"Transport: %s
\n
"
,
ss
->
transport_name
);
/* fix for single-lun devices */
if
(
ss
->
flags
&
US_FL_SINGLE_LUN
)
ss
->
max_lun
=
0
;
switch
(
ss
->
subclass
)
{
case
US_SC_RBC
:
ss
->
protocol_name
=
"Reduced Block Commands (RBC)"
;
ss
->
proto_handler
=
usb_stor_transparent_scsi_command
;
break
;
case
US_SC_8020
:
ss
->
protocol_name
=
"8020i"
;
ss
->
proto_handler
=
usb_stor_ATAPI_command
;
ss
->
max_lun
=
0
;
break
;
case
US_SC_QIC
:
ss
->
protocol_name
=
"QIC-157"
;
ss
->
proto_handler
=
usb_stor_qic157_command
;
ss
->
max_lun
=
0
;
break
;
case
US_SC_8070
:
ss
->
protocol_name
=
"8070i"
;
ss
->
proto_handler
=
usb_stor_ATAPI_command
;
ss
->
max_lun
=
0
;
break
;
case
US_SC_SCSI
:
ss
->
protocol_name
=
"Transparent SCSI"
;
ss
->
proto_handler
=
usb_stor_transparent_scsi_command
;
break
;
case
US_SC_UFI
:
ss
->
protocol_name
=
"Uniform Floppy Interface (UFI)"
;
ss
->
proto_handler
=
usb_stor_ufi_command
;
break
;
case
US_SC_8020
:
ss
->
protocol_name
=
"8020i"
;
ss
->
proto_handler
=
usb_stor_ATAPI_command
;
ss
->
max_lun
=
0
;
break
;
#ifdef CONFIG_USB_STORAGE_ISD200
case
US_SC_ISD200
:
ss
->
protocol_name
=
"ISD200 ATA/ATAPI"
;
ss
->
proto_handler
=
isd200_ata_command
;
break
;
#endif
case
US_SC_QIC
:
ss
->
protocol_name
=
"QIC-157"
;
ss
->
proto_handler
=
usb_stor_qic157_command
;
ss
->
max_lun
=
0
;
break
;
default
:
/* ss->protocol_name = "Unknown"; */
goto
BadDevice
;
}
US_DEBUGP
(
"Protocol: %s
\n
"
,
ss
->
protocol_name
)
;
case
US_SC_8070
:
ss
->
protocol_name
=
"8070i"
;
ss
->
proto_handler
=
usb_stor_ATAPI_command
;
ss
->
max_lun
=
0
;
break
;
/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if
(
usb_stor_allocate_urbs
(
ss
))
goto
BadDevice
;
case
US_SC_SCSI
:
ss
->
protocol_name
=
"Transparent SCSI"
;
ss
->
proto_handler
=
usb_stor_transparent_scsi_command
;
break
;
/*
* Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers
*/
case
US_SC_UFI
:
ss
->
protocol_name
=
"Uniform Floppy Interface (UFI)"
;
ss
->
proto_handler
=
usb_stor_ufi_command
;
break
;
/* Just before we start our control thread, initialize
* the device if it needs initialization */
if
(
unusual_dev
&&
unusual_dev
->
initFunction
)
unusual_dev
->
initFunction
(
ss
);
/* start up our control thread */
atomic_set
(
&
ss
->
sm_state
,
US_STATE_IDLE
);
ss
->
pid
=
kernel_thread
(
usb_stor_control_thread
,
ss
,
CLONE_VM
);
if
(
ss
->
pid
<
0
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to start control thread
\n
"
);
goto
BadDevice
;
}
#ifdef CONFIG_USB_STORAGE_ISD200
case
US_SC_ISD200
:
ss
->
protocol_name
=
"ISD200 ATA/ATAPI"
;
ss
->
proto_handler
=
isd200_ata_command
;
break
;
#endif
/* wait for the thread to start */
wait_for_completion
(
&
(
ss
->
notify
));
default:
/* ss->protocol_name = "Unknown"; */
goto
BadDevice
;
}
US_DEBUGP
(
"Protocol: %s
\n
"
,
ss
->
protocol_name
);
/* unlock the device pointers */
up
(
&
(
ss
->
dev_semaphore
));
/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if
(
usb_stor_allocate_urbs
(
ss
))
goto
BadDevice
;
/* now register */
ss
->
host
=
scsi_register
(
&
usb_stor_host_template
,
sizeof
(
ss
));
if
(
!
ss
->
host
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to register the scsi host
\n
"
);
/*
* Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers
*/
/*
tell the control thread to exit */
ss
->
srb
=
NULL
;
up
(
&
ss
->
sema
);
wait_for_completion
(
&
ss
->
notify
);
/* Initialize the host template based on the default one */
memcpy
(
&
(
ss
->
htmplt
),
&
usb_stor_host_template
,
sizeof
(
usb_stor_host_template
));
/* re-lock the device pointers */
down
(
&
ss
->
dev_semaphore
);
goto
BadDevice
;
}
/* Grab the next host number
*/
ss
->
host_number
=
my_host_number
++
;
/* set the hostdata to prepare for scanning
*/
ss
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
ss
;
/* 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
* the device if it needs initialization */
if
(
unusual_dev
&&
unusual_dev
->
initFunction
)
unusual_dev
->
initFunction
(
ss
);
/* start up our control thread */
atomic_set
(
&
ss
->
sm_state
,
US_STATE_IDLE
);
ss
->
pid
=
kernel_thread
(
usb_stor_control_thread
,
ss
,
CLONE_VM
);
if
(
ss
->
pid
<
0
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to start control thread
\n
"
);
goto
BadDevice
;
}
/* associate this host with our interface */
scsi_set_device
(
ss
->
host
,
&
intf
->
dev
);
/* wait for the thread to start */
wait_for_completion
(
&
(
ss
->
notify
));
/* 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
"
);
/* unlock the device pointers */
up
(
&
(
ss
->
dev_semaphore
));
/* now register - our detect function will be called */
ss
->
htmplt
.
module
=
THIS_MODULE
;
result
=
scsi_register_host
(
&
(
ss
->
htmplt
));
if
(
result
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to register the scsi host
\n
"
);
/* tell the control thread to exit */
ss
->
srb
=
NULL
;
up
(
&
ss
->
sema
);
wait_for_completion
(
&
ss
->
notify
);
/* re-lock the device pointers */
down
(
&
ss
->
dev_semaphore
);
goto
BadDevice
;
}
/* tell the control thread to exit */
ss
->
srb
=
NULL
;
up
(
&
ss
->
sema
);
wait_for_completion
(
&
ss
->
notify
);
/* lock access to the data structures */
down
(
&
us_list_semaphore
);
/* put us in the list */
ss
->
next
=
us_list
;
us_list
=
ss
;
/* release the data structure lock */
up
(
&
us_list_semaphore
);
/* re-lock the device pointers */
down
(
&
ss
->
dev_semaphore
);
goto
BadDevice
;
}
printk
(
KERN_DEBUG
...
...
@@ -1041,33 +929,96 @@ static int storage_probe(struct usb_interface *intf,
/* we come here if there are any problems */
/* ss->dev_semaphore must be locked */
BadDevice:
BadDevice:
US_DEBUGP
(
"storage_probe() failed
\n
"
);
usb_stor_deallocate_urbs
(
ss
);
up
(
&
ss
->
dev_semaphore
);
if
(
new_device
)
kfree
(
ss
);
kfree
(
ss
);
return
-
EIO
;
}
/* Handle a disconnect event from the USB core */
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
"
);
ss
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
/* this is the odd case -- we disconnected but weren't using it */
if
(
!
ss
)
{
US_DEBUGP
(
"-- device was not in use
\n
"
);
return
;
}
/* serious error -- we're attempting to disconnect an interface but
* cannot locate the local data structure
*/
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
));
/* 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
);
/* 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
));
/* free the structure itself */
kfree
(
ss
);
}
/***********************************************************************
...
...
@@ -1078,11 +1029,6 @@ int __init usb_stor_init(void)
{
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 */
if
(
usb_register
(
&
usb_storage_driver
)
<
0
)
return
-
1
;
...
...
@@ -1094,16 +1040,16 @@ int __init usb_stor_init(void)
void
__exit
usb_stor_exit
(
void
)
{
struct
us_data
*
next
;
US_DEBUGP
(
"usb_stor_exit() called
\n
"
);
/* 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
"
);
usb_deregister
(
&
usb_storage_driver
)
;
#if 0
/* While there are still virtual hosts, unregister them
* Note that it's important to do this completely before removing
* the structures because of possible races with the /proc
...
...
@@ -1111,7 +1057,7 @@ void __exit usb_stor_exit(void)
*/
for (next = us_list; next; next = next->next) {
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
...
...
@@ -1137,11 +1083,12 @@ void __exit usb_stor_exit(void)
}
/* free the structure itself */
kfree
(
us_list
);
kfree (us_list);
/* advance the list pointer */
us_list = next;
}
#endif
}
module_init
(
usb_stor_init
);
...
...
drivers/usb/storage/usb.h
View file @
20b397bb
...
...
@@ -52,33 +52,6 @@
#include "scsi.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
;
/*
...
...
@@ -104,7 +77,6 @@ struct us_unusual_dev {
#define US_FL_FIX_INQUIRY 0x00000040
/* INQUIRY response needs fixing */
#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_CANCEL_SG 19
/* 0x00080000 okay to cancel current_sg? */
...
...
@@ -124,12 +96,9 @@ typedef void (*extra_data_destructor)(void *); /* extra data destructor */
/* we allocate one of these for every device that we remember */
struct
us_data
{
struct
us_data
*
next
;
/* next device */
/* The device we're working with
* It's important to note:
* (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
usb_device
*
pusb_dev
;
/* this usb_device */
...
...
@@ -163,11 +132,7 @@ struct us_data {
proto_cmnd
proto_handler
;
/* protocol handler */
/* SCSI interfaces */
GUID
(
guid
);
/* unique dev id */
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 */
/* thread information */
...
...
@@ -192,10 +157,6 @@ struct us_data {
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 */
extern
struct
usb_driver
usb_storage_driver
;
...
...
include/linux/usb.h
View file @
20b397bb
...
...
@@ -554,7 +554,6 @@ extern int usb_disabled(void);
#define URB_NO_FSBR 0x0020
/* UHCI-specific */
#define URB_ZERO_PACKET 0x0040
/* Finish bulk OUTs with short packet */
#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
{
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