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
nexedi
linux
Commits
ef4333ae
Commit
ef4333ae
authored
Mar 06, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge pcnet32 conflicting updates manually
parents
8e8acb7f
86261eb9
Changes
28
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
10419 additions
and
828 deletions
+10419
-828
Documentation/tty.txt
Documentation/tty.txt
+5
-0
drivers/char/stallion.c
drivers/char/stallion.c
+51
-71
drivers/scsi/Kconfig
drivers/scsi/Kconfig
+2
-2
drivers/scsi/atp870u.c
drivers/scsi/atp870u.c
+1846
-715
drivers/scsi/atp870u.h
drivers/scsi/atp870u.h
+53
-39
drivers/usb/media/Kconfig
drivers/usb/media/Kconfig
+36
-0
drivers/usb/media/Makefile
drivers/usb/media/Makefile
+1
-0
drivers/usb/media/pwc/ChangeLog
drivers/usb/media/pwc/ChangeLog
+143
-0
drivers/usb/media/pwc/Makefile
drivers/usb/media/pwc/Makefile
+20
-0
drivers/usb/media/pwc/philips.txt
drivers/usb/media/pwc/philips.txt
+236
-0
drivers/usb/media/pwc/pwc-ctrl.c
drivers/usb/media/pwc/pwc-ctrl.c
+1630
-0
drivers/usb/media/pwc/pwc-dec1.c
drivers/usb/media/pwc/pwc-dec1.c
+42
-0
drivers/usb/media/pwc/pwc-dec1.h
drivers/usb/media/pwc/pwc-dec1.h
+36
-0
drivers/usb/media/pwc/pwc-dec23.c
drivers/usb/media/pwc/pwc-dec23.c
+623
-0
drivers/usb/media/pwc/pwc-dec23.h
drivers/usb/media/pwc/pwc-dec23.h
+58
-0
drivers/usb/media/pwc/pwc-if.c
drivers/usb/media/pwc/pwc-if.c
+2211
-0
drivers/usb/media/pwc/pwc-ioctl.h
drivers/usb/media/pwc/pwc-ioctl.h
+292
-0
drivers/usb/media/pwc/pwc-kiara.c
drivers/usb/media/pwc/pwc-kiara.c
+891
-0
drivers/usb/media/pwc/pwc-kiara.h
drivers/usb/media/pwc/pwc-kiara.h
+45
-0
drivers/usb/media/pwc/pwc-misc.c
drivers/usb/media/pwc/pwc-misc.c
+140
-0
drivers/usb/media/pwc/pwc-nala.h
drivers/usb/media/pwc/pwc-nala.h
+66
-0
drivers/usb/media/pwc/pwc-timon.c
drivers/usb/media/pwc/pwc-timon.c
+1446
-0
drivers/usb/media/pwc/pwc-timon.h
drivers/usb/media/pwc/pwc-timon.h
+61
-0
drivers/usb/media/pwc/pwc-uncompress.c
drivers/usb/media/pwc/pwc-uncompress.c
+147
-0
drivers/usb/media/pwc/pwc-uncompress.h
drivers/usb/media/pwc/pwc-uncompress.h
+41
-0
drivers/usb/media/pwc/pwc.h
drivers/usb/media/pwc/pwc.h
+278
-0
include/linux/pci_ids.h
include/linux/pci_ids.h
+18
-0
include/linux/stallion.h
include/linux/stallion.h
+1
-1
No files found.
Documentation/tty.txt
View file @
ef4333ae
...
@@ -93,6 +93,11 @@ write_wakeup() - May be called at any point between open and close.
...
@@ -93,6 +93,11 @@ write_wakeup() - May be called at any point between open and close.
ldisc must be careful about setting order and to
ldisc must be careful about setting order and to
handle unexpected calls. Must not sleep.
handle unexpected calls. Must not sleep.
The driver is forbidden from calling this directly
from the ->write call from the ldisc as the ldisc
is permitted to call the driver write method from
this function. In such a situation defer it.
Locking
Locking
...
...
drivers/char/stallion.c
View file @
ef4333ae
...
@@ -174,14 +174,6 @@ static stlport_t stl_dummyport;
...
@@ -174,14 +174,6 @@ static stlport_t stl_dummyport;
*/
*/
static
char
stl_unwanted
[
SC26198_RXFIFOSIZE
];
static
char
stl_unwanted
[
SC26198_RXFIFOSIZE
];
/*
* Keep track of what interrupts we have requested for us.
* We don't need to request an interrupt twice if it is being
* shared with another Stallion board.
*/
static
int
stl_gotintrs
[
STL_MAXBRDS
];
static
int
stl_numintrs
;
/*****************************************************************************/
/*****************************************************************************/
static
stlbrd_t
*
stl_brds
[
STL_MAXBRDS
];
static
stlbrd_t
*
stl_brds
[
STL_MAXBRDS
];
...
@@ -504,7 +496,6 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
...
@@ -504,7 +496,6 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
static
int
stl_brdinit
(
stlbrd_t
*
brdp
);
static
int
stl_brdinit
(
stlbrd_t
*
brdp
);
static
int
stl_initports
(
stlbrd_t
*
brdp
,
stlpanel_t
*
panelp
);
static
int
stl_initports
(
stlbrd_t
*
brdp
,
stlpanel_t
*
panelp
);
static
int
stl_mapirq
(
int
irq
,
char
*
name
);
static
int
stl_getserial
(
stlport_t
*
portp
,
struct
serial_struct
__user
*
sp
);
static
int
stl_getserial
(
stlport_t
*
portp
,
struct
serial_struct
__user
*
sp
);
static
int
stl_setserial
(
stlport_t
*
portp
,
struct
serial_struct
__user
*
sp
);
static
int
stl_setserial
(
stlport_t
*
portp
,
struct
serial_struct
__user
*
sp
);
static
int
stl_getbrdstats
(
combrd_t
__user
*
bp
);
static
int
stl_getbrdstats
(
combrd_t
__user
*
bp
);
...
@@ -513,11 +504,11 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp);
...
@@ -513,11 +504,11 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp);
static
int
stl_getportstruct
(
stlport_t
__user
*
arg
);
static
int
stl_getportstruct
(
stlport_t
__user
*
arg
);
static
int
stl_getbrdstruct
(
stlbrd_t
__user
*
arg
);
static
int
stl_getbrdstruct
(
stlbrd_t
__user
*
arg
);
static
int
stl_waitcarrier
(
stlport_t
*
portp
,
struct
file
*
filp
);
static
int
stl_waitcarrier
(
stlport_t
*
portp
,
struct
file
*
filp
);
static
void
stl_eiointr
(
stlbrd_t
*
brdp
);
static
int
stl_eiointr
(
stlbrd_t
*
brdp
);
static
void
stl_echatintr
(
stlbrd_t
*
brdp
);
static
int
stl_echatintr
(
stlbrd_t
*
brdp
);
static
void
stl_echmcaintr
(
stlbrd_t
*
brdp
);
static
int
stl_echmcaintr
(
stlbrd_t
*
brdp
);
static
void
stl_echpciintr
(
stlbrd_t
*
brdp
);
static
int
stl_echpciintr
(
stlbrd_t
*
brdp
);
static
void
stl_echpci64intr
(
stlbrd_t
*
brdp
);
static
int
stl_echpci64intr
(
stlbrd_t
*
brdp
);
static
void
stl_offintr
(
void
*
private
);
static
void
stl_offintr
(
void
*
private
);
static
void
*
stl_memalloc
(
int
len
);
static
void
*
stl_memalloc
(
int
len
);
static
stlbrd_t
*
stl_allocbrd
(
void
);
static
stlbrd_t
*
stl_allocbrd
(
void
);
...
@@ -807,6 +798,9 @@ static void __exit stallion_module_exit(void)
...
@@ -807,6 +798,9 @@ static void __exit stallion_module_exit(void)
for
(
i
=
0
;
(
i
<
stl_nrbrds
);
i
++
)
{
for
(
i
=
0
;
(
i
<
stl_nrbrds
);
i
++
)
{
if
((
brdp
=
stl_brds
[
i
])
==
(
stlbrd_t
*
)
NULL
)
if
((
brdp
=
stl_brds
[
i
])
==
(
stlbrd_t
*
)
NULL
)
continue
;
continue
;
free_irq
(
brdp
->
irq
,
brdp
);
for
(
j
=
0
;
(
j
<
STL_MAXPANELS
);
j
++
)
{
for
(
j
=
0
;
(
j
<
STL_MAXPANELS
);
j
++
)
{
panelp
=
brdp
->
panels
[
j
];
panelp
=
brdp
->
panels
[
j
];
if
(
panelp
==
(
stlpanel_t
*
)
NULL
)
if
(
panelp
==
(
stlpanel_t
*
)
NULL
)
...
@@ -832,9 +826,6 @@ static void __exit stallion_module_exit(void)
...
@@ -832,9 +826,6 @@ static void __exit stallion_module_exit(void)
stl_brds
[
i
]
=
(
stlbrd_t
*
)
NULL
;
stl_brds
[
i
]
=
(
stlbrd_t
*
)
NULL
;
}
}
for
(
i
=
0
;
(
i
<
stl_numintrs
);
i
++
)
free_irq
(
stl_gotintrs
[
i
],
NULL
);
restore_flags
(
flags
);
restore_flags
(
flags
);
}
}
...
@@ -1992,23 +1983,14 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
...
@@ -1992,23 +1983,14 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
static
irqreturn_t
stl_intr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
stl_intr
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
stlbrd_t
*
brdp
;
stlbrd_t
*
brdp
=
(
stlbrd_t
*
)
dev_id
;
int
i
;
int
handled
=
0
;
#ifdef DEBUG
#ifdef DEBUG
printk
(
"stl_intr(irq=%d,regs=%x)
\n
"
,
irq
,
(
int
)
regs
);
printk
(
"stl_intr(brdp=%x,irq=%d,regs=%x)
\n
"
,
(
int
)
brdp
,
irq
,
(
int
)
regs
);
#endif
#endif
for
(
i
=
0
;
(
i
<
stl_nrbrds
);
i
++
)
{
return
IRQ_RETVAL
((
*
brdp
->
isr
)(
brdp
));
if
((
brdp
=
stl_brds
[
i
])
==
(
stlbrd_t
*
)
NULL
)
continue
;
if
(
brdp
->
state
==
0
)
continue
;
handled
=
1
;
(
*
brdp
->
isr
)(
brdp
);
}
return
IRQ_RETVAL
(
handled
);
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2017,15 +1999,19 @@ static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -2017,15 +1999,19 @@ static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
* Interrupt service routine for EasyIO board types.
* Interrupt service routine for EasyIO board types.
*/
*/
static
void
stl_eiointr
(
stlbrd_t
*
brdp
)
static
int
stl_eiointr
(
stlbrd_t
*
brdp
)
{
{
stlpanel_t
*
panelp
;
stlpanel_t
*
panelp
;
unsigned
int
iobase
;
unsigned
int
iobase
;
int
handled
=
0
;
panelp
=
brdp
->
panels
[
0
];
panelp
=
brdp
->
panels
[
0
];
iobase
=
panelp
->
iobase
;
iobase
=
panelp
->
iobase
;
while
(
inb
(
brdp
->
iostatus
)
&
EIO_INTRPEND
)
while
(
inb
(
brdp
->
iostatus
)
&
EIO_INTRPEND
)
{
handled
=
1
;
(
*
panelp
->
isr
)(
panelp
,
iobase
);
(
*
panelp
->
isr
)(
panelp
,
iobase
);
}
return
handled
;
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2034,15 +2020,17 @@ static void stl_eiointr(stlbrd_t *brdp)
...
@@ -2034,15 +2020,17 @@ static void stl_eiointr(stlbrd_t *brdp)
* Interrupt service routine for ECH-AT board types.
* Interrupt service routine for ECH-AT board types.
*/
*/
static
void
stl_echatintr
(
stlbrd_t
*
brdp
)
static
int
stl_echatintr
(
stlbrd_t
*
brdp
)
{
{
stlpanel_t
*
panelp
;
stlpanel_t
*
panelp
;
unsigned
int
ioaddr
;
unsigned
int
ioaddr
;
int
bnknr
;
int
bnknr
;
int
handled
=
0
;
outb
((
brdp
->
ioctrlval
|
ECH_BRDENABLE
),
brdp
->
ioctrl
);
outb
((
brdp
->
ioctrlval
|
ECH_BRDENABLE
),
brdp
->
ioctrl
);
while
(
inb
(
brdp
->
iostatus
)
&
ECH_INTRPEND
)
{
while
(
inb
(
brdp
->
iostatus
)
&
ECH_INTRPEND
)
{
handled
=
1
;
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
...
@@ -2053,6 +2041,8 @@ static void stl_echatintr(stlbrd_t *brdp)
...
@@ -2053,6 +2041,8 @@ static void stl_echatintr(stlbrd_t *brdp)
}
}
outb
((
brdp
->
ioctrlval
|
ECH_BRDDISABLE
),
brdp
->
ioctrl
);
outb
((
brdp
->
ioctrlval
|
ECH_BRDDISABLE
),
brdp
->
ioctrl
);
return
handled
;
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2061,13 +2051,15 @@ static void stl_echatintr(stlbrd_t *brdp)
...
@@ -2061,13 +2051,15 @@ static void stl_echatintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-MCA board types.
* Interrupt service routine for ECH-MCA board types.
*/
*/
static
void
stl_echmcaintr
(
stlbrd_t
*
brdp
)
static
int
stl_echmcaintr
(
stlbrd_t
*
brdp
)
{
{
stlpanel_t
*
panelp
;
stlpanel_t
*
panelp
;
unsigned
int
ioaddr
;
unsigned
int
ioaddr
;
int
bnknr
;
int
bnknr
;
int
handled
=
0
;
while
(
inb
(
brdp
->
iostatus
)
&
ECH_INTRPEND
)
{
while
(
inb
(
brdp
->
iostatus
)
&
ECH_INTRPEND
)
{
handled
=
1
;
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
...
@@ -2076,6 +2068,7 @@ static void stl_echmcaintr(stlbrd_t *brdp)
...
@@ -2076,6 +2068,7 @@ static void stl_echmcaintr(stlbrd_t *brdp)
}
}
}
}
}
}
return
handled
;
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2084,11 +2077,12 @@ static void stl_echmcaintr(stlbrd_t *brdp)
...
@@ -2084,11 +2077,12 @@ static void stl_echmcaintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-PCI board types.
* Interrupt service routine for ECH-PCI board types.
*/
*/
static
void
stl_echpciintr
(
stlbrd_t
*
brdp
)
static
int
stl_echpciintr
(
stlbrd_t
*
brdp
)
{
{
stlpanel_t
*
panelp
;
stlpanel_t
*
panelp
;
unsigned
int
ioaddr
;
unsigned
int
ioaddr
;
int
bnknr
,
recheck
;
int
bnknr
,
recheck
;
int
handled
=
0
;
while
(
1
)
{
while
(
1
)
{
recheck
=
0
;
recheck
=
0
;
...
@@ -2099,11 +2093,13 @@ static void stl_echpciintr(stlbrd_t *brdp)
...
@@ -2099,11 +2093,13 @@ static void stl_echpciintr(stlbrd_t *brdp)
panelp
=
brdp
->
bnk2panel
[
bnknr
];
panelp
=
brdp
->
bnk2panel
[
bnknr
];
(
*
panelp
->
isr
)(
panelp
,
(
ioaddr
&
0xfffc
));
(
*
panelp
->
isr
)(
panelp
,
(
ioaddr
&
0xfffc
));
recheck
++
;
recheck
++
;
handled
=
1
;
}
}
}
}
if
(
!
recheck
)
if
(
!
recheck
)
break
;
break
;
}
}
return
handled
;
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2112,13 +2108,15 @@ static void stl_echpciintr(stlbrd_t *brdp)
...
@@ -2112,13 +2108,15 @@ static void stl_echpciintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-8/64-PCI board types.
* Interrupt service routine for ECH-8/64-PCI board types.
*/
*/
static
void
stl_echpci64intr
(
stlbrd_t
*
brdp
)
static
int
stl_echpci64intr
(
stlbrd_t
*
brdp
)
{
{
stlpanel_t
*
panelp
;
stlpanel_t
*
panelp
;
unsigned
int
ioaddr
;
unsigned
int
ioaddr
;
int
bnknr
;
int
bnknr
;
int
handled
=
0
;
while
(
inb
(
brdp
->
ioctrl
)
&
0x1
)
{
while
(
inb
(
brdp
->
ioctrl
)
&
0x1
)
{
handled
=
1
;
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
for
(
bnknr
=
0
;
(
bnknr
<
brdp
->
nrbnks
);
bnknr
++
)
{
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
ioaddr
=
brdp
->
bnkstataddr
[
bnknr
];
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
if
(
inb
(
ioaddr
)
&
ECH_PNLINTRPEND
)
{
...
@@ -2127,6 +2125,8 @@ static void stl_echpci64intr(stlbrd_t *brdp)
...
@@ -2127,6 +2125,8 @@ static void stl_echpci64intr(stlbrd_t *brdp)
}
}
}
}
}
}
return
handled
;
}
}
/*****************************************************************************/
/*****************************************************************************/
...
@@ -2173,39 +2173,6 @@ static void stl_offintr(void *private)
...
@@ -2173,39 +2173,6 @@ static void stl_offintr(void *private)
/*****************************************************************************/
/*****************************************************************************/
/*
* Map in interrupt vector to this driver. Check that we don't
* already have this vector mapped, we might be sharing this
* interrupt across multiple boards.
*/
static
int
__init
stl_mapirq
(
int
irq
,
char
*
name
)
{
int
rc
,
i
;
#ifdef DEBUG
printk
(
"stl_mapirq(irq=%d,name=%s)
\n
"
,
irq
,
name
);
#endif
rc
=
0
;
for
(
i
=
0
;
(
i
<
stl_numintrs
);
i
++
)
{
if
(
stl_gotintrs
[
i
]
==
irq
)
break
;
}
if
(
i
>=
stl_numintrs
)
{
if
(
request_irq
(
irq
,
stl_intr
,
SA_SHIRQ
,
name
,
NULL
)
!=
0
)
{
printk
(
"STALLION: failed to register interrupt "
"routine for %s irq=%d
\n
"
,
name
,
irq
);
rc
=
-
ENODEV
;
}
else
{
stl_gotintrs
[
stl_numintrs
++
]
=
irq
;
}
}
return
(
rc
);
}
/*****************************************************************************/
/*
/*
* Initialize all the ports on a panel.
* Initialize all the ports on a panel.
*/
*/
...
@@ -2389,7 +2356,13 @@ static inline int stl_initeio(stlbrd_t *brdp)
...
@@ -2389,7 +2356,13 @@ static inline int stl_initeio(stlbrd_t *brdp)
brdp
->
nrpanels
=
1
;
brdp
->
nrpanels
=
1
;
brdp
->
state
|=
BRD_FOUND
;
brdp
->
state
|=
BRD_FOUND
;
brdp
->
hwid
=
status
;
brdp
->
hwid
=
status
;
rc
=
stl_mapirq
(
brdp
->
irq
,
name
);
if
(
request_irq
(
brdp
->
irq
,
stl_intr
,
SA_SHIRQ
,
name
,
brdp
)
!=
0
)
{
printk
(
"STALLION: failed to register interrupt "
"routine for %s irq=%d
\n
"
,
name
,
brdp
->
irq
);
rc
=
-
ENODEV
;
}
else
{
rc
=
0
;
}
return
(
rc
);
return
(
rc
);
}
}
...
@@ -2594,7 +2567,14 @@ static inline int stl_initech(stlbrd_t *brdp)
...
@@ -2594,7 +2567,14 @@ static inline int stl_initech(stlbrd_t *brdp)
outb
((
brdp
->
ioctrlval
|
ECH_BRDDISABLE
),
brdp
->
ioctrl
);
outb
((
brdp
->
ioctrlval
|
ECH_BRDDISABLE
),
brdp
->
ioctrl
);
brdp
->
state
|=
BRD_FOUND
;
brdp
->
state
|=
BRD_FOUND
;
i
=
stl_mapirq
(
brdp
->
irq
,
name
);
if
(
request_irq
(
brdp
->
irq
,
stl_intr
,
SA_SHIRQ
,
name
,
brdp
)
!=
0
)
{
printk
(
"STALLION: failed to register interrupt "
"routine for %s irq=%d
\n
"
,
name
,
brdp
->
irq
);
i
=
-
ENODEV
;
}
else
{
i
=
0
;
}
return
(
i
);
return
(
i
);
}
}
...
...
drivers/scsi/Kconfig
View file @
ef4333ae
...
@@ -273,8 +273,8 @@ config SCSI_ACARD
...
@@ -273,8 +273,8 @@ config SCSI_ACARD
tristate "ACARD SCSI support"
tristate "ACARD SCSI support"
depends on PCI && SCSI
depends on PCI && SCSI
help
help
This driver supports the ACARD
870U/W
SCSI host adapter.
This driver supports the ACARD SCSI host adapter.
Support Chip <ATP870 ATP876 ATP880 ATP885>
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called atp870u.
module will be called atp870u.
...
...
drivers/scsi/atp870u.c
View file @
ef4333ae
...
@@ -13,8 +13,9 @@
...
@@ -13,8 +13,9 @@
* fix disconnect bug 2000/12/21
* fix disconnect bug 2000/12/21
* support atp880 chip lvd u160 2001/05/15
* support atp880 chip lvd u160 2001/05/15
* fix prd table bug 2001/09/12 (7.1)
* fix prd table bug 2001/09/12 (7.1)
*
* atp885 support add by ACARD Hao Ping Lian 2005/01/05
*/
*/
#include <linux/module.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
...
@@ -38,39 +39,54 @@
...
@@ -38,39 +39,54 @@
#include "atp870u.h"
#include "atp870u.h"
static
struct
scsi_host_template
atp870u_template
;
static
struct
scsi_host_template
atp870u_template
;
static
void
send_s870
(
struct
Scsi_Host
*
host
);
void
send_s870
(
struct
atp_unit
*
dev
,
unsigned
char
c
);
void
is885
(
struct
atp_unit
*
dev
,
unsigned
int
wkport
,
unsigned
char
c
);
void
tscam_885
(
void
);
static
irqreturn_t
atp870u_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
static
irqreturn_t
atp870u_intr_handle
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
short
int
tmpcip
,
id
;
unsigned
short
int
tmpcip
,
id
;
unsigned
char
i
,
j
,
target_id
,
lun
;
unsigned
char
i
,
j
,
c
,
target_id
,
lun
,
cmdp
;
unsigned
char
*
prd
;
unsigned
char
*
prd
;
struct
scsi_cmnd
*
workrequ
;
struct
scsi_cmnd
*
workreq
;
unsigned
int
workportu
,
tmport
;
unsigned
int
workport
,
tmport
,
tmport1
;
unsigned
long
adrcntu
,
k
;
unsigned
long
adrcnt
,
k
;
#ifdef ED_DBGP
unsigned
long
l
;
#endif
int
errstus
;
int
errstus
;
struct
Scsi_Host
*
host
=
dev_id
;
struct
Scsi_Host
*
host
=
dev_id
;
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
dev
->
in_int
=
1
;
for
(
c
=
0
;
c
<
2
;
c
++
)
{
workportu
=
dev
->
ioport
;
tmport
=
dev
->
ioport
[
c
]
+
0x1f
;
tmport
=
workportu
;
if
(
dev
->
working
!=
0
)
{
tmport
+=
0x1f
;
j
=
inb
(
tmport
);
j
=
inb
(
tmport
);
if
((
j
&
0x80
)
==
0
)
{
if
((
j
&
0x80
)
!=
0
)
dev
->
in_int
=
0
;
{
return
IRQ_NONE
;
goto
ch_sel
;
}
}
dev
->
in_int
[
c
]
=
0
;
tmpcip
=
dev
->
pciport
;
}
if
((
inb
(
tmpcip
)
&
0x08
)
!=
0
)
{
return
IRQ_NONE
;
ch_sel:
#ifdef ED_DBGP
printk
(
"atp870u_intr_handle enter
\n
"
);
#endif
dev
->
in_int
[
c
]
=
1
;
cmdp
=
inb
(
dev
->
ioport
[
c
]
+
0x10
);
workport
=
dev
->
ioport
[
c
];
if
(
dev
->
working
[
c
]
!=
0
)
{
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport1
=
workport
+
0x16
;
if
((
inb
(
tmport1
)
&
0x80
)
==
0
)
outb
((
inb
(
tmport1
)
|
0x80
),
tmport1
);
}
tmpcip
=
dev
->
pciport
[
c
];
if
((
inb
(
tmpcip
)
&
0x08
)
!=
0
)
{
tmpcip
+=
0x2
;
tmpcip
+=
0x2
;
for
(
k
=
0
;
k
<
1000
;
k
++
)
{
for
(
k
=
0
;
k
<
1000
;
k
++
)
{
if
((
inb
(
tmpcip
)
&
0x08
)
==
0
)
{
if
((
inb
(
tmpcip
)
&
0x08
)
==
0
)
{
goto
stop_dma
;
goto
stop_dma
;
}
}
...
@@ -80,12 +96,18 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -80,12 +96,18 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
}
}
}
}
stop_dma:
stop_dma:
tmpcip
=
dev
->
pciport
;
tmpcip
=
dev
->
pciport
[
c
]
;
outb
(
0x00
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
tmport
-=
0x08
;
tmport
-=
0x08
;
i
=
inb
(
tmport
);
i
=
inb
(
tmport
);
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmpcip
+=
2
;
outb
(
0x06
,
tmpcip
);
tmpcip
-=
2
;
}
tmport
-=
0x02
;
tmport
-=
0x02
;
target_id
=
inb
(
tmport
);
target_id
=
inb
(
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
...
@@ -101,21 +123,43 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -101,21 +123,43 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
}
}
if
((
j
&
0x40
)
!=
0
)
{
if
((
j
&
0x40
)
!=
0
)
{
if
(
dev
->
last_cmd
==
0xff
)
{
if
(
dev
->
last_cmd
[
c
]
==
0xff
)
{
dev
->
last_cmd
=
target_id
;
dev
->
last_cmd
[
c
]
=
target_id
;
}
}
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
}
}
if
(
dev
->
dev_id
==
ATP885_DEVID
)
dev
->
r1f
[
c
][
target_id
]
|=
j
;
#ifdef ED_DBGP
printk
(
"atp870u_intr_handle status = %x
\n
"
,
i
);
#endif
if
(
i
==
0x85
)
{
if
(
i
==
0x85
)
{
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
{
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport
-=
0x05
;
adrcnt
=
0
;
((
unsigned
char
*
)
&
adrcnt
)[
2
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
1
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
0
]
=
inb
(
tmport
);
if
(
dev
->
id
[
c
][
target_id
].
last_len
!=
adrcnt
)
{
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
k
-=
adrcnt
;
dev
->
id
[
c
][
target_id
].
tran_len
=
k
;
dev
->
id
[
c
][
target_id
].
last_len
=
adrcnt
;
}
#ifdef ED_DBGP
printk
(
"tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d
\n
"
,
tmport
,
dev
->
id
[
c
][
target_id
].
last_len
,
dev
->
id
[
c
][
target_id
].
tran_len
);
#endif
}
/*
/*
* Flip wide
* Flip wide
*/
*/
if
(
dev
->
wide_id
u
!=
0
)
{
if
(
dev
->
wide_id
[
c
]
!=
0
)
{
tmport
=
workport
u
+
0x1b
;
tmport
=
workport
+
0x1b
;
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
while
((
inb
(
tmport
)
&
0x01
)
!=
0x01
)
{
while
((
inb
(
tmport
)
&
0x01
)
!=
0x01
)
{
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
...
@@ -125,87 +169,119 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -125,87 +169,119 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
* Issue more commands
* Issue more commands
*/
*/
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
if
(((
dev
->
quhdu
!=
dev
->
quendu
)
||
(
dev
->
last_cmd
!=
0xff
))
&&
(
dev
->
in_snd
==
0
))
{
if
(((
dev
->
quhd
[
c
]
!=
dev
->
quend
[
c
])
||
(
dev
->
last_cmd
[
c
]
!=
0xff
))
&&
send_s870
(
host
);
(
dev
->
in_snd
[
c
]
==
0
))
{
#ifdef ED_DBGP
printk
(
"Call sent_s870
\n
"
);
#endif
send_s870
(
dev
,
c
);
}
}
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
/*
/*
* Done
* Done
*/
*/
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
#ifdef ED_DBGP
printk
(
"Status 0x85 return
\n
"
);
#endif
goto
handled
;
}
}
if
(
i
==
0x40
)
{
if
(
i
==
0x40
)
{
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
}
if
(
i
==
0x21
)
{
if
(
i
==
0x21
)
{
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
{
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
tmport
-=
0x05
;
tmport
-=
0x05
;
adrcnt
u
=
0
;
adrcnt
=
0
;
((
unsigned
char
*
)
&
adrcnt
u
)[
2
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
2
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
u
)[
1
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
1
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
u
)[
0
]
=
inb
(
tmport
);
((
unsigned
char
*
)
&
adrcnt
)[
0
]
=
inb
(
tmport
);
k
=
dev
->
id
[
target_id
].
last_lenu
;
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
k
-=
adrcnt
u
;
k
-=
adrcnt
;
dev
->
id
[
target_id
].
tran_lenu
=
k
;
dev
->
id
[
c
][
target_id
].
tran_len
=
k
;
dev
->
id
[
target_id
].
last_lenu
=
adrcntu
;
dev
->
id
[
c
][
target_id
].
last_len
=
adrcnt
;
tmport
-=
0x04
;
tmport
-=
0x04
;
outb
(
0x41
,
tmport
);
outb
(
0x41
,
tmport
);
tmport
+=
0x08
;
tmport
+=
0x08
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
if
((
i
==
0x4c
)
||
(
i
==
0x4d
)
||
(
i
==
0x8c
)
||
(
i
==
0x8d
))
{
if
((
i
==
0x4c
)
||
(
i
==
0x8c
))
i
=
0x48
;
else
i
=
0x49
;
}
}
}
if
((
i
==
0x80
)
||
(
i
==
0x8f
))
{
if
((
i
==
0x80
)
||
(
i
==
0x8f
))
{
#ifdef ED_DBGP
printk
(
KERN_DEBUG
"Device reselect
\n
"
);
#endif
lun
=
0
;
lun
=
0
;
tmport
-=
0x07
;
tmport
-=
0x07
;
j
=
inb
(
tmport
);
if
(
cmdp
==
0x44
||
i
==
0x80
)
{
if
(
j
==
0x44
||
i
==
0x80
)
{
tmport
+=
0x0d
;
tmport
+=
0x0d
;
lun
=
inb
(
tmport
)
&
0x07
;
lun
=
inb
(
tmport
)
&
0x07
;
}
else
{
}
else
{
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
{
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
if
(
j
==
0x41
)
{
if
(
cmdp
==
0x41
)
{
#ifdef ED_DBGP
printk
(
"cmdp = 0x41
\n
"
);
#endif
tmport
+=
0x02
;
tmport
+=
0x02
;
adrcnt
u
=
0
;
adrcnt
=
0
;
((
unsigned
char
*
)
&
adrcnt
u
)[
2
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
2
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
u
)[
1
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
)[
1
]
=
inb
(
tmport
++
);
((
unsigned
char
*
)
&
adrcnt
u
)[
0
]
=
inb
(
tmport
);
((
unsigned
char
*
)
&
adrcnt
)[
0
]
=
inb
(
tmport
);
k
=
dev
->
id
[
target_id
].
last_lenu
;
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
k
-=
adrcnt
u
;
k
-=
adrcnt
;
dev
->
id
[
target_id
].
tran_lenu
=
k
;
dev
->
id
[
c
][
target_id
].
tran_len
=
k
;
dev
->
id
[
target_id
].
last_lenu
=
adrcntu
;
dev
->
id
[
c
][
target_id
].
last_len
=
adrcnt
;
tmport
+=
0x04
;
tmport
+=
0x04
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
else
{
}
else
{
#ifdef ED_DBGP
printk
(
"cmdp != 0x41
\n
"
);
#endif
outb
(
0x46
,
tmport
);
outb
(
0x46
,
tmport
);
dev
->
id
[
target_id
].
dirctu
=
0x00
;
dev
->
id
[
c
][
target_id
].
dirct
=
0x00
;
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
tmport
+=
0x03
;
tmport
+=
0x03
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
}
}
}
if
(
dev
->
last_cmd
!=
0xff
)
{
if
(
dev
->
last_cmd
[
c
]
!=
0xff
)
{
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
}
}
tmport
=
workportu
+
0x10
;
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
j
=
inb
(
dev
->
baseport
+
0x29
)
&
0xfe
;
outb
(
j
,
dev
->
baseport
+
0x29
);
tmport
=
workport
+
0x16
;
}
else
{
tmport
=
workport
+
0x10
;
outb
(
0x45
,
tmport
);
outb
(
0x45
,
tmport
);
tmport
+=
0x06
;
tmport
+=
0x06
;
}
target_id
=
inb
(
tmport
);
target_id
=
inb
(
tmport
);
/*
/*
* Remap wide identifiers
* Remap wide identifiers
...
@@ -215,162 +291,214 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -215,162 +291,214 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
}
else
{
}
else
{
target_id
&=
0x07
;
target_id
&=
0x07
;
}
}
workrequ
=
dev
->
id
[
target_id
].
curr_req
;
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport
=
workportu
+
0x0f
;
tmport
=
workport
+
0x10
;
outb
(
0x45
,
tmport
);
}
workreq
=
dev
->
id
[
c
][
target_id
].
curr_req
;
#ifdef ED_DBGP
printk
(
KERN_DEBUG
"Channel = %d ID = %d LUN = %d CDB"
,
c
,
workreq
->
device
->
id
,
workreq
->
device
->
lun
);
for
(
l
=
0
;
l
<
workreq
->
cmd_len
;
l
++
)
{
printk
(
KERN_DEBUG
" %x"
,
workreq
->
cmnd
[
l
]);
}
#endif
tmport
=
workport
+
0x0f
;
outb
(
lun
,
tmport
);
outb
(
lun
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
target_id
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
c
][
target_id
].
devsp
,
tmport
++
);
adrcntu
=
dev
->
id
[
target_id
].
tran_lenu
;
adrcnt
=
dev
->
id
[
c
][
target_id
].
tran_len
;
k
=
dev
->
id
[
target_id
].
last_lenu
;
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
outb
(((
unsigned
char
*
)
&
k
)[
2
],
tmport
++
);
outb
(((
unsigned
char
*
)
&
k
)[
2
],
tmport
++
);
outb
(((
unsigned
char
*
)
&
k
)[
1
],
tmport
++
);
outb
(((
unsigned
char
*
)
&
k
)[
1
],
tmport
++
);
outb
(((
unsigned
char
*
)
&
k
)[
0
],
tmport
++
);
outb
(((
unsigned
char
*
)
&
k
)[
0
],
tmport
++
);
#ifdef ED_DBGP
printk
(
"k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x
\n
"
,
k
,
inb
(
tmport
-
1
),
inb
(
tmport
-
2
),
inb
(
tmport
-
3
));
#endif
/* Remap wide */
/* Remap wide */
j
=
target_id
;
j
=
target_id
;
if
(
target_id
>
7
)
{
if
(
target_id
>
7
)
{
j
=
(
j
&
0x07
)
|
0x40
;
j
=
(
j
&
0x07
)
|
0x40
;
}
}
/* Add direction */
/* Add direction */
j
|=
dev
->
id
[
target_id
].
dirctu
;
j
|=
dev
->
id
[
c
][
target_id
].
dirct
;
outb
(
j
,
tmport
++
);
outb
(
j
,
tmport
++
);
outb
(
0x80
,
tmport
);
outb
(
0x80
,
tmport
);
/* enable 32 bit fifo transfer */
/* enable 32 bit fifo transfer */
if
(
dev
->
deviceid
!=
0x8081
)
{
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport
=
workportu
+
0x3a
;
tmpcip
=
dev
->
pciport
[
c
]
+
1
;
if
((
dev
->
ata_cdbu
[
0
]
==
0x08
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x28
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x0a
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x2a
))
{
i
=
inb
(
tmpcip
)
&
0xf3
;
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0xf3
)
|
0x08
),
tmport
);
//j=workreq->cmnd[0];
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
i
|=
0x0c
;
}
outb
(
i
,
tmpcip
);
}
else
if
((
dev
->
dev_id
==
ATP880_DEVID1
)
||
(
dev
->
dev_id
==
ATP880_DEVID2
)
)
{
tmport
=
workport
-
0x05
;
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0x3f
)
|
0xc0
),
tmport
);
}
else
{
}
else
{
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0x
f3
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0x
3f
),
tmport
);
}
}
}
else
{
}
else
{
tmport
=
workport
u
-
0x05
;
tmport
=
workport
+
0x3a
;
if
((
dev
->
ata_cdbu
[
0
]
==
0x08
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x28
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x0a
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x2a
))
{
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0x
3f
)
|
0xc0
),
tmport
);
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0x
f3
)
|
0x08
),
tmport
);
}
else
{
}
else
{
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0x
3f
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0x
f3
),
tmport
);
}
}
}
}
tmport
=
workport
+
0x1b
;
tmport
=
workportu
+
0x1b
;
j
=
0
;
j
=
0
;
id
=
1
;
id
=
1
;
id
=
id
<<
target_id
;
id
=
id
<<
target_id
;
/*
/*
* Is this a wide device
* Is this a wide device
*/
*/
if
((
id
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
id
&
dev
->
wide_id
[
c
]
)
!=
0
)
{
j
|=
0x01
;
j
|=
0x01
;
}
}
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
while
((
inb
(
tmport
)
&
0x01
)
!=
j
)
{
while
((
inb
(
tmport
)
&
0x01
)
!=
j
)
{
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
}
}
if
(
dev
->
id
[
c
][
target_id
].
last_len
==
0
)
{
if
(
dev
->
id
[
target_id
].
last_lenu
==
0
)
{
tmport
=
workport
+
0x18
;
tmport
=
workportu
+
0x18
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
#ifdef ED_DBGP
}
printk
(
"dev->id[c][target_id].last_len = 0
\n
"
);
prd
=
dev
->
id
[
target_id
].
prd_posu
;
#endif
while
(
adrcntu
!=
0
)
{
goto
handled
;
id
=
((
unsigned
short
int
*
)
(
prd
))[
2
];
}
#ifdef ED_DBGP
printk
(
"target_id = %d adrcnt = %d
\n
"
,
target_id
,
adrcnt
);
#endif
prd
=
dev
->
id
[
c
][
target_id
].
prd_pos
;
while
(
adrcnt
!=
0
)
{
id
=
((
unsigned
short
int
*
)
prd
)[
2
];
if
(
id
==
0
)
{
if
(
id
==
0
)
{
k
=
0x10000
;
k
=
0x10000
;
}
else
{
}
else
{
k
=
id
;
k
=
id
;
}
}
if
(
k
>
adrcnt
u
)
{
if
(
k
>
adrcnt
)
{
((
unsigned
short
int
*
)
(
prd
)
)[
2
]
=
(
unsigned
short
int
)
((
unsigned
short
int
*
)
prd
)[
2
]
=
(
unsigned
short
int
)
(
k
-
adrcnt
u
);
(
k
-
adrcnt
);
((
unsigned
long
*
)
(
prd
))[
0
]
+=
adrcntu
;
((
unsigned
long
*
)
prd
)[
0
]
+=
adrcnt
;
adrcnt
u
=
0
;
adrcnt
=
0
;
dev
->
id
[
target_id
].
prd_posu
=
prd
;
dev
->
id
[
c
][
target_id
].
prd_pos
=
prd
;
}
else
{
}
else
{
adrcnt
u
-=
k
;
adrcnt
-=
k
;
dev
->
id
[
target_id
].
prdaddru
+=
0x08
;
dev
->
id
[
c
][
target_id
].
prdaddr
+=
0x08
;
prd
+=
0x08
;
prd
+=
0x08
;
if
(
adrcnt
u
==
0
)
{
if
(
adrcnt
==
0
)
{
dev
->
id
[
target_id
].
prd_posu
=
prd
;
dev
->
id
[
c
][
target_id
].
prd_pos
=
prd
;
}
}
}
}
}
}
tmpcip
=
dev
->
pciport
+
0x04
;
tmpcip
=
dev
->
pciport
[
c
]
+
0x04
;
outl
(
dev
->
id
[
target_id
].
prdaddru
,
tmpcip
);
outl
(
dev
->
id
[
c
][
target_id
].
prdaddr
,
tmpcip
);
#ifdef ED_DBGP
printk
(
"dev->id[%d][%d].prdaddr 0x%8x
\n
"
,
c
,
target_id
,
dev
->
id
[
c
][
target_id
].
prdaddr
);
#endif
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmpcip
-=
0x04
;
}
else
{
tmpcip
-=
0x02
;
tmpcip
-=
0x02
;
outb
(
0x06
,
tmpcip
);
outb
(
0x06
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
tmpcip
-=
0x02
;
tmpcip
-=
0x02
;
tmport
=
workportu
+
0x18
;
}
tmport
=
workport
+
0x18
;
/*
/*
* Check transfer direction
* Check transfer direction
*/
*/
if
(
dev
->
id
[
target_id
].
dirctu
!=
0
)
{
if
(
dev
->
id
[
c
][
target_id
].
dirct
!=
0
)
{
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x01
,
tmpcip
);
outb
(
0x01
,
tmpcip
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
#ifdef ED_DBGP
printk
(
"status 0x80 return dirct != 0
\n
"
);
#endif
goto
handled
;
}
}
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x09
,
tmpcip
);
outb
(
0x09
,
tmpcip
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
#ifdef ED_DBGP
printk
(
"status 0x80 return dirct = 0
\n
"
);
#endif
goto
handled
;
}
}
/*
/*
* Current scsi request on this target
* Current scsi request on this target
*/
*/
workreq
u
=
dev
->
id
[
target_id
].
curr_req
;
workreq
=
dev
->
id
[
c
]
[
target_id
].
curr_req
;
if
(
i
==
0x42
)
{
if
(
i
==
0x42
)
{
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
dev
->
last_cmd
=
0xff
;
{
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
errstus
=
0x02
;
errstus
=
0x02
;
workreq
u
->
result
=
errstus
;
workreq
->
result
=
errstus
;
goto
go_42
;
goto
go_42
;
}
}
if
(
i
==
0x16
)
{
if
(
i
==
0x16
)
{
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
{
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
errstus
=
0
;
errstus
=
0
;
tmport
-=
0x08
;
tmport
-=
0x08
;
errstus
=
inb
(
tmport
);
errstus
=
inb
(
tmport
);
workrequ
->
result
=
errstus
;
if
(((
dev
->
r1f
[
c
][
target_id
]
&
0x10
)
!=
0
)
&&
(
dev
->
dev_id
==
ATP885_DEVID
))
{
printk
(
KERN_WARNING
"AEC67162 CRC ERROR !
\n
"
);
errstus
=
0x02
;
}
workreq
->
result
=
errstus
;
go_42:
go_42:
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
j
=
inb
(
dev
->
baseport
+
0x29
)
|
0x01
;
outb
(
j
,
dev
->
baseport
+
0x29
);
}
/*
/*
* Complete the command
* Complete the command
*/
*/
if
(
workreq
->
use_sg
)
{
if
(
workrequ
->
use_sg
)
{
pci_unmap_sg
(
dev
->
pdev
,
pci_unmap_sg
(
dev
->
pdev
,
(
struct
scatterlist
*
)
workreq
u
->
buffer
,
(
struct
scatterlist
*
)
workreq
->
buffer
,
workreq
u
->
use_sg
,
workreq
->
use_sg
,
workreq
u
->
sc_data_direction
);
workreq
->
sc_data_direction
);
}
else
if
(
workreq
u
->
request_bufflen
&&
}
else
if
(
workreq
->
request_bufflen
&&
workreq
u
->
sc_data_direction
!=
DMA_NONE
)
{
workreq
->
sc_data_direction
!=
DMA_NONE
)
{
pci_unmap_single
(
dev
->
pdev
,
pci_unmap_single
(
dev
->
pdev
,
workreq
u
->
SCp
.
dma_handle
,
workreq
->
SCp
.
dma_handle
,
workreq
u
->
request_bufflen
,
workreq
->
request_bufflen
,
workreq
u
->
sc_data_direction
);
workreq
->
sc_data_direction
);
}
}
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
(
*
workrequ
->
scsi_done
)
(
workrequ
);
(
*
workreq
->
scsi_done
)
(
workreq
);
#ifdef ED_DBGP
printk
(
"workreq->scsi_done
\n
"
);
#endif
/*
/*
* Clear it off the queue
* Clear it off the queue
*/
*/
dev
->
id
[
target_id
].
curr_req
=
NULL
;
dev
->
id
[
c
][
target_id
].
curr_req
=
0
;
dev
->
working
--
;
dev
->
working
[
c
]
--
;
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
/*
/*
* Take it back wide
* Take it back wide
*/
*/
if
(
dev
->
wide_id
u
!=
0
)
{
if
(
dev
->
wide_id
[
c
]
!=
0
)
{
tmport
=
workport
u
+
0x1b
;
tmport
=
workport
+
0x1b
;
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
while
((
inb
(
tmport
)
&
0x01
)
!=
0x01
)
{
while
((
inb
(
tmport
)
&
0x01
)
!=
0x01
)
{
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
...
@@ -380,53 +508,75 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -380,53 +508,75 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
* If there is stuff to send and nothing going then send it
* If there is stuff to send and nothing going then send it
*/
*/
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
dev
->
host
->
host_lock
,
flags
);
if
(((
dev
->
last_cmd
!=
0xff
)
||
(
dev
->
quhdu
!=
dev
->
quendu
))
&&
(
dev
->
in_snd
==
0
))
{
if
(((
dev
->
last_cmd
[
c
]
!=
0xff
)
||
(
dev
->
quhd
[
c
]
!=
dev
->
quend
[
c
]))
&&
send_s870
(
host
);
(
dev
->
in_snd
[
c
]
==
0
))
{
#ifdef ED_DBGP
printk
(
"Call sent_s870(scsi_done)
\n
"
);
#endif
send_s870
(
dev
,
c
);
}
}
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
dev
->
host
->
host_lock
,
flags
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
}
if
((
dev
->
last_cmd
&
0xf0
)
!=
0x40
)
{
if
((
dev
->
last_cmd
[
c
]
&
0xf0
)
!=
0x40
)
{
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
}
}
if
(
i
==
0x4f
)
{
if
(
i
==
0x4f
)
{
i
=
0x89
;
i
=
0x89
;
}
}
i
&=
0x0f
;
i
&=
0x0f
;
if
(
i
==
0x09
)
{
if
(
i
==
0x09
)
{
tmpcip
=
tmpcip
+
4
;
tmpcip
+=
4
;
outl
(
dev
->
id
[
target_id
].
prdaddru
,
tmpcip
);
outl
(
dev
->
id
[
c
][
target_id
].
prdaddr
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
tmpcip
=
tmpcip
-
2
;
outb
(
0x06
,
tmpcip
);
outb
(
0x06
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
tmpcip
=
tmpcip
-
2
;
tmport
=
workport
u
+
0x10
;
tmport
=
workport
+
0x10
;
outb
(
0x41
,
tmport
);
outb
(
0x41
,
tmport
);
dev
->
id
[
target_id
].
dirctu
=
0x00
;
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport
+=
2
;
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
2
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
1
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
0
]),
tmport
);
dev
->
id
[
c
][
target_id
].
dirct
=
0x00
;
tmport
+=
0x04
;
}
else
{
dev
->
id
[
c
][
target_id
].
dirct
=
0x00
;
tmport
+=
0x08
;
tmport
+=
0x08
;
}
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x09
,
tmpcip
);
outb
(
0x09
,
tmpcip
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
}
if
(
i
==
0x08
)
{
if
(
i
==
0x08
)
{
tmpcip
=
tmpcip
+
4
;
tmpcip
+=
4
;
outl
(
dev
->
id
[
target_id
].
prdaddru
,
tmpcip
);
outl
(
dev
->
id
[
c
][
target_id
].
prdaddr
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
tmpcip
=
tmpcip
-
2
;
outb
(
0x06
,
tmpcip
);
outb
(
0x06
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
tmpcip
=
tmpcip
-
2
;
tmport
=
workport
u
+
0x10
;
tmport
=
workport
+
0x10
;
outb
(
0x41
,
tmport
);
outb
(
0x41
,
tmport
);
tmport
+=
0x05
;
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmport
+=
2
;
k
=
dev
->
id
[
c
][
target_id
].
last_len
;
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
2
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
1
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
k
))[
0
]),
tmport
++
);
}
else
{
tmport
+=
5
;
}
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x20
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x20
),
tmport
);
dev
->
id
[
target_id
].
dirctu
=
0x20
;
dev
->
id
[
c
][
target_id
].
dirct
=
0x20
;
tmport
+=
0x03
;
tmport
+=
0x03
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x01
,
tmpcip
);
outb
(
0x01
,
tmpcip
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
}
tmport
-=
0x07
;
tmport
-=
0x07
;
if
(
i
==
0x0a
)
{
if
(
i
==
0x0a
)
{
...
@@ -434,25 +584,29 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -434,25 +584,29 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
}
else
{
}
else
{
outb
(
0x46
,
tmport
);
outb
(
0x46
,
tmport
);
}
}
dev
->
id
[
target_id
].
dirctu
=
0x00
;
dev
->
id
[
c
][
target_id
].
dirct
=
0x00
;
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
outb
(
0x00
,
tmport
++
);
tmport
+=
0x03
;
tmport
+=
0x03
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
out
;
goto
handled
;
}
else
{
}
else
{
//
tmport = workportu
+ 0x17;
//
tmport = workport
+ 0x17;
// inb(tmport);
// inb(tmport);
// dev->working = 0;
// dev->working[c] = 0;
dev
->
in_int
=
0
;
dev
->
in_int
[
c
]
=
0
;
goto
handled
;
}
}
out:
handled:
#ifdef ED_DBGP
printk
(
"atp870u_intr_handle exit
\n
"
);
#endif
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
}
}
/**
/**
* atp870u_queuecommand - Queue SCSI command
* atp870u_queuecommand - Queue SCSI command
* @req_p: request block
* @req_p: request block
...
@@ -460,24 +614,30 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
...
@@ -460,24 +614,30 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
*
*
* Queue a command to the ATP queue. Called with the host lock held.
* Queue a command to the ATP queue. Called with the host lock held.
*/
*/
int
atp870u_queuecommand
(
struct
scsi_cmnd
*
req_p
,
void
(
*
done
)
(
struct
scsi_cmnd
*
))
static
int
atp870u_queuecommand
(
struct
scsi_cmnd
*
req_p
,
void
(
*
done
)
(
struct
scsi_cmnd
*
))
{
{
unsigned
short
int
m
;
unsigned
char
c
;
unsigned
int
tmport
;
unsigned
int
tmport
,
m
;
struct
Scsi_Host
*
host
;
struct
atp_unit
*
dev
;
struct
atp_unit
*
dev
;
struct
Scsi_Host
*
host
;
if
(
req_p
->
device
->
channel
!=
0
)
{
c
=
req_p
->
device
->
channel
;
req_p
->
sense_buffer
[
0
]
=
0
;
req_p
->
resid
=
0
;
if
(
req_p
->
device
->
channel
>
1
)
{
req_p
->
result
=
0x00040000
;
req_p
->
result
=
0x00040000
;
done
(
req_p
);
done
(
req_p
);
#ifdef ED_DBGP
printk
(
"atp870u_queuecommand : req_p->device->channel > 1
\n
"
);
#endif
return
0
;
return
0
;
}
;
}
host
=
req_p
->
device
->
host
;
host
=
req_p
->
device
->
host
;
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
m
=
1
;
m
=
1
;
m
=
m
<<
req_p
->
device
->
id
;
m
=
m
<<
req_p
->
device
->
id
;
...
@@ -485,44 +645,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
...
@@ -485,44 +645,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
* Fake a timeout for missing targets
* Fake a timeout for missing targets
*/
*/
if
((
m
&
dev
->
active_id
u
)
==
0
)
{
if
((
m
&
dev
->
active_id
[
c
]
)
==
0
)
{
req_p
->
result
=
0x00040000
;
req_p
->
result
=
0x00040000
;
done
(
req_p
);
done
(
req_p
);
return
0
;
return
0
;
}
}
if
(
done
)
{
if
(
done
)
{
req_p
->
scsi_done
=
done
;
req_p
->
scsi_done
=
done
;
}
else
{
}
else
{
printk
(
KERN_WARNING
"atp870u_queuecommand: done can't be NULL
\n
"
);
#ifdef ED_DBGP
printk
(
"atp870u_queuecommand: done can't be NULL
\n
"
);
#endif
req_p
->
result
=
0
;
req_p
->
result
=
0
;
done
(
req_p
);
done
(
req_p
);
return
0
;
return
0
;
}
}
/*
/*
* Count new command
* Count new command
*/
*/
dev
->
quend
[
c
]
++
;
dev
->
quendu
++
;
if
(
dev
->
quend
[
c
]
>=
qcnt
)
{
if
(
dev
->
quendu
>=
qcnt
)
{
dev
->
quend
[
c
]
=
0
;
dev
->
quendu
=
0
;
}
}
/*
/*
* Check queue state
* Check queue state
*/
*/
if
(
dev
->
quhdu
==
dev
->
quendu
)
{
if
(
dev
->
quhd
[
c
]
==
dev
->
quend
[
c
])
{
if
(
dev
->
quendu
==
0
)
{
if
(
dev
->
quend
[
c
]
==
0
)
{
dev
->
quendu
=
qcnt
;
dev
->
quend
[
c
]
=
qcnt
;
}
}
dev
->
quendu
--
;
#ifdef ED_DBGP
printk
(
"atp870u_queuecommand : dev->quhd[c] == dev->quend[c]
\n
"
);
#endif
dev
->
quend
[
c
]
--
;
req_p
->
result
=
0x00020000
;
req_p
->
result
=
0x00020000
;
done
(
req_p
);
done
(
req_p
);
return
0
;
return
0
;
}
}
dev
->
querequ
[
dev
->
quendu
]
=
req_p
;
dev
->
quereq
[
c
][
dev
->
quend
[
c
]]
=
req_p
;
tmport
=
dev
->
ioport
+
0x1c
;
tmport
=
dev
->
ioport
[
c
]
+
0x1c
;
if
((
inb
(
tmport
)
==
0
)
&&
(
dev
->
in_int
==
0
)
&&
(
dev
->
in_snd
==
0
))
{
#ifdef ED_DBGP
send_s870
(
host
);
printk
(
"dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d
\n
"
,
dev
->
ioport
[
c
],
inb
(
tmport
),
c
,
dev
->
in_int
[
c
],
c
,
dev
->
in_snd
[
c
]);
}
#endif
if
((
inb
(
tmport
)
==
0
)
&&
(
dev
->
in_int
[
c
]
==
0
)
&&
(
dev
->
in_snd
[
c
]
==
0
))
{
#ifdef ED_DBGP
printk
(
"Call sent_s870(atp870u_queuecommand)
\n
"
);
#endif
send_s870
(
dev
,
c
);
}
#ifdef ED_DBGP
printk
(
"atp870u_queuecommand : exit
\n
"
);
#endif
return
0
;
return
0
;
}
}
...
@@ -535,141 +711,180 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
...
@@ -535,141 +711,180 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
*
*
* Caller holds the host lock.
* Caller holds the host lock.
*/
*/
void
send_s870
(
struct
atp_unit
*
dev
,
unsigned
char
c
)
static
void
send_s870
(
struct
Scsi_Host
*
host
)
{
{
unsigned
int
tmport
;
unsigned
int
tmport
;
struct
scsi_cmnd
*
workreq
u
;
struct
scsi_cmnd
*
workreq
;
unsigned
int
i
;
unsigned
int
i
;
//,k;
unsigned
char
j
,
target_id
;
unsigned
char
j
,
target_id
;
unsigned
char
*
prd
;
unsigned
char
*
prd
;
unsigned
short
int
tmpcip
,
w
;
unsigned
short
int
tmpcip
,
w
;
unsigned
long
l
;
unsigned
long
l
,
bttl
=
0
;
dma_addr_t
bttl
;
unsigned
int
workport
;
unsigned
int
workportu
;
struct
scatterlist
*
sgpnt
;
struct
scatterlist
*
sgpnt
;
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
unsigned
long
sg_count
;
int
sg_count
;
if
(
dev
->
in_snd
!=
0
)
{
if
(
dev
->
in_snd
[
c
]
!=
0
)
{
#ifdef ED_DBGP
printk
(
"cmnd in_snd
\n
"
);
#endif
return
;
return
;
}
}
dev
->
in_snd
=
1
;
#ifdef ED_DBGP
if
((
dev
->
last_cmd
!=
0xff
)
&&
((
dev
->
last_cmd
&
0x40
)
!=
0
))
{
printk
(
"Sent_s870 enter
\n
"
);
dev
->
last_cmd
&=
0x0f
;
#endif
workrequ
=
dev
->
id
[
dev
->
last_cmd
].
curr_req
;
dev
->
in_snd
[
c
]
=
1
;
if
(
workrequ
!=
NULL
)
{
/* check NULL pointer */
if
((
dev
->
last_cmd
[
c
]
!=
0xff
)
&&
((
dev
->
last_cmd
[
c
]
&
0x40
)
!=
0
))
{
dev
->
last_cmd
[
c
]
&=
0x0f
;
workreq
=
dev
->
id
[
c
][
dev
->
last_cmd
[
c
]].
curr_req
;
if
(
workreq
!=
NULL
)
{
/* check NULL pointer */
goto
cmd_subp
;
goto
cmd_subp
;
}
}
dev
->
last_cmd
=
0xff
;
dev
->
last_cmd
[
c
]
=
0xff
;
if
(
dev
->
quhd
u
==
dev
->
quendu
)
{
if
(
dev
->
quhd
[
c
]
==
dev
->
quend
[
c
]
)
{
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
}
}
}
}
if
((
dev
->
last_cmd
!=
0xff
)
&&
(
dev
->
working
!=
0
))
{
if
((
dev
->
last_cmd
[
c
]
!=
0xff
)
&&
(
dev
->
working
[
c
]
!=
0
))
{
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
}
}
dev
->
working
++
;
dev
->
working
[
c
]
++
;
j
=
dev
->
quhd
u
;
j
=
dev
->
quhd
[
c
]
;
dev
->
quhd
u
++
;
dev
->
quhd
[
c
]
++
;
if
(
dev
->
quhd
u
>=
qcnt
)
{
if
(
dev
->
quhd
[
c
]
>=
qcnt
)
{
dev
->
quhd
u
=
0
;
dev
->
quhd
[
c
]
=
0
;
}
}
workreq
u
=
dev
->
querequ
[
dev
->
quhdu
];
workreq
=
dev
->
quereq
[
c
][
dev
->
quhd
[
c
]
];
if
(
dev
->
id
[
workrequ
->
device
->
id
].
curr_req
==
0
)
{
if
(
dev
->
id
[
c
][
workreq
->
device
->
id
].
curr_req
==
0
)
{
dev
->
id
[
workrequ
->
device
->
id
].
curr_req
=
workrequ
;
dev
->
id
[
c
][
workreq
->
device
->
id
].
curr_req
=
workreq
;
dev
->
last_cmd
=
workrequ
->
device
->
id
;
dev
->
last_cmd
[
c
]
=
workreq
->
device
->
id
;
goto
cmd_subp
;
goto
cmd_subp
;
}
}
dev
->
quhd
u
=
j
;
dev
->
quhd
[
c
]
=
j
;
dev
->
working
--
;
dev
->
working
[
c
]
--
;
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
cmd_subp:
cmd_subp:
workport
u
=
dev
->
ioport
;
workport
=
dev
->
ioport
[
c
]
;
tmport
=
workport
u
+
0x1f
;
tmport
=
workport
+
0x1f
;
if
((
inb
(
tmport
)
&
0xb0
)
!=
0
)
{
if
((
inb
(
tmport
)
&
0xb0
)
!=
0
)
{
goto
abortsnd
;
goto
abortsnd
;
}
}
tmport
=
workport
u
+
0x1c
;
tmport
=
workport
+
0x1c
;
if
(
inb
(
tmport
)
==
0
)
{
if
(
inb
(
tmport
)
==
0
)
{
goto
oktosend
;
goto
oktosend
;
}
}
abortsnd:
abortsnd:
dev
->
last_cmd
|=
0x40
;
#ifdef ED_DBGP
dev
->
in_snd
=
0
;
printk
(
"Abort to Send
\n
"
);
#endif
dev
->
last_cmd
[
c
]
|=
0x40
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
oktosend:
oktosend:
memcpy
(
&
dev
->
ata_cdbu
[
0
],
&
workrequ
->
cmnd
[
0
],
workrequ
->
cmd_len
);
#ifdef ED_DBGP
if
(
dev
->
ata_cdbu
[
0
]
==
READ_CAPACITY
)
{
printk
(
"OK to Send
\n
"
);
if
(
workrequ
->
request_bufflen
>
8
)
{
printk
(
"CDB"
);
workrequ
->
request_bufflen
=
0x08
;
for
(
i
=
0
;
i
<
workreq
->
cmd_len
;
i
++
)
{
printk
(
" %x"
,
workreq
->
cmnd
[
i
]);
}
printk
(
"
\n
Channel = %d ID = %d LUN = %d
\n
"
,
c
,
workreq
->
device
->
id
,
workreq
->
device
->
lun
);
#endif
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
j
=
inb
(
dev
->
baseport
+
0x29
)
&
0xfe
;
outb
(
j
,
dev
->
baseport
+
0x29
);
dev
->
r1f
[
c
][
workreq
->
device
->
id
]
=
0
;
}
if
(
workreq
->
cmnd
[
0
]
==
READ_CAPACITY
)
{
if
(
workreq
->
request_bufflen
>
8
)
{
workreq
->
request_bufflen
=
0x08
;
}
}
}
}
if
(
dev
->
ata_cdbu
[
0
]
==
0x00
)
{
if
(
workreq
->
cmnd
[
0
]
==
0x00
)
{
workreq
u
->
request_bufflen
=
0
;
workreq
->
request_bufflen
=
0
;
}
}
tmport
=
workport
u
+
0x1b
;
tmport
=
workport
+
0x1b
;
j
=
0
;
j
=
0
;
target_id
=
workreq
u
->
device
->
id
;
target_id
=
workreq
->
device
->
id
;
/*
/*
* Wide ?
* Wide ?
*/
*/
w
=
1
;
w
=
1
;
w
=
w
<<
target_id
;
w
=
w
<<
target_id
;
if
((
w
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
w
&
dev
->
wide_id
[
c
]
)
!=
0
)
{
j
|=
0x01
;
j
|=
0x01
;
}
}
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
while
((
inb
(
tmport
)
&
0x01
)
!=
j
)
{
while
((
inb
(
tmport
)
&
0x01
)
!=
j
)
{
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
#ifdef ED_DBGP
printk
(
"send_s870 while loop 1
\n
"
);
#endif
}
}
/*
/*
* Write the command
* Write the command
*/
*/
tmport
=
workport
u
;
tmport
=
workport
;
outb
(
workreq
u
->
cmd_len
,
tmport
++
);
outb
(
workreq
->
cmd_len
,
tmport
++
);
outb
(
0x2c
,
tmport
++
);
outb
(
0x2c
,
tmport
++
);
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
outb
(
0x7f
,
tmport
++
);
}
else
{
outb
(
0xcf
,
tmport
++
);
outb
(
0xcf
,
tmport
++
);
for
(
i
=
0
;
i
<
workrequ
->
cmd_len
;
i
++
)
{
outb
(
dev
->
ata_cdbu
[
i
],
tmport
++
);
}
}
tmport
=
workportu
+
0x0f
;
for
(
i
=
0
;
i
<
workreq
->
cmd_len
;
i
++
)
{
outb
(
workrequ
->
device
->
lun
,
tmport
);
outb
(
workreq
->
cmnd
[
i
],
tmport
++
);
}
tmport
=
workport
+
0x0f
;
outb
(
workreq
->
device
->
lun
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
/*
/*
* Write the target
* Write the target
*/
*/
outb
(
dev
->
id
[
target_id
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
c
][
target_id
].
devsp
,
tmport
++
);
#ifdef ED_DBGP
printk
(
"dev->id[%d][%d].devsp = %2x
\n
"
,
c
,
target_id
,
dev
->
id
[
c
][
target_id
].
devsp
);
#endif
/*
/*
* Figure out the transfer size
* Figure out the transfer size
*/
*/
if
(
workrequ
->
use_sg
)
{
if
(
workreq
->
use_sg
)
{
#ifdef ED_DBGP
printk
(
"Using SGL
\n
"
);
#endif
l
=
0
;
l
=
0
;
sgpnt
=
(
struct
scatterlist
*
)
workrequ
->
request_buffer
;
sg_count
=
pci_map_sg
(
dev
->
pdev
,
sgpnt
,
workrequ
->
use_sg
,
sgpnt
=
(
struct
scatterlist
*
)
workreq
->
request_buffer
;
workrequ
->
sc_data_direction
);
sg_count
=
pci_map_sg
(
dev
->
pdev
,
sgpnt
,
workreq
->
use_sg
,
for
(
i
=
0
;
i
<
workrequ
->
use_sg
;
i
++
)
{
workreq
->
sc_data_direction
);
if
(
sgpnt
[
i
].
length
==
0
||
workrequ
->
use_sg
>
ATP870U_SCATTER
)
{
for
(
i
=
0
;
i
<
workreq
->
use_sg
;
i
++
)
{
if
(
sgpnt
[
i
].
length
==
0
||
workreq
->
use_sg
>
ATP870U_SCATTER
)
{
panic
(
"Foooooooood fight!"
);
panic
(
"Foooooooood fight!"
);
}
}
l
+=
sgpnt
[
i
].
length
;
l
+=
sgpnt
[
i
].
length
;
}
}
}
else
if
(
workrequ
->
request_bufflen
&&
workrequ
->
sc_data_direction
!=
PCI_DMA_NONE
)
{
#ifdef ED_DBGP
workrequ
->
SCp
.
dma_handle
=
pci_map_single
(
dev
->
pdev
,
printk
(
"send_s870: workreq->use_sg %d, sg_count %d l %8ld
\n
"
,
workreq
->
use_sg
,
sg_count
,
l
);
workrequ
->
request_buffer
,
#endif
workrequ
->
request_bufflen
,
}
else
if
(
workreq
->
request_bufflen
&&
workreq
->
sc_data_direction
!=
PCI_DMA_NONE
)
{
workrequ
->
sc_data_direction
);
#ifdef ED_DBGP
l
=
workrequ
->
request_bufflen
;
printk
(
"Not using SGL
\n
"
);
}
#endif
else
l
=
0
;
workreq
->
SCp
.
dma_handle
=
pci_map_single
(
dev
->
pdev
,
workreq
->
request_buffer
,
workreq
->
request_bufflen
,
workreq
->
sc_data_direction
);
l
=
workreq
->
request_bufflen
;
#ifdef ED_DBGP
printk
(
"send_s870: workreq->use_sg %d, l %8ld
\n
"
,
workreq
->
use_sg
,
l
);
#endif
}
else
l
=
0
;
/*
/*
* Write transfer size
* Write transfer size
*/
*/
...
@@ -677,8 +892,11 @@ static void send_s870(struct Scsi_Host *host)
...
@@ -677,8 +892,11 @@ static void send_s870(struct Scsi_Host *host)
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
l
))[
1
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
l
))[
1
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
l
))[
0
]),
tmport
++
);
outb
((
unsigned
char
)
(((
unsigned
char
*
)
(
&
l
))[
0
]),
tmport
++
);
j
=
target_id
;
j
=
target_id
;
dev
->
id
[
j
].
last_lenu
=
l
;
dev
->
id
[
c
][
j
].
last_len
=
l
;
dev
->
id
[
j
].
tran_lenu
=
0
;
dev
->
id
[
c
][
j
].
tran_len
=
0
;
#ifdef ED_DBGP
printk
(
"dev->id[%2d][%2d].last_len = %d
\n
"
,
c
,
j
,
dev
->
id
[
c
][
j
].
last_len
);
#endif
/*
/*
* Flip the wide bits
* Flip the wide bits
*/
*/
...
@@ -688,40 +906,46 @@ static void send_s870(struct Scsi_Host *host)
...
@@ -688,40 +906,46 @@ static void send_s870(struct Scsi_Host *host)
/*
/*
* Check transfer direction
* Check transfer direction
*/
*/
if
(
workreq
u
->
sc_data_direction
==
DMA_TO_DEVICE
)
{
if
(
workreq
->
sc_data_direction
==
DMA_TO_DEVICE
)
{
outb
((
unsigned
char
)
(
j
|
0x20
),
tmport
++
);
outb
((
unsigned
char
)
(
j
|
0x20
),
tmport
++
);
}
else
{
}
else
{
outb
(
j
,
tmport
++
);
outb
(
j
,
tmport
++
);
}
}
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x80
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x80
),
tmport
);
outb
(
0x80
,
tmport
);
outb
(
0x80
,
tmport
);
tmport
=
workport
u
+
0x1c
;
tmport
=
workport
+
0x1c
;
dev
->
id
[
target_id
].
dirctu
=
0
;
dev
->
id
[
c
][
target_id
].
dirct
=
0
;
if
(
l
==
0
)
{
if
(
l
==
0
)
{
if
(
inb
(
tmport
)
==
0
)
{
if
(
inb
(
tmport
)
==
0
)
{
tmport
=
workportu
+
0x18
;
tmport
=
workport
+
0x18
;
#ifdef ED_DBGP
printk
(
"change SCSI_CMD_REG 0x08
\n
"
);
#endif
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
}
else
{
}
else
{
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
}
}
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
}
}
tmpcip
=
dev
->
pciport
;
tmpcip
=
dev
->
pciport
[
c
]
;
prd
=
dev
->
id
[
target_id
].
prd_tableu
;
prd
=
dev
->
id
[
c
][
target_id
].
prd_table
;
dev
->
id
[
target_id
].
prd_posu
=
prd
;
dev
->
id
[
c
][
target_id
].
prd_pos
=
prd
;
/*
/*
* Now write the request list. Either as scatter/gather or as
* Now write the request list. Either as scatter/gather or as
* a linear chain.
* a linear chain.
*/
*/
if
(
workreq
u
->
use_sg
)
{
if
(
workreq
->
use_sg
)
{
sgpnt
=
(
struct
scatterlist
*
)
workreq
u
->
request_buffer
;
sgpnt
=
(
struct
scatterlist
*
)
workreq
->
request_buffer
;
i
=
0
;
i
=
0
;
for
(
j
=
0
;
j
<
workreq
u
->
use_sg
;
j
++
)
{
for
(
j
=
0
;
j
<
workreq
->
use_sg
;
j
++
)
{
bttl
=
sg_dma_address
(
&
sgpnt
[
j
]);
bttl
=
sg_dma_address
(
&
sgpnt
[
j
]);
l
=
sg_dma_len
(
&
sgpnt
[
j
]);
l
=
sg_dma_len
(
&
sgpnt
[
j
]);
#ifdef ED_DBGP
printk
(
"1. bttl %x, l %x
\n
"
,
bttl
,
l
);
#endif
while
(
l
>
0x10000
)
{
while
(
l
>
0x10000
)
{
(((
u16
*
)
(
prd
))[
i
+
3
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
3
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
2
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
2
])
=
0x0000
;
...
@@ -736,13 +960,20 @@ static void send_s870(struct Scsi_Host *host)
...
@@ -736,13 +960,20 @@ static void send_s870(struct Scsi_Host *host)
i
+=
0x04
;
i
+=
0x04
;
}
}
(((
u16
*
)
(
prd
))[
i
-
1
])
=
cpu_to_le16
(
0x8000
);
(((
u16
*
)
(
prd
))[
i
-
1
])
=
cpu_to_le16
(
0x8000
);
#ifdef ED_DBGP
printk
(
"prd %4x %4x %4x %4x
\n
"
,(((
unsigned
short
int
*
)
prd
)[
0
]),(((
unsigned
short
int
*
)
prd
)[
1
]),(((
unsigned
short
int
*
)
prd
)[
2
]),(((
unsigned
short
int
*
)
prd
)[
3
]));
printk
(
"2. bttl %x, l %x
\n
"
,
bttl
,
l
);
#endif
}
else
{
}
else
{
/*
/*
* For a linear request write a chain of blocks
* For a linear request write a chain of blocks
*/
*/
bttl
=
workreq
u
->
SCp
.
dma_handle
;
bttl
=
workreq
->
SCp
.
dma_handle
;
l
=
workreq
u
->
request_bufflen
;
l
=
workreq
->
request_bufflen
;
i
=
0
;
i
=
0
;
#ifdef ED_DBGP
printk
(
"3. bttl %x, l %x
\n
"
,
bttl
,
l
);
#endif
while
(
l
>
0x10000
)
{
while
(
l
>
0x10000
)
{
(((
u16
*
)
(
prd
))[
i
+
3
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
3
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
2
])
=
0x0000
;
(((
u16
*
)
(
prd
))[
i
+
2
])
=
0x0000
;
...
@@ -754,52 +985,81 @@ static void send_s870(struct Scsi_Host *host)
...
@@ -754,52 +985,81 @@ static void send_s870(struct Scsi_Host *host)
(((
u16
*
)
(
prd
))[
i
+
3
])
=
cpu_to_le16
(
0x8000
);
(((
u16
*
)
(
prd
))[
i
+
3
])
=
cpu_to_le16
(
0x8000
);
(((
u16
*
)
(
prd
))[
i
+
2
])
=
cpu_to_le16
(
l
);
(((
u16
*
)
(
prd
))[
i
+
2
])
=
cpu_to_le16
(
l
);
(((
u32
*
)
(
prd
))[
i
>>
1
])
=
cpu_to_le32
(
bttl
);
(((
u32
*
)
(
prd
))[
i
>>
1
])
=
cpu_to_le32
(
bttl
);
}
#ifdef ED_DBGP
tmpcip
=
tmpcip
+
4
;
printk
(
"prd %4x %4x %4x %4x
\n
"
,(((
unsigned
short
int
*
)
prd
)[
0
]),(((
unsigned
short
int
*
)
prd
)[
1
]),(((
unsigned
short
int
*
)
prd
)[
2
]),(((
unsigned
short
int
*
)
prd
)[
3
]));
dev
->
id
[
target_id
].
prdaddru
=
dev
->
id
[
target_id
].
prd_phys
;
printk
(
"4. bttl %x, l %x
\n
"
,
bttl
,
l
);
outl
(
dev
->
id
[
target_id
].
prd_phys
,
tmpcip
);
#endif
}
tmpcip
+=
4
;
#ifdef ED_DBGP
printk
(
"send_s870: prdaddr_1 0x%8x
\n
"
,
dev
->
id
[
c
][
target_id
].
prdaddr
);
#endif
dev
->
id
[
c
][
target_id
].
prdaddr
=
virt_to_bus
(
dev
->
id
[
c
][
target_id
].
prd_table
);
#ifdef ED_DBGP
printk
(
"send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d
\n
"
,
dev
->
id
[
c
][
target_id
].
prdaddr
,
tmpcip
,
target_id
);
#endif
outl
(
dev
->
id
[
c
][
target_id
].
prdaddr
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
tmpcip
=
tmpcip
-
2
;
outb
(
0x06
,
tmpcip
);
outb
(
0x06
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
outb
(
0x00
,
tmpcip
);
tmpcip
=
tmpcip
-
2
;
if
(
dev
->
dev_id
==
ATP885_DEVID
)
{
tmpcip
--
;
if
(
dev
->
deviceid
!=
0x8081
)
{
j
=
inb
(
tmpcip
)
&
0xf3
;
tmport
=
workportu
+
0x3a
;
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
if
((
dev
->
ata_cdbu
[
0
]
==
0x08
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x28
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x0a
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x2a
))
{
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
outb
((
inb
(
tmport
)
&
0xf3
)
|
0x08
,
tmport
);
j
|=
0x0c
;
}
outb
(
j
,
tmpcip
);
tmpcip
--
;
}
else
if
((
dev
->
dev_id
==
ATP880_DEVID1
)
||
(
dev
->
dev_id
==
ATP880_DEVID2
))
{
tmpcip
=
tmpcip
-
2
;
tmport
=
workport
-
0x05
;
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0x3f
)
|
0xc0
),
tmport
);
}
else
{
}
else
{
outb
(
inb
(
tmport
)
&
0xf3
,
tmport
);
outb
(
(
unsigned
char
)
(
inb
(
tmport
)
&
0x3f
)
,
tmport
);
}
}
}
else
{
}
else
{
tmport
=
workportu
-
0x05
;
tmpcip
=
tmpcip
-
2
;
if
((
dev
->
ata_cdbu
[
0
]
==
0x08
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x28
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x0a
)
||
(
dev
->
ata_cdbu
[
0
]
==
0x2a
))
{
tmport
=
workport
+
0x3a
;
outb
((
unsigned
char
)
((
inb
(
tmport
)
&
0x3f
)
|
0xc0
),
tmport
);
if
((
workreq
->
cmnd
[
0
]
==
0x08
)
||
(
workreq
->
cmnd
[
0
]
==
0x28
)
||
(
workreq
->
cmnd
[
0
]
==
0x0a
)
||
(
workreq
->
cmnd
[
0
]
==
0x2a
))
{
outb
((
inb
(
tmport
)
&
0xf3
)
|
0x08
,
tmport
);
}
else
{
}
else
{
outb
(
(
unsigned
char
)
(
inb
(
tmport
)
&
0x3f
)
,
tmport
);
outb
(
inb
(
tmport
)
&
0xf3
,
tmport
);
}
}
}
}
tmport
=
workport
u
+
0x1c
;
tmport
=
workport
+
0x1c
;
if
(
workrequ
->
sc_data_direction
==
DMA_TO_DEVICE
)
{
if
(
workreq
->
sc_data_direction
==
DMA_TO_DEVICE
)
{
dev
->
id
[
target_id
].
dirctu
=
0x20
;
dev
->
id
[
c
][
target_id
].
dirct
=
0x20
;
if
(
inb
(
tmport
)
==
0
)
{
if
(
inb
(
tmport
)
==
0
)
{
tmport
=
workport
u
+
0x18
;
tmport
=
workport
+
0x18
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x01
,
tmpcip
);
outb
(
0x01
,
tmpcip
);
#ifdef ED_DBGP
printk
(
"start DMA(to target)
\n
"
);
#endif
}
else
{
}
else
{
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
}
}
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
return
;
}
}
if
(
inb
(
tmport
)
==
0
)
{
if
(
inb
(
tmport
)
==
0
)
{
tmport
=
workport
u
+
0x18
;
tmport
=
workport
+
0x18
;
outb
(
0x08
,
tmport
);
outb
(
0x08
,
tmport
);
outb
(
0x09
,
tmpcip
);
outb
(
0x09
,
tmpcip
);
#ifdef ED_DBGP
printk
(
"start DMA(to host)
\n
"
);
#endif
}
else
{
}
else
{
dev
->
last_cmd
|=
0x40
;
dev
->
last_cmd
[
c
]
|=
0x40
;
}
}
dev
->
in_snd
=
0
;
dev
->
in_snd
[
c
]
=
0
;
return
;
}
}
static
unsigned
char
fun_scam
(
struct
atp_unit
*
dev
,
unsigned
short
int
*
val
)
static
unsigned
char
fun_scam
(
struct
atp_unit
*
dev
,
unsigned
short
int
*
val
)
...
@@ -808,7 +1068,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
...
@@ -808,7 +1068,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
unsigned
short
int
i
,
k
;
unsigned
short
int
i
,
k
;
unsigned
char
j
;
unsigned
char
j
;
tmport
=
dev
->
ioport
+
0x1c
;
tmport
=
dev
->
ioport
[
0
]
+
0x1c
;
outw
(
*
val
,
tmport
);
outw
(
*
val
,
tmport
);
FUN_D7:
FUN_D7:
for
(
i
=
0
;
i
<
10
;
i
++
)
{
/* stable >= bus settle delay(400 ns) */
for
(
i
=
0
;
i
<
10
;
i
++
)
{
/* stable >= bus settle delay(400 ns) */
...
@@ -863,24 +1123,24 @@ static void tscam(struct Scsi_Host *host)
...
@@ -863,24 +1123,24 @@ static void tscam(struct Scsi_Host *host)
}
}
*/
*/
tmport
=
dev
->
ioport
+
1
;
tmport
=
dev
->
ioport
[
0
]
+
1
;
outb
(
0x08
,
tmport
++
);
outb
(
0x08
,
tmport
++
);
outb
(
0x7f
,
tmport
);
outb
(
0x7f
,
tmport
);
tmport
=
dev
->
ioport
+
0x11
;
tmport
=
dev
->
ioport
[
0
]
+
0x11
;
outb
(
0x20
,
tmport
);
outb
(
0x20
,
tmport
);
if
((
dev
->
scam_on
&
0x40
)
==
0
)
{
if
((
dev
->
scam_on
&
0x40
)
==
0
)
{
return
;
return
;
}
}
m
=
1
;
m
=
1
;
m
<<=
dev
->
host_id
u
;
m
<<=
dev
->
host_id
[
0
]
;
j
=
16
;
j
=
16
;
if
(
dev
->
chip_ver
u
<
4
)
{
if
(
dev
->
chip_ver
<
4
)
{
m
|=
0xff00
;
m
|=
0xff00
;
j
=
8
;
j
=
8
;
}
}
assignid_map
=
m
;
assignid_map
=
m
;
tmport
=
dev
->
ioport
+
0x02
;
tmport
=
dev
->
ioport
[
0
]
+
0x02
;
outb
(
0x02
,
tmport
++
);
/* 2*2=4ms,3EH 2/32*3E=3.9ms */
outb
(
0x02
,
tmport
++
);
/* 2*2=4ms,3EH 2/32*3E=3.9ms */
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
...
@@ -895,7 +1155,7 @@ static void tscam(struct Scsi_Host *host)
...
@@ -895,7 +1155,7 @@ static void tscam(struct Scsi_Host *host)
if
((
m
&
assignid_map
)
!=
0
)
{
if
((
m
&
assignid_map
)
!=
0
)
{
continue
;
continue
;
}
}
tmport
=
dev
->
ioport
+
0x0f
;
tmport
=
dev
->
ioport
[
0
]
+
0x0f
;
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
...
@@ -907,14 +1167,14 @@ static void tscam(struct Scsi_Host *host)
...
@@ -907,14 +1167,14 @@ static void tscam(struct Scsi_Host *host)
k
=
i
;
k
=
i
;
}
}
outb
(
k
,
tmport
++
);
outb
(
k
,
tmport
++
);
tmport
=
dev
->
ioport
+
0x1b
;
tmport
=
dev
->
ioport
[
0
]
+
0x1b
;
if
(
dev
->
chip_ver
u
==
4
)
{
if
(
dev
->
chip_ver
==
4
)
{
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
}
else
{
}
else
{
outb
(
0x00
,
tmport
);
outb
(
0x00
,
tmport
);
}
}
wait_rdyok:
wait_rdyok:
tmport
=
dev
->
ioport
+
0x18
;
tmport
=
dev
->
ioport
[
0
]
+
0x18
;
outb
(
0x09
,
tmport
);
outb
(
0x09
,
tmport
);
tmport
+=
0x07
;
tmport
+=
0x07
;
...
@@ -925,22 +1185,22 @@ static void tscam(struct Scsi_Host *host)
...
@@ -925,22 +1185,22 @@ static void tscam(struct Scsi_Host *host)
if
((
k
==
0x85
)
||
(
k
==
0x42
))
{
if
((
k
==
0x85
)
||
(
k
==
0x42
))
{
continue
;
continue
;
}
}
tmport
=
dev
->
ioport
+
0x10
;
tmport
=
dev
->
ioport
[
0
]
+
0x10
;
outb
(
0x41
,
tmport
);
outb
(
0x41
,
tmport
);
goto
wait_rdyok
;
goto
wait_rdyok
;
}
}
assignid_map
|=
m
;
assignid_map
|=
m
;
}
}
tmport
=
dev
->
ioport
+
0x02
;
tmport
=
dev
->
ioport
[
0
]
+
0x02
;
outb
(
0x7f
,
tmport
);
outb
(
0x7f
,
tmport
);
tmport
=
dev
->
ioport
+
0x1b
;
tmport
=
dev
->
ioport
[
0
]
+
0x1b
;
outb
(
0x02
,
tmport
);
outb
(
0x02
,
tmport
);
outb
(
0
,
0x80
);
outb
(
0
,
0x80
);
val
=
0x0080
;
/* bsy */
val
=
0x0080
;
/* bsy */
tmport
=
dev
->
ioport
+
0x1c
;
tmport
=
dev
->
ioport
[
0
]
+
0x1c
;
outw
(
val
,
tmport
);
outw
(
val
,
tmport
);
val
|=
0x0040
;
/* sel */
val
|=
0x0040
;
/* sel */
outw
(
val
,
tmport
);
outw
(
val
,
tmport
);
...
@@ -984,7 +1244,7 @@ static void tscam(struct Scsi_Host *host)
...
@@ -984,7 +1244,7 @@ static void tscam(struct Scsi_Host *host)
if
((
inb
(
tmport
)
&
0x80
)
==
0x00
)
{
/* bsy ? */
if
((
inb
(
tmport
)
&
0x80
)
==
0x00
)
{
/* bsy ? */
outw
(
0
,
tmport
--
);
outw
(
0
,
tmport
--
);
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
=
dev
->
ioport
+
0x15
;
tmport
=
dev
->
ioport
[
0
]
+
0x15
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x03
;
tmport
+=
0x03
;
outb
(
0x09
,
tmport
);
outb
(
0x09
,
tmport
);
...
@@ -1085,7 +1345,7 @@ static void tscam(struct Scsi_Host *host)
...
@@ -1085,7 +1345,7 @@ static void tscam(struct Scsi_Host *host)
}
}
static
void
is870
(
struct
Scsi_Host
*
host
,
unsigned
int
wkport
)
void
is870
(
struct
atp_unit
*
dev
,
unsigned
int
wkport
)
{
{
unsigned
int
tmport
;
unsigned
int
tmport
;
unsigned
char
i
,
j
,
k
,
rmb
,
n
;
unsigned
char
i
,
j
,
k
,
rmb
,
n
;
...
@@ -1097,26 +1357,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1097,26 +1357,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
static
unsigned
char
synu
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0c
,
0x0e
};
static
unsigned
char
synu
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0c
,
0x0e
};
static
unsigned
char
synw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0c
,
0x07
};
static
unsigned
char
synw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0c
,
0x07
};
static
unsigned
char
wide
[
6
]
=
{
0x80
,
1
,
2
,
3
,
1
,
0
};
static
unsigned
char
wide
[
6
]
=
{
0x80
,
1
,
2
,
3
,
1
,
0
};
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
tmport
=
wkport
+
0x3a
;
tmport
=
wkport
+
0x3a
;
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x10
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
|
0x10
),
tmport
);
for
(
i
=
0
;
i
<
16
;
i
++
)
{
for
(
i
=
0
;
i
<
16
;
i
++
)
{
if
((
dev
->
chip_ver
u
!=
4
)
&&
(
i
>
7
))
{
if
((
dev
->
chip_ver
!=
4
)
&&
(
i
>
7
))
{
break
;
break
;
}
}
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
if
((
m
&
dev
->
active_id
u
)
!=
0
)
{
if
((
m
&
dev
->
active_id
[
0
]
)
!=
0
)
{
continue
;
continue
;
}
}
if
(
i
==
dev
->
host_id
u
)
{
if
(
i
==
dev
->
host_id
[
0
]
)
{
printk
(
KERN_INFO
" ID: %2d Host Adapter
\n
"
,
dev
->
host_id
u
);
printk
(
KERN_INFO
" ID: %2d Host Adapter
\n
"
,
dev
->
host_id
[
0
]
);
continue
;
continue
;
}
}
tmport
=
wkport
+
0x1b
;
tmport
=
wkport
+
0x1b
;
if
(
dev
->
chip_ver
u
==
4
)
{
if
(
dev
->
chip_ver
==
4
)
{
outb
(
0x01
,
tmport
);
outb
(
0x01
,
tmport
);
}
else
{
}
else
{
outb
(
0x00
,
tmport
);
outb
(
0x00
,
tmport
);
...
@@ -1133,7 +1392,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1133,7 +1392,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -1152,7 +1411,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1152,7 +1411,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
continue
;
continue
;
}
}
while
(
inb
(
tmport
)
!=
0x8e
);
while
(
inb
(
tmport
)
!=
0x8e
);
dev
->
active_id
u
|=
m
;
dev
->
active_id
[
0
]
|=
m
;
tmport
=
wkport
+
0x10
;
tmport
=
wkport
+
0x10
;
outb
(
0x30
,
tmport
);
outb
(
0x30
,
tmport
);
...
@@ -1182,7 +1441,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1182,7 +1441,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x07
;
tmport
+=
0x07
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
inqd
[
6
],
tmport
++
);
outb
(
inqd
[
6
],
tmport
++
);
outb
(
inqd
[
7
],
tmport
++
);
outb
(
inqd
[
7
],
tmport
++
);
...
@@ -1196,7 +1455,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1196,7 +1455,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
}
}
while
(
inb
(
tmport
)
!=
0x8e
);
while
(
inb
(
tmport
)
!=
0x8e
);
tmport
=
wkport
+
0x1b
;
tmport
=
wkport
+
0x1b
;
if
(
dev
->
chip_ver
u
==
4
)
{
if
(
dev
->
chip_ver
==
4
)
{
outb
(
0x00
,
tmport
);
outb
(
0x00
,
tmport
);
}
}
tmport
=
wkport
+
0x18
;
tmport
=
wkport
+
0x18
;
...
@@ -1236,16 +1495,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1236,16 +1495,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
inq_ok:
inq_ok:
mbuf
[
36
]
=
0
;
mbuf
[
36
]
=
0
;
printk
(
KERN_INFO
" ID: %2d %s
\n
"
,
i
,
&
mbuf
[
8
]);
printk
(
KERN_INFO
" ID: %2d %s
\n
"
,
i
,
&
mbuf
[
8
]);
dev
->
id
[
i
].
devtypeu
=
mbuf
[
0
];
dev
->
id
[
0
][
i
].
devtype
=
mbuf
[
0
];
rmb
=
mbuf
[
1
];
rmb
=
mbuf
[
1
];
n
=
mbuf
[
7
];
n
=
mbuf
[
7
];
if
(
dev
->
chip_ver
u
!=
4
)
{
if
(
dev
->
chip_ver
!=
4
)
{
goto
not_wide
;
goto
not_wide
;
}
}
if
((
mbuf
[
7
]
&
0x60
)
==
0
)
{
if
((
mbuf
[
7
]
&
0x60
)
==
0
)
{
goto
not_wide
;
goto
not_wide
;
}
}
if
((
dev
->
global_map
&
0x20
)
==
0
)
{
if
((
dev
->
global_map
[
0
]
&
0x20
)
==
0
)
{
goto
not_wide
;
goto
not_wide
;
}
}
tmport
=
wkport
+
0x1b
;
tmport
=
wkport
+
0x1b
;
...
@@ -1260,7 +1519,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1260,7 +1519,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -1386,16 +1645,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1386,16 +1645,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
}
}
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
dev
->
wide_id
u
|=
m
;
dev
->
wide_id
[
0
]
|=
m
;
not_wide:
not_wide:
if
((
dev
->
id
[
i
].
devtypeu
==
0x00
)
||
(
dev
->
id
[
i
].
devtypeu
==
0x07
)
||
((
dev
->
id
[
i
].
devtypeu
==
0x05
)
&&
((
n
&
0x10
)
!=
0
)))
{
if
((
dev
->
id
[
0
][
i
].
devtype
==
0x00
)
||
(
dev
->
id
[
0
][
i
].
devtype
==
0x07
)
||
((
dev
->
id
[
0
][
i
].
devtype
==
0x05
)
&&
((
n
&
0x10
)
!=
0
)))
{
goto
set_sync
;
goto
set_sync
;
}
}
continue
;
continue
;
set_sync:
set_sync:
tmport
=
wkport
+
0x1b
;
tmport
=
wkport
+
0x1b
;
j
=
0
;
j
=
0
;
if
((
m
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
m
&
dev
->
wide_id
[
0
]
)
!=
0
)
{
j
|=
0x01
;
j
|=
0x01
;
}
}
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
...
@@ -1409,7 +1668,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1409,7 +1668,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -1434,10 +1693,10 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1434,10 +1693,10 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
tmport
-=
0x06
;
if
((
m
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
m
&
dev
->
wide_id
[
0
]
)
!=
0
)
{
outb
(
synw
[
j
++
],
tmport
);
outb
(
synw
[
j
++
],
tmport
);
}
else
{
}
else
{
if
((
m
&
dev
->
ultra_map
)
!=
0
)
{
if
((
m
&
dev
->
ultra_map
[
0
]
)
!=
0
)
{
outb
(
synu
[
j
++
],
tmport
);
outb
(
synu
[
j
++
],
tmport
);
}
else
{
}
else
{
outb
(
synn
[
j
++
],
tmport
);
outb
(
synn
[
j
++
],
tmport
);
...
@@ -1551,7 +1810,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1551,7 +1810,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
if
(
mbuf
[
4
]
>
0x0c
)
{
if
(
mbuf
[
4
]
>
0x0c
)
{
mbuf
[
4
]
=
0x0c
;
mbuf
[
4
]
=
0x0c
;
}
}
dev
->
id
[
i
].
devspu
=
mbuf
[
4
];
dev
->
id
[
0
][
i
].
devsp
=
mbuf
[
4
];
if
((
mbuf
[
3
]
<
0x0d
)
&&
(
rmb
==
0
))
{
if
((
mbuf
[
3
]
<
0x0d
)
&&
(
rmb
==
0
))
{
j
=
0xa0
;
j
=
0xa0
;
goto
set_syn_ok
;
goto
set_syn_ok
;
...
@@ -1570,13 +1829,13 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1570,13 +1829,13 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
}
}
j
=
0x60
;
j
=
0x60
;
set_syn_ok:
set_syn_ok:
dev
->
id
[
i
].
devspu
=
(
dev
->
id
[
i
].
devspu
&
0x0f
)
|
j
;
dev
->
id
[
0
][
i
].
devsp
=
(
dev
->
id
[
0
][
i
].
devsp
&
0x0f
)
|
j
;
}
}
tmport
=
wkport
+
0x3a
;
tmport
=
wkport
+
0x3a
;
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0xef
),
tmport
);
outb
((
unsigned
char
)
(
inb
(
tmport
)
&
0xef
),
tmport
);
}
}
static
void
is880
(
struct
Scsi_Host
*
host
,
unsigned
int
wkport
)
static
void
is880
(
struct
atp_unit
*
dev
,
unsigned
int
wkport
)
{
{
unsigned
int
tmport
;
unsigned
int
tmport
;
unsigned
char
i
,
j
,
k
,
rmb
,
n
,
lvdmode
;
unsigned
char
i
,
j
,
k
,
rmb
,
n
,
lvdmode
;
...
@@ -1590,18 +1849,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1590,18 +1849,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
unsigned
char
synuw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0a
,
0x0e
};
unsigned
char
synuw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0a
,
0x0e
};
static
unsigned
char
wide
[
6
]
=
{
0x80
,
1
,
2
,
3
,
1
,
0
};
static
unsigned
char
wide
[
6
]
=
{
0x80
,
1
,
2
,
3
,
1
,
0
};
static
unsigned
char
u3
[
9
]
=
{
0x80
,
1
,
6
,
4
,
0x09
,
00
,
0x0e
,
0x01
,
0x02
};
static
unsigned
char
u3
[
9
]
=
{
0x80
,
1
,
6
,
4
,
0x09
,
00
,
0x0e
,
0x01
,
0x02
};
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
lvdmode
=
inb
(
wkport
+
0x3f
)
&
0x40
;
lvdmode
=
inb
(
wkport
+
0x3f
)
&
0x40
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
for
(
i
=
0
;
i
<
16
;
i
++
)
{
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
if
((
m
&
dev
->
active_id
u
)
!=
0
)
{
if
((
m
&
dev
->
active_id
[
0
]
)
!=
0
)
{
continue
;
continue
;
}
}
if
(
i
==
dev
->
host_id
u
)
{
if
(
i
==
dev
->
host_id
[
0
]
)
{
printk
(
KERN_INFO
" ID: %2d Host Adapter
\n
"
,
dev
->
host_id
u
);
printk
(
KERN_INFO
" ID: %2d Host Adapter
\n
"
,
dev
->
host_id
[
0
]
);
continue
;
continue
;
}
}
tmport
=
wkport
+
0x5b
;
tmport
=
wkport
+
0x5b
;
...
@@ -1618,7 +1876,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1618,7 +1876,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -1637,7 +1895,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1637,7 +1895,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
continue
;
continue
;
}
}
while
(
inb
(
tmport
)
!=
0x8e
);
while
(
inb
(
tmport
)
!=
0x8e
);
dev
->
active_id
u
|=
m
;
dev
->
active_id
[
0
]
|=
m
;
tmport
=
wkport
+
0x50
;
tmport
=
wkport
+
0x50
;
outb
(
0x30
,
tmport
);
outb
(
0x30
,
tmport
);
...
@@ -1667,7 +1925,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1667,7 +1925,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x07
;
tmport
+=
0x07
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
inqd
[
6
],
tmport
++
);
outb
(
inqd
[
6
],
tmport
++
);
outb
(
inqd
[
7
],
tmport
++
);
outb
(
inqd
[
7
],
tmport
++
);
...
@@ -1719,19 +1977,19 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1719,19 +1977,19 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
inq_ok:
inq_ok:
mbuf
[
36
]
=
0
;
mbuf
[
36
]
=
0
;
printk
(
KERN_INFO
" ID: %2d %s
\n
"
,
i
,
&
mbuf
[
8
]);
printk
(
KERN_INFO
" ID: %2d %s
\n
"
,
i
,
&
mbuf
[
8
]);
dev
->
id
[
i
].
devtypeu
=
mbuf
[
0
];
dev
->
id
[
0
][
i
].
devtype
=
mbuf
[
0
];
rmb
=
mbuf
[
1
];
rmb
=
mbuf
[
1
];
n
=
mbuf
[
7
];
n
=
mbuf
[
7
];
if
((
mbuf
[
7
]
&
0x60
)
==
0
)
{
if
((
mbuf
[
7
]
&
0x60
)
==
0
)
{
goto
not_wide
;
goto
not_wide
;
}
}
if
((
i
<
8
)
&&
((
dev
->
global_map
&
0x20
)
==
0
))
{
if
((
i
<
8
)
&&
((
dev
->
global_map
[
0
]
&
0x20
)
==
0
))
{
goto
not_wide
;
goto
not_wide
;
}
}
if
(
lvdmode
==
0
)
{
if
(
lvdmode
==
0
)
{
goto
chg_wide
;
goto
chg_wide
;
}
}
if
(
dev
->
sp
[
i
]
!=
0x04
)
// force u2
if
(
dev
->
sp
[
0
][
i
]
!=
0x04
)
// force u2
{
{
goto
chg_wide
;
goto
chg_wide
;
}
}
...
@@ -1748,7 +2006,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1748,7 +2006,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -1872,8 +2130,8 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1872,8 +2130,8 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
if
(
mbuf
[
3
]
==
0x09
)
{
if
(
mbuf
[
3
]
==
0x09
)
{
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
dev
->
wide_id
u
|=
m
;
dev
->
wide_id
[
0
]
|=
m
;
dev
->
id
[
i
].
devspu
=
0xce
;
dev
->
id
[
0
][
i
].
devsp
=
0xce
;
continue
;
continue
;
}
}
chg_wide:
chg_wide:
...
@@ -1889,7 +2147,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -1889,7 +2147,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -2015,29 +2273,29 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -2015,29 +2273,29 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
}
}
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
dev
->
wide_id
u
|=
m
;
dev
->
wide_id
[
0
]
|=
m
;
not_wide:
not_wide:
if
((
dev
->
id
[
i
].
devtypeu
==
0x00
)
||
(
dev
->
id
[
i
].
devtypeu
==
0x07
)
||
((
dev
->
id
[
i
].
devtypeu
==
0x05
)
&&
((
n
&
0x10
)
!=
0
)))
{
if
((
dev
->
id
[
0
][
i
].
devtype
==
0x00
)
||
(
dev
->
id
[
0
][
i
].
devtype
==
0x07
)
||
((
dev
->
id
[
0
][
i
].
devtype
==
0x05
)
&&
((
n
&
0x10
)
!=
0
)))
{
m
=
1
;
m
=
1
;
m
=
m
<<
i
;
m
=
m
<<
i
;
if
((
dev
->
async
&
m
)
!=
0
)
{
if
((
dev
->
async
[
0
]
&
m
)
!=
0
)
{
goto
set_sync
;
goto
set_sync
;
}
}
}
}
continue
;
continue
;
set_sync:
set_sync:
if
(
dev
->
sp
[
i
]
==
0x02
)
{
if
(
dev
->
sp
[
0
][
i
]
==
0x02
)
{
synu
[
4
]
=
0x0c
;
synu
[
4
]
=
0x0c
;
synuw
[
4
]
=
0x0c
;
synuw
[
4
]
=
0x0c
;
}
else
{
}
else
{
if
(
dev
->
sp
[
i
]
>=
0x03
)
{
if
(
dev
->
sp
[
0
][
i
]
>=
0x03
)
{
synu
[
4
]
=
0x0a
;
synu
[
4
]
=
0x0a
;
synuw
[
4
]
=
0x0a
;
synuw
[
4
]
=
0x0a
;
}
}
}
}
tmport
=
wkport
+
0x5b
;
tmport
=
wkport
+
0x5b
;
j
=
0
;
j
=
0
;
if
((
m
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
m
&
dev
->
wide_id
[
0
]
)
!=
0
)
{
j
|=
0x01
;
j
|=
0x01
;
}
}
outb
(
j
,
tmport
);
outb
(
j
,
tmport
);
...
@@ -2051,7 +2309,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -2051,7 +2309,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport
+=
0x06
;
tmport
+=
0x06
;
outb
(
0
,
tmport
);
outb
(
0
,
tmport
);
tmport
+=
0x02
;
tmport
+=
0x02
;
outb
(
dev
->
id
[
i
].
devspu
,
tmport
++
);
outb
(
dev
->
id
[
0
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
...
@@ -2076,14 +2334,14 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -2076,14 +2334,14 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
tmport
-=
0x06
;
if
((
m
&
dev
->
wide_id
u
)
!=
0
)
{
if
((
m
&
dev
->
wide_id
[
0
]
)
!=
0
)
{
if
((
m
&
dev
->
ultra_map
)
!=
0
)
{
if
((
m
&
dev
->
ultra_map
[
0
]
)
!=
0
)
{
outb
(
synuw
[
j
++
],
tmport
);
outb
(
synuw
[
j
++
],
tmport
);
}
else
{
}
else
{
outb
(
synw
[
j
++
],
tmport
);
outb
(
synw
[
j
++
],
tmport
);
}
}
}
else
{
}
else
{
if
((
m
&
dev
->
ultra_map
)
!=
0
)
{
if
((
m
&
dev
->
ultra_map
[
0
]
)
!=
0
)
{
outb
(
synu
[
j
++
],
tmport
);
outb
(
synu
[
j
++
],
tmport
);
}
else
{
}
else
{
outb
(
synn
[
j
++
],
tmport
);
outb
(
synn
[
j
++
],
tmport
);
...
@@ -2197,7 +2455,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -2197,7 +2455,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
if
(
mbuf
[
4
]
>
0x0e
)
{
if
(
mbuf
[
4
]
>
0x0e
)
{
mbuf
[
4
]
=
0x0e
;
mbuf
[
4
]
=
0x0e
;
}
}
dev
->
id
[
i
].
devspu
=
mbuf
[
4
];
dev
->
id
[
0
][
i
].
devsp
=
mbuf
[
4
];
if
(
mbuf
[
3
]
<
0x0c
)
{
if
(
mbuf
[
3
]
<
0x0c
)
{
j
=
0xb0
;
j
=
0xb0
;
goto
set_syn_ok
;
goto
set_syn_ok
;
...
@@ -2220,249 +2478,179 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
...
@@ -2220,249 +2478,179 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
}
}
j
=
0x60
;
j
=
0x60
;
set_syn_ok:
set_syn_ok:
dev
->
id
[
i
].
devspu
=
(
dev
->
id
[
i
].
devspu
&
0x0f
)
|
j
;
dev
->
id
[
0
][
i
].
devsp
=
(
dev
->
id
[
0
][
i
].
devsp
&
0x0f
)
|
j
;
}
}
}
}
static
void
atp870u_free_tables
(
struct
Scsi_Host
*
host
)
static
void
atp870u_free_tables
(
struct
Scsi_Host
*
host
)
{
{
struct
atp_unit
*
atp_dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
struct
atp_unit
*
atp_dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
int
k
;
int
j
,
k
;
for
(
j
=
0
;
j
<
2
;
j
++
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
if
(
!
atp_dev
->
id
[
k
].
prd_tableu
)
if
(
!
atp_dev
->
id
[
j
][
k
].
prd_table
)
continue
;
continue
;
pci_free_consistent
(
atp_dev
->
pdev
,
1024
,
atp_dev
->
id
[
k
].
prd_tableu
,
pci_free_consistent
(
atp_dev
->
pdev
,
1024
,
atp_dev
->
id
[
j
][
k
].
prd_table
,
atp_dev
->
id
[
j
][
k
].
prdaddr
);
atp_dev
->
id
[
k
].
prd_phys
)
;
atp_dev
->
id
[
j
][
k
].
prd_table
=
NULL
;
atp_dev
->
id
[
k
].
prd_tableu
=
NULL
;
}
}
}
}
}
static
int
atp870u_init_tables
(
struct
Scsi_Host
*
host
)
static
int
atp870u_init_tables
(
struct
Scsi_Host
*
host
)
{
{
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
struct
atp_unit
*
atp_dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
int
k
,
i
;
int
c
,
k
;
for
(
c
=
0
;
c
<
2
;
c
++
)
{
for
(
i
=
k
=
0
;
k
<
16
;
k
++
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
dev
->
id
[
k
].
prd_tableu
=
pci_alloc_consistent
(
dev
->
pdev
,
1024
,
&
dev
->
id
[
k
].
prd_phys
);
atp_dev
->
id
[
c
][
k
].
prd_table
=
pci_alloc_consistent
(
atp_dev
->
pdev
,
1024
,
&
(
atp_dev
->
id
[
c
][
k
].
prdaddr
));
if
(
!
dev
->
id
[
k
].
prd_tableu
)
{
if
(
!
atp_dev
->
id
[
c
][
k
].
prd_table
)
{
printk
(
"atp870u_init_tables fail
\n
"
);
atp870u_free_tables
(
host
);
atp870u_free_tables
(
host
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
dev
->
id
[
k
].
devspu
=
0x20
;
atp_dev
->
id
[
c
][
k
].
devsp
=
0x20
;
dev
->
id
[
k
].
devtypeu
=
0
;
atp_dev
->
id
[
c
][
k
].
devtype
=
0x7f
;
dev
->
id
[
k
].
curr_req
=
NULL
;
atp_dev
->
id
[
c
][
k
].
curr_req
=
NULL
;
}
}
dev
->
active_idu
=
0
;
dev
->
wide_idu
=
0
;
atp_dev
->
active_id
[
c
]
=
0
;
dev
->
host_idu
=
0x07
;
atp_dev
->
wide_id
[
c
]
=
0
;
dev
->
quhdu
=
0
;
atp_dev
->
host_id
[
c
]
=
0x07
;
dev
->
quendu
=
0
;
atp_dev
->
quhd
[
c
]
=
0
;
dev
->
chip_veru
=
0
;
atp_dev
->
quend
[
c
]
=
0
;
dev
->
last_cmd
=
0xff
;
atp_dev
->
last_cmd
[
c
]
=
0xff
;
dev
->
in_snd
=
0
;
atp_dev
->
in_snd
[
c
]
=
0
;
dev
->
in_int
=
0
;
atp_dev
->
in_int
[
c
]
=
0
;
for
(
k
=
0
;
k
<
qcnt
;
k
++
)
{
for
(
k
=
0
;
k
<
qcnt
;
k
++
)
{
dev
->
querequ
[
k
]
=
NULL
;
atp_dev
->
quereq
[
c
]
[
k
]
=
NULL
;
}
}
for
(
k
=
0
;
k
<
16
;
k
++
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
dev
->
id
[
k
].
curr_req
=
NULL
;
atp_dev
->
id
[
c
][
k
].
curr_req
=
NULL
;
dev
->
sp
[
k
]
=
0x04
;
atp_dev
->
sp
[
c
][
k
]
=
0x04
;
}
}
}
return
0
;
return
0
;
}
}
/* return non-zero on detection */
/* return non-zero on detection */
static
int
atp870u_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
static
int
atp870u_probe
(
struct
pci_dev
*
p
dev
,
const
struct
pci_device_id
*
ent
)
{
{
unsigned
char
k
,
m
;
unsigned
char
k
,
m
,
c
;
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
int
base_io
,
error
,
tmport
;
unsigned
int
base_io
,
tmport
,
error
,
n
;
unsigned
char
host_id
;
unsigned
char
host_id
;
unsigned
short
n
;
struct
Scsi_Host
*
shpnt
=
NULL
;
struct
Scsi_Host
*
shpnt
;
struct
atp_unit
atp_dev
,
*
p
;
struct
atp_unit
atp_dev
,
*
p
;
static
int
count
;
unsigned
char
setupdata
[
2
][
16
];
int
count
=
0
;
if
(
pci_enable_device
(
dev
))
if
(
pci_enable_device
(
p
dev
))
return
-
EIO
;
return
-
EIO
;
if
(
pci_set_dma_mask
(
dev
,
0xFFFFFFFFUL
))
{
if
(
!
pci_set_dma_mask
(
pdev
,
0xFFFFFFUL
))
{
printk
(
KERN_ERR
"atp870u: 32bit DMA mask required but not available.
\n
"
);
printk
(
KERN_INFO
"atp870u: use 32bit DMA mask.
\n
"
);
}
else
{
printk
(
KERN_ERR
"atp870u: DMA mask required but not available.
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
memset
(
&
atp_dev
,
0
,
sizeof
atp_dev
);
memset
(
&
atp_dev
,
0
,
sizeof
atp_dev
);
/*
/*
* It's probably easier to weed out some revisions like
* It's probably easier to weed out some revisions like
* this than via the PCI device table
* this than via the PCI device table
*/
*/
if
(
ent
->
device
==
PCI_DEVICE_ID_ARTOP_AEC7610
)
{
if
(
ent
->
device
==
PCI_DEVICE_ID_ARTOP_AEC7610
)
{
error
=
pci_read_config_byte
(
dev
,
PCI_CLASS_REVISION
,
&
atp_dev
.
chip_veru
);
error
=
pci_read_config_byte
(
pdev
,
PCI_CLASS_REVISION
,
&
atp_dev
.
chip_ver
);
if
(
atp_dev
.
chip_ver
u
<
2
)
if
(
atp_dev
.
chip_ver
<
2
)
return
-
EIO
;
return
-
EIO
;
}
}
switch
(
ent
->
device
)
{
switch
(
ent
->
device
)
{
case
0x8081
:
case
PCI_DEVICE_ID_ARTOP_AEC7612UW
:
case
PCI_DEVICE_ID_ARTOP_AEC7612UW
:
case
PCI_DEVICE_ID_ARTOP_AEC7612SUW
:
case
PCI_DEVICE_ID_ARTOP_AEC7612SUW
:
atp_dev
.
chip_veru
=
0x04
;
case
ATP880_DEVID1
:
case
ATP880_DEVID2
:
case
ATP885_DEVID
:
atp_dev
.
chip_ver
=
0x04
;
default:
default:
break
;
break
;
}
}
base_io
=
pci_resource_start
(
pdev
,
0
);
base_io
=
pci_resource_start
(
dev
,
0
);
if
(
ent
->
device
!=
0x8081
)
{
error
=
pci_read_config_byte
(
dev
,
0x49
,
&
host_id
);
base_io
&=
0xfffffff8
;
base_io
&=
0xfffffff8
;
printk
(
KERN_INFO
" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
if
((
ent
->
device
==
ATP880_DEVID1
)
||
(
ent
->
device
==
ATP880_DEVID2
))
{
"IO:%x, IRQ:%d.
\n
"
,
count
,
base_io
,
dev
->
irq
);
error
=
pci_read_config_byte
(
pdev
,
PCI_CLASS_REVISION
,
&
atp_dev
.
chip_ver
);
pci_write_config_byte
(
pdev
,
PCI_LATENCY_TIMER
,
0x80
);
//JCC082803
atp_dev
.
unit
=
count
;
atp_dev
.
ioport
=
base_io
;
atp_dev
.
pciport
=
base_io
+
0x20
;
atp_dev
.
deviceid
=
ent
->
device
;
host_id
&=
0x07
;
atp_dev
.
host_idu
=
host_id
;
tmport
=
base_io
+
0x22
;
atp_dev
.
scam_on
=
inb
(
tmport
);
tmport
+=
0x0b
;
atp_dev
.
global_map
=
inb
(
tmport
++
);
atp_dev
.
ultra_map
=
inw
(
tmport
);
if
(
atp_dev
.
ultra_map
==
0
)
{
atp_dev
.
scam_on
=
0x00
;
atp_dev
.
global_map
=
0x20
;
atp_dev
.
ultra_map
=
0xffff
;
}
shpnt
=
scsi_host_alloc
(
&
atp870u_template
,
sizeof
(
struct
atp_unit
));
if
(
!
shpnt
)
return
-
ENOMEM
;
p
=
(
struct
atp_unit
*
)
&
shpnt
->
hostdata
;
atp_dev
.
host
=
shpnt
;
atp_dev
.
pdev
=
dev
;
pci_set_drvdata
(
dev
,
p
);
memcpy
(
p
,
&
atp_dev
,
sizeof
atp_dev
);
if
(
atp870u_init_tables
(
shpnt
)
<
0
)
goto
unregister
;
if
(
request_irq
(
dev
->
irq
,
atp870u_intr_handle
,
SA_SHIRQ
,
"atp870u"
,
shpnt
))
{
printk
(
KERN_ERR
"Unable to allocate IRQ%d for Acard controller.
\n
"
,
dev
->
irq
);
goto
free_tables
;
}
spin_lock_irqsave
(
shpnt
->
host_lock
,
flags
);
if
(
atp_dev
.
chip_veru
>
0x07
)
{
/* check if atp876 chip then enable terminator */
tmport
=
base_io
+
0x3e
;
outb
(
0x00
,
tmport
);
}
tmport
=
base_io
+
0x3a
;
k
=
(
inb
(
tmport
)
&
0xf3
)
|
0x10
;
outb
(
k
,
tmport
);
outb
((
k
&
0xdf
),
tmport
);
mdelay
(
32
);
outb
(
k
,
tmport
);
mdelay
(
32
);
tmport
=
base_io
;
outb
((
host_id
|
0x08
),
tmport
);
tmport
+=
0x18
;
outb
(
0
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
mdelay
(
1
);
tmport
-=
0x08
;
inb
(
tmport
);
tmport
=
base_io
+
1
;
outb
(
8
,
tmport
++
);
outb
(
0x7f
,
tmport
);
tmport
=
base_io
+
0x11
;
outb
(
0x20
,
tmport
);
tscam
(
shpnt
);
is870
(
shpnt
,
base_io
);
tmport
=
base_io
+
0x3a
;
outb
((
inb
(
tmport
)
&
0xef
),
tmport
);
tmport
++
;
outb
((
inb
(
tmport
)
|
0x20
),
tmport
);
}
else
{
base_io
&=
0xfffffff8
;
host_id
=
inb
(
base_io
+
0x39
);
host_id
=
inb
(
base_io
+
0x39
);
host_id
>>=
0x04
;
host_id
>>=
0x04
;
printk
(
KERN_INFO
" ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
printk
(
KERN_INFO
" ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
" IO:%x, IRQ:%d.
\n
"
,
count
,
base_io
,
dev
->
irq
);
" IO:%x, IRQ:%d.
\n
"
,
count
,
base_io
,
p
dev
->
irq
);
atp_dev
.
ioport
=
base_io
+
0x40
;
atp_dev
.
ioport
[
0
]
=
base_io
+
0x40
;
atp_dev
.
pciport
=
base_io
+
0x28
;
atp_dev
.
pciport
[
0
]
=
base_io
+
0x28
;
atp_dev
.
dev
ice
id
=
ent
->
device
;
atp_dev
.
dev
_
id
=
ent
->
device
;
atp_dev
.
host_id
u
=
host_id
;
atp_dev
.
host_id
[
0
]
=
host_id
;
tmport
=
base_io
+
0x22
;
tmport
=
base_io
+
0x22
;
atp_dev
.
scam_on
=
inb
(
tmport
);
atp_dev
.
scam_on
=
inb
(
tmport
);
tmport
+=
0x13
;
tmport
+=
0x13
;
atp_dev
.
global_map
=
inb
(
tmport
);
atp_dev
.
global_map
[
0
]
=
inb
(
tmport
);
tmport
+=
0x07
;
tmport
+=
0x07
;
atp_dev
.
ultra_map
=
inw
(
tmport
);
atp_dev
.
ultra_map
[
0
]
=
inw
(
tmport
);
n
=
0x3f09
;
n
=
0x3f09
;
next_fblk:
next_fblk
_880
:
if
(
n
>=
0x4000
)
if
(
n
>=
0x4000
)
goto
flash_ok
;
goto
flash_ok
_880
;
m
=
0
;
m
=
0
;
outw
(
n
,
base_io
+
0x34
);
outw
(
n
,
base_io
+
0x34
);
n
+=
0x0002
;
n
+=
0x0002
;
if
(
inb
(
base_io
+
0x30
)
==
0xff
)
if
(
inb
(
base_io
+
0x30
)
==
0xff
)
goto
flash_ok
;
goto
flash_ok
_880
;
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x33
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x33
);
outw
(
n
,
base_io
+
0x34
);
outw
(
n
,
base_io
+
0x34
);
n
+=
0x0002
;
n
+=
0x0002
;
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x33
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x33
);
outw
(
n
,
base_io
+
0x34
);
outw
(
n
,
base_io
+
0x34
);
n
+=
0x0002
;
n
+=
0x0002
;
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x33
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x33
);
outw
(
n
,
base_io
+
0x34
);
outw
(
n
,
base_io
+
0x34
);
n
+=
0x0002
;
n
+=
0x0002
;
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x30
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x31
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x32
);
atp_dev
.
sp
[
m
++
]
=
inb
(
base_io
+
0x33
);
atp_dev
.
sp
[
0
][
m
++
]
=
inb
(
base_io
+
0x33
);
n
+=
0x0018
;
n
+=
0x0018
;
goto
next_fblk
;
goto
next_fblk
_880
;
flash_ok:
flash_ok
_880
:
outw
(
0
,
base_io
+
0x34
);
outw
(
0
,
base_io
+
0x34
);
atp_dev
.
ultra_map
=
0
;
atp_dev
.
ultra_map
[
0
]
=
0
;
atp_dev
.
async
=
0
;
atp_dev
.
async
[
0
]
=
0
;
for
(
k
=
0
;
k
<
16
;
k
++
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
n
=
1
;
n
=
1
;
n
=
n
<<
k
;
n
=
n
<<
k
;
if
(
atp_dev
.
sp
[
k
]
>
1
)
{
if
(
atp_dev
.
sp
[
0
][
k
]
>
1
)
{
atp_dev
.
ultra_map
|=
n
;
atp_dev
.
ultra_map
[
0
]
|=
n
;
}
else
{
}
else
{
if
(
atp_dev
.
sp
[
k
]
==
0
)
if
(
atp_dev
.
sp
[
0
][
k
]
==
0
)
atp_dev
.
async
|=
n
;
atp_dev
.
async
[
0
]
|=
n
;
}
}
}
}
atp_dev
.
async
=
~
(
atp_dev
.
async
);
atp_dev
.
async
[
0
]
=
~
(
atp_dev
.
async
[
0
]
);
outb
(
atp_dev
.
global_map
,
base_io
+
0x35
);
outb
(
atp_dev
.
global_map
[
0
]
,
base_io
+
0x35
);
shpnt
=
scsi_host_alloc
(
&
atp870u_template
,
sizeof
(
struct
atp_unit
));
shpnt
=
scsi_host_alloc
(
&
atp870u_template
,
sizeof
(
struct
atp_unit
));
if
(
!
shpnt
)
if
(
!
shpnt
)
...
@@ -2471,16 +2659,16 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
...
@@ -2471,16 +2659,16 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
p
=
(
struct
atp_unit
*
)
&
shpnt
->
hostdata
;
p
=
(
struct
atp_unit
*
)
&
shpnt
->
hostdata
;
atp_dev
.
host
=
shpnt
;
atp_dev
.
host
=
shpnt
;
atp_dev
.
pdev
=
dev
;
atp_dev
.
pdev
=
p
dev
;
pci_set_drvdata
(
dev
,
p
);
pci_set_drvdata
(
p
dev
,
p
);
memcpy
(
p
,
&
atp_dev
,
sizeof
atp_dev
);
memcpy
(
p
,
&
atp_dev
,
sizeof
atp_dev
);
if
(
atp870u_init_tables
(
shpnt
)
<
0
)
{
if
(
atp870u_init_tables
(
shpnt
)
<
0
)
{
printk
(
KERN_ERR
"Unable to allocate tables for Acard controller
\n
"
);
printk
(
KERN_ERR
"Unable to allocate tables for Acard controller
\n
"
);
goto
unregister
;
goto
unregister
;
}
}
if
(
request_irq
(
dev
->
irq
,
atp870u_intr_handle
,
SA_SHIRQ
,
"atp870u
"
,
shpnt
))
{
if
(
request_irq
(
pdev
->
irq
,
atp870u_intr_handle
,
SA_SHIRQ
,
"atp880i
"
,
shpnt
))
{
printk
(
KERN_ERR
"Unable to allocate IRQ%d for Acard controller.
\n
"
,
dev
->
irq
);
printk
(
KERN_ERR
"Unable to allocate IRQ%d for Acard controller.
\n
"
,
p
dev
->
irq
);
goto
free_tables
;
goto
free_tables
;
}
}
...
@@ -2513,109 +2701,371 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
...
@@ -2513,109 +2701,371 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
outb
(
0x20
,
tmport
);
outb
(
0x20
,
tmport
);
tscam
(
shpnt
);
tscam
(
shpnt
);
is880
(
shpnt
,
base_io
);
is880
(
p
,
base_io
);
tmport
=
base_io
+
0x38
;
tmport
=
base_io
+
0x38
;
outb
(
0xb0
,
tmport
);
outb
(
0xb0
,
tmport
);
}
if
(
p
->
chip_veru
==
4
)
shpnt
->
max_id
=
16
;
shpnt
->
max_id
=
16
;
shpnt
->
this_id
=
host_id
;
shpnt
->
this_id
=
host_id
;
shpnt
->
unique_id
=
base_io
;
shpnt
->
unique_id
=
base_io
;
shpnt
->
io_port
=
base_io
;
shpnt
->
io_port
=
base_io
;
if
(
ent
->
device
==
0x8081
)
{
shpnt
->
n_io_port
=
0x60
;
/* Number of bytes of I/O space used */
shpnt
->
n_io_port
=
0x60
;
/* Number of bytes of I/O space used */
}
else
{
shpnt
->
irq
=
pdev
->
irq
;
shpnt
->
n_io_port
=
0x40
;
/* Number of bytes of I/O space used */
}
else
if
(
ent
->
device
==
ATP885_DEVID
)
{
}
printk
(
KERN_INFO
" ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.
\n
"
shpnt
->
irq
=
dev
->
irq
;
,
base_io
,
pdev
->
irq
);
spin_unlock_irqrestore
(
shpnt
->
host_lock
,
flags
);
if
(
ent
->
device
==
0x8081
)
{
atp_dev
.
pdev
=
pdev
;
if
(
!
request_region
(
base_io
,
0x60
,
"atp870u"
))
atp_dev
.
dev_id
=
ent
->
device
;
goto
request_io_fail
;
atp_dev
.
baseport
=
base_io
;
}
else
{
atp_dev
.
ioport
[
0
]
=
base_io
+
0x80
;
if
(
!
request_region
(
base_io
,
0x40
,
"atp870u"
))
atp_dev
.
ioport
[
1
]
=
base_io
+
0xc0
;
goto
request_io_fail
;
atp_dev
.
pciport
[
0
]
=
base_io
+
0x40
;
}
atp_dev
.
pciport
[
1
]
=
base_io
+
0x50
;
count
++
;
if
(
scsi_add_host
(
shpnt
,
&
dev
->
dev
))
goto
scsi_add_fail
;
scsi_scan_host
(
shpnt
);
return
0
;
scsi_add_fail:
shpnt
=
scsi_host_alloc
(
&
atp870u_template
,
sizeof
(
struct
atp_unit
));
if
(
ent
->
device
==
0x8081
)
if
(
!
shpnt
)
release_region
(
base_io
,
0x60
);
return
-
ENOMEM
;
else
release_region
(
base_io
,
0x40
);
request_io_fail:
free_irq
(
dev
->
irq
,
shpnt
);
free_tables:
atp870u_free_tables
(
shpnt
);
unregister:
scsi_host_put
(
shpnt
);
return
-
1
;
}
/* The abort command does not leave the device in a clean state where
p
=
(
struct
atp_unit
*
)
&
shpnt
->
hostdata
;
it is available to be used again. Until this gets worked out, we will
leave it commented out. */
static
int
atp870u_abort
(
struct
scsi_cmnd
*
SCpnt
)
atp_dev
.
host
=
shpnt
;
{
atp_dev
.
pdev
=
pdev
;
unsigned
char
j
,
k
;
pci_set_drvdata
(
pdev
,
p
)
;
struct
scsi_cmnd
*
workrequ
;
memcpy
(
p
,
&
atp_dev
,
sizeof
(
struct
atp_unit
))
;
unsigned
int
tmport
;
if
(
atp870u_init_tables
(
shpnt
)
<
0
)
struct
atp_unit
*
dev
=
(
struct
atp_unit
*
)
&
SCpnt
->
device
->
host
->
hostdata
;
goto
unregister
;
printk
(
KERN_DEBUG
"working=%x last_cmd=%x "
,
dev
->
working
,
dev
->
last_cmd
);
#ifdef ED_DBGP
printk
(
" quhdu=%x quendu=%x "
,
dev
->
quhdu
,
dev
->
quendu
);
printk
(
"request_irq() shpnt %p hostdata %p
\n
"
,
shpnt
,
p
);
tmport
=
dev
->
ioport
;
#endif
for
(
j
=
0
;
j
<
0x17
;
j
++
)
{
if
(
request_irq
(
pdev
->
irq
,
atp870u_intr_handle
,
SA_SHIRQ
,
"atp870u"
,
shpnt
))
{
printk
(
" r%2x=%2x"
,
j
,
inb
(
tmport
++
));
printk
(
KERN_ERR
"Unable to allocate IRQ for Acard controller.
\n
"
);
goto
free_tables
;
}
}
tmport
+=
0x05
;
printk
(
" r1c=%2x"
,
inb
(
tmport
));
spin_lock_irqsave
(
shpnt
->
host_lock
,
flags
);
tmport
+=
0x03
;
printk
(
" r1f=%2x in_snd=%2x "
,
inb
(
tmport
),
dev
->
in_snd
);
c
=
inb
(
base_io
+
0x29
);
tmport
=
dev
->
pciport
;
outb
((
c
|
0x04
),
base_io
+
0x29
);
printk
(
" r20=%2x"
,
inb
(
tmport
));
tmport
+=
0x02
;
n
=
0x1f80
;
printk
(
" r22=%2x"
,
inb
(
tmport
));
next_fblk_885:
tmport
=
dev
->
ioport
+
0x3a
;
if
(
n
>=
0x2000
)
{
printk
(
" r3a=%2x
\n
"
,
inb
(
tmport
));
goto
flash_ok_885
;
tmport
=
dev
->
ioport
+
0x3b
;
}
printk
(
" r3b=%2x
\n
"
,
inb
(
tmport
));
outw
(
n
,
base_io
+
0x3c
);
for
(
j
=
0
;
j
<
16
;
j
++
)
{
if
(
inl
(
base_io
+
0x38
)
==
0xffffffff
)
{
if
(
dev
->
id
[
j
].
curr_req
!=
NULL
)
{
goto
flash_ok_885
;
workrequ
=
dev
->
id
[
j
].
curr_req
;
}
printk
(
"
\n
que cdb= "
);
for
(
m
=
0
;
m
<
2
;
m
++
)
{
for
(
k
=
0
;
k
<
workrequ
->
cmd_len
;
k
++
)
{
p
->
global_map
[
m
]
=
0
;
printk
(
" %2x "
,
workrequ
->
cmnd
[
k
]);
for
(
k
=
0
;
k
<
4
;
k
++
)
{
outw
(
n
++
,
base_io
+
0x3c
);
((
unsigned
long
*
)
&
setupdata
[
m
][
0
])[
k
]
=
inl
(
base_io
+
0x38
);
}
for
(
k
=
0
;
k
<
4
;
k
++
)
{
outw
(
n
++
,
base_io
+
0x3c
);
((
unsigned
long
*
)
&
p
->
sp
[
m
][
0
])[
k
]
=
inl
(
base_io
+
0x38
);
}
n
+=
8
;
}
goto
next_fblk_885
;
flash_ok_885:
#ifdef ED_DBGP
printk
(
"Flash Read OK
\n
"
);
#endif
c
=
inb
(
base_io
+
0x29
);
outb
((
c
&
0xfb
),
base_io
+
0x29
);
for
(
c
=
0
;
c
<
2
;
c
++
)
{
p
->
ultra_map
[
c
]
=
0
;
p
->
async
[
c
]
=
0
;
for
(
k
=
0
;
k
<
16
;
k
++
)
{
n
=
1
;
n
=
n
<<
k
;
if
(
p
->
sp
[
c
][
k
]
>
1
)
{
p
->
ultra_map
[
c
]
|=
n
;
}
else
{
if
(
p
->
sp
[
c
][
k
]
==
0
)
{
p
->
async
[
c
]
|=
n
;
}
}
printk
(
" last_lenu= %lx "
,
dev
->
id
[
j
].
last_lenu
);
}
}
}
}
/* Sort of - the thing handles itself */
p
->
async
[
c
]
=
~
(
p
->
async
[
c
]);
return
SUCCESS
;
}
static
const
char
*
atp870u_info
(
struct
Scsi_Host
*
notused
)
{
static
char
buffer
[
128
];
strcpy
(
buffer
,
"ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "
);
return
buffer
;
if
(
p
->
global_map
[
c
]
==
0
)
{
}
k
=
setupdata
[
c
][
1
];
if
((
k
&
0x40
)
!=
0
)
p
->
global_map
[
c
]
|=
0x20
;
k
&=
0x07
;
p
->
global_map
[
c
]
|=
k
;
if
((
setupdata
[
c
][
2
]
&
0x04
)
!=
0
)
p
->
global_map
[
c
]
|=
0x08
;
p
->
host_id
[
c
]
=
setupdata
[
c
][
0
]
&
0x07
;
}
}
k
=
inb
(
base_io
+
0x28
)
&
0x8f
;
k
|=
0x10
;
outb
(
k
,
base_io
+
0x28
);
outb
(
0x80
,
base_io
+
0x41
);
outb
(
0x80
,
base_io
+
0x51
);
mdelay
(
100
);
outb
(
0
,
base_io
+
0x41
);
outb
(
0
,
base_io
+
0x51
);
mdelay
(
1000
);
inb
(
base_io
+
0x9b
);
inb
(
base_io
+
0x97
);
inb
(
base_io
+
0xdb
);
inb
(
base_io
+
0xd7
);
tmport
=
base_io
+
0x80
;
k
=
p
->
host_id
[
0
];
if
(
k
>
7
)
k
=
(
k
&
0x07
)
|
0x40
;
k
|=
0x08
;
outb
(
k
,
tmport
);
tmport
+=
0x18
;
outb
(
0
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
);
tmport
-=
0x08
;
inb
(
tmport
);
tmport
=
base_io
+
0x81
;
outb
(
8
,
tmport
++
);
outb
(
0x7f
,
tmport
);
tmport
=
base_io
+
0x91
;
outb
(
0x20
,
tmport
);
#define BLS buffer + len + size
tmport
=
base_io
+
0xc0
;
static
int
atp870u_proc_info
(
struct
Scsi_Host
*
HBAptr
,
char
*
buffer
,
k
=
p
->
host_id
[
1
];
char
**
start
,
off_t
offset
,
int
length
,
int
inout
)
if
(
k
>
7
)
{
k
=
(
k
&
0x07
)
|
0x40
;
static
u8
buff
[
512
];
k
|=
0x08
;
outb
(
k
,
tmport
);
tmport
+=
0x18
;
outb
(
0
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
);
tmport
-=
0x08
;
inb
(
tmport
);
tmport
=
base_io
+
0xc1
;
outb
(
8
,
tmport
++
);
outb
(
0x7f
,
tmport
);
tmport
=
base_io
+
0xd1
;
outb
(
0x20
,
tmport
);
tscam_885
();
printk
(
KERN_INFO
" Scanning Channel A SCSI Device ...
\n
"
);
is885
(
p
,
base_io
+
0x80
,
0
);
printk
(
KERN_INFO
" Scanning Channel B SCSI Device ...
\n
"
);
is885
(
p
,
base_io
+
0xc0
,
1
);
k
=
inb
(
base_io
+
0x28
)
&
0xcf
;
k
|=
0xc0
;
outb
(
k
,
base_io
+
0x28
);
k
=
inb
(
base_io
+
0x1f
)
|
0x80
;
outb
(
k
,
base_io
+
0x1f
);
k
=
inb
(
base_io
+
0x29
)
|
0x01
;
outb
(
k
,
base_io
+
0x29
);
#ifdef ED_DBGP
//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
#endif
shpnt
->
max_id
=
16
;
shpnt
->
max_lun
=
(
p
->
global_map
[
0
]
&
0x07
)
+
1
;
shpnt
->
max_channel
=
1
;
shpnt
->
this_id
=
p
->
host_id
[
0
];
shpnt
->
unique_id
=
base_io
;
shpnt
->
io_port
=
base_io
;
shpnt
->
n_io_port
=
0xff
;
/* Number of bytes of I/O space used */
shpnt
->
irq
=
pdev
->
irq
;
}
else
{
error
=
pci_read_config_byte
(
pdev
,
0x49
,
&
host_id
);
printk
(
KERN_INFO
" ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
"IO:%x, IRQ:%d.
\n
"
,
count
,
base_io
,
pdev
->
irq
);
atp_dev
.
ioport
[
0
]
=
base_io
;
atp_dev
.
pciport
[
0
]
=
base_io
+
0x20
;
atp_dev
.
dev_id
=
ent
->
device
;
host_id
&=
0x07
;
atp_dev
.
host_id
[
0
]
=
host_id
;
tmport
=
base_io
+
0x22
;
atp_dev
.
scam_on
=
inb
(
tmport
);
tmport
+=
0x0b
;
atp_dev
.
global_map
[
0
]
=
inb
(
tmport
++
);
atp_dev
.
ultra_map
[
0
]
=
inw
(
tmport
);
if
(
atp_dev
.
ultra_map
[
0
]
==
0
)
{
atp_dev
.
scam_on
=
0x00
;
atp_dev
.
global_map
[
0
]
=
0x20
;
atp_dev
.
ultra_map
[
0
]
=
0xffff
;
}
shpnt
=
scsi_host_alloc
(
&
atp870u_template
,
sizeof
(
struct
atp_unit
));
if
(
!
shpnt
)
return
-
ENOMEM
;
p
=
(
struct
atp_unit
*
)
&
shpnt
->
hostdata
;
atp_dev
.
host
=
shpnt
;
atp_dev
.
pdev
=
pdev
;
pci_set_drvdata
(
pdev
,
p
);
memcpy
(
p
,
&
atp_dev
,
sizeof
atp_dev
);
if
(
atp870u_init_tables
(
shpnt
)
<
0
)
goto
unregister
;
if
(
request_irq
(
pdev
->
irq
,
atp870u_intr_handle
,
SA_SHIRQ
,
"atp870i"
,
shpnt
))
{
printk
(
KERN_ERR
"Unable to allocate IRQ%d for Acard controller.
\n
"
,
pdev
->
irq
);
goto
free_tables
;
}
spin_lock_irqsave
(
shpnt
->
host_lock
,
flags
);
if
(
atp_dev
.
chip_ver
>
0x07
)
{
/* check if atp876 chip then enable terminator */
tmport
=
base_io
+
0x3e
;
outb
(
0x00
,
tmport
);
}
tmport
=
base_io
+
0x3a
;
k
=
(
inb
(
tmport
)
&
0xf3
)
|
0x10
;
outb
(
k
,
tmport
);
outb
((
k
&
0xdf
),
tmport
);
mdelay
(
32
);
outb
(
k
,
tmport
);
mdelay
(
32
);
tmport
=
base_io
;
outb
((
host_id
|
0x08
),
tmport
);
tmport
+=
0x18
;
outb
(
0
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
mdelay
(
1
);
tmport
-=
0x08
;
inb
(
tmport
);
tmport
=
base_io
+
1
;
outb
(
8
,
tmport
++
);
outb
(
0x7f
,
tmport
);
tmport
=
base_io
+
0x11
;
outb
(
0x20
,
tmport
);
tscam
(
shpnt
);
is870
(
p
,
base_io
);
tmport
=
base_io
+
0x3a
;
outb
((
inb
(
tmport
)
&
0xef
),
tmport
);
tmport
++
;
outb
((
inb
(
tmport
)
|
0x20
),
tmport
);
if
(
atp_dev
.
chip_ver
==
4
)
shpnt
->
max_id
=
16
;
else
shpnt
->
max_id
=
7
;
shpnt
->
this_id
=
host_id
;
shpnt
->
unique_id
=
base_io
;
shpnt
->
io_port
=
base_io
;
shpnt
->
n_io_port
=
0x40
;
/* Number of bytes of I/O space used */
shpnt
->
irq
=
pdev
->
irq
;
}
spin_unlock_irqrestore
(
shpnt
->
host_lock
,
flags
);
if
(
ent
->
device
==
ATP885_DEVID
)
{
if
(
!
request_region
(
base_io
,
0xff
,
"atp870u"
))
/* Register the IO ports that we use */
goto
request_io_fail
;
}
else
if
((
ent
->
device
==
ATP880_DEVID1
)
||
(
ent
->
device
==
ATP880_DEVID2
))
{
if
(
!
request_region
(
base_io
,
0x60
,
"atp870u"
))
/* Register the IO ports that we use */
goto
request_io_fail
;
}
else
{
if
(
!
request_region
(
base_io
,
0x40
,
"atp870u"
))
/* Register the IO ports that we use */
goto
request_io_fail
;
}
count
++
;
if
(
scsi_add_host
(
shpnt
,
&
pdev
->
dev
))
goto
scsi_add_fail
;
scsi_scan_host
(
shpnt
);
#ifdef ED_DBGP
printk
(
"atp870u_prob : exit
\n
"
);
#endif
return
0
;
scsi_add_fail:
printk
(
"atp870u_prob:scsi_add_fail
\n
"
);
if
(
ent
->
device
==
ATP885_DEVID
)
{
release_region
(
base_io
,
0xff
);
}
else
if
((
ent
->
device
==
ATP880_DEVID1
)
||
(
ent
->
device
==
ATP880_DEVID2
))
{
release_region
(
base_io
,
0x60
);
}
else
{
release_region
(
base_io
,
0x40
);
}
request_io_fail:
printk
(
"atp870u_prob:request_io_fail
\n
"
);
free_irq
(
pdev
->
irq
,
shpnt
);
free_tables:
printk
(
"atp870u_prob:free_table
\n
"
);
atp870u_free_tables
(
shpnt
);
unregister:
printk
(
"atp870u_prob:unregister
\n
"
);
scsi_host_put
(
shpnt
);
return
-
1
;
}
/* The abort command does not leave the device in a clean state where
it is available to be used again. Until this gets worked out, we will
leave it commented out. */
int
atp870u_abort
(
struct
scsi_cmnd
*
SCpnt
)
{
unsigned
char
j
,
k
,
c
;
struct
scsi_cmnd
*
workrequ
;
unsigned
int
tmport
;
struct
atp_unit
*
dev
;
struct
Scsi_Host
*
host
;
host
=
SCpnt
->
device
->
host
;
dev
=
(
struct
atp_unit
*
)
&
host
->
hostdata
;
c
=
SCpnt
->
device
->
channel
;
printk
(
" atp870u: abort Channel = %x
\n
"
,
c
);
printk
(
"working=%x last_cmd=%x "
,
dev
->
working
[
c
],
dev
->
last_cmd
[
c
]);
printk
(
" quhdu=%x quendu=%x "
,
dev
->
quhd
[
c
],
dev
->
quend
[
c
]);
tmport
=
dev
->
ioport
[
c
];
for
(
j
=
0
;
j
<
0x18
;
j
++
)
{
printk
(
" r%2x=%2x"
,
j
,
inb
(
tmport
++
));
}
tmport
+=
0x04
;
printk
(
" r1c=%2x"
,
inb
(
tmport
));
tmport
+=
0x03
;
printk
(
" r1f=%2x in_snd=%2x "
,
inb
(
tmport
),
dev
->
in_snd
[
c
]);
tmport
=
dev
->
pciport
[
c
];
printk
(
" d00=%2x"
,
inb
(
tmport
));
tmport
+=
0x02
;
printk
(
" d02=%2x"
,
inb
(
tmport
));
for
(
j
=
0
;
j
<
16
;
j
++
)
{
if
(
dev
->
id
[
c
][
j
].
curr_req
!=
NULL
)
{
workrequ
=
dev
->
id
[
c
][
j
].
curr_req
;
printk
(
"
\n
que cdb= "
);
for
(
k
=
0
;
k
<
workrequ
->
cmd_len
;
k
++
)
{
printk
(
" %2x "
,
workrequ
->
cmnd
[
k
]);
}
printk
(
" last_lenu= %x "
,(
unsigned
int
)
dev
->
id
[
c
][
j
].
last_len
);
}
}
return
SUCCESS
;
}
const
char
*
atp870u_info
(
struct
Scsi_Host
*
notused
)
{
static
char
buffer
[
128
];
strcpy
(
buffer
,
"ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "
);
return
buffer
;
}
int
atp870u_set_info
(
char
*
buffer
,
int
length
,
struct
Scsi_Host
*
HBAptr
)
{
return
-
ENOSYS
;
/* Currently this is a no-op */
}
#define BLS buffer + len + size
int
atp870u_proc_info
(
struct
Scsi_Host
*
HBAptr
,
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
inout
)
{
static
u8
buff
[
512
];
int
size
=
0
;
int
size
=
0
;
int
len
=
0
;
int
len
=
0
;
off_t
begin
=
0
;
off_t
begin
=
0
;
...
@@ -2646,15 +3096,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
...
@@ -2646,15 +3096,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
return
(
len
);
return
(
len
);
}
}
static
int
atp870u_biosparam
(
struct
scsi_device
*
sdev
,
struct
block_device
*
dev
,
sector_t
capacity
,
int
*
ip
)
static
int
atp870u_biosparam
(
struct
scsi_device
*
disk
,
struct
block_device
*
dev
,
sector_t
capacity
,
int
*
ip
)
{
{
int
heads
,
sectors
,
cylinders
;
int
heads
,
sectors
,
cylinders
;
heads
=
64
;
heads
=
64
;
sectors
=
32
;
sectors
=
32
;
cylinders
=
(
unsigned
long
)
capacity
/
(
heads
*
sectors
);
cylinders
=
(
unsigned
long
)
capacity
/
(
heads
*
sectors
);
if
(
cylinders
>
1024
)
{
if
(
cylinders
>
1024
)
{
heads
=
255
;
heads
=
255
;
sectors
=
63
;
sectors
=
63
;
...
@@ -2667,39 +3117,46 @@ static int atp870u_biosparam(struct scsi_device *sdev,
...
@@ -2667,39 +3117,46 @@ static int atp870u_biosparam(struct scsi_device *sdev,
return
0
;
return
0
;
}
}
static
void
atp870u_remove
(
struct
pci_dev
*
pdev
)
static
void
atp870u_remove
(
struct
pci_dev
*
pdev
)
{
{
struct
atp_unit
*
atp_dev
=
pci_get_drvdata
(
pdev
);
struct
atp_unit
*
devext
=
pci_get_drvdata
(
pdev
);
struct
Scsi_Host
*
pshost
=
atp_dev
->
host
;
struct
Scsi_Host
*
pshost
=
devext
->
host
;
scsi_remove_host
(
pshost
);
scsi_remove_host
(
pshost
);
printk
(
KERN_INFO
"free_irq : %d
\n
"
,
pshost
->
irq
);
free_irq
(
pshost
->
irq
,
pshost
);
free_irq
(
pshost
->
irq
,
pshost
);
release_region
(
pshost
->
io_port
,
pshost
->
n_io_port
);
release_region
(
pshost
->
io_port
,
pshost
->
n_io_port
);
printk
(
KERN_INFO
"atp870u_free_tables : %p
\n
"
,
pshost
);
atp870u_free_tables
(
pshost
);
atp870u_free_tables
(
pshost
);
printk
(
KERN_INFO
"scsi_host_put : %p
\n
"
,
pshost
);
scsi_host_put
(
pshost
);
scsi_host_put
(
pshost
);
printk
(
KERN_INFO
"pci_set_drvdata : %p
\n
"
,
pdev
);
pci_set_drvdata
(
pdev
,
NULL
);
pci_set_drvdata
(
pdev
,
NULL
);
}
}
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
struct
scsi_host_template
atp870u_template
=
{
static
struct
scsi_host_template
atp870u_template
=
{
.
module
=
THIS_MODULE
,
.
module
=
THIS_MODULE
,
.
name
=
"atp870u"
,
.
name
=
"atp870u"
/* name */
,
.
proc_name
=
"atp870u"
,
.
proc_name
=
"atp870u"
,
.
proc_info
=
atp870u_proc_info
,
.
proc_info
=
atp870u_proc_info
,
.
info
=
atp870u_info
,
.
info
=
atp870u_info
/* info */
,
.
queuecommand
=
atp870u_queuecommand
,
.
queuecommand
=
atp870u_queuecommand
/* queuecommand */
,
.
eh_abort_handler
=
atp870u_abort
,
.
eh_abort_handler
=
atp870u_abort
/* abort */
,
.
bios_param
=
atp870u_biosparam
,
.
bios_param
=
atp870u_biosparam
/* biosparm */
,
.
can_queue
=
qcnt
,
.
can_queue
=
qcnt
/* can_queue */
,
.
this_id
=
7
,
.
this_id
=
7
/* SCSI ID */
,
.
sg_tablesize
=
ATP870U_SCATTER
,
.
sg_tablesize
=
ATP870U_SCATTER
/*SG_ALL*/
/*SG_NONE*/
,
.
cmd_per_lun
=
ATP870U_CMDLUN
,
.
cmd_per_lun
=
ATP870U_CMDLUN
/* commands per lun */
,
.
use_clustering
=
ENABLE_CLUSTERING
,
.
use_clustering
=
ENABLE_CLUSTERING
,
.
max_sectors
=
ATP870U_MAX_SECTORS
,
};
};
static
struct
pci_device_id
atp870u_id_table
[]
=
{
static
struct
pci_device_id
atp870u_id_table
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
0x8081
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
ATP885_DEVID
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
ATP880_DEVID1
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
ATP880_DEVID2
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7610
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7610
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7612UW
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7612UW
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7612U
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ARTOP
,
PCI_DEVICE_ID_ARTOP_AEC7612U
)
},
...
@@ -2721,14 +3178,688 @@ static struct pci_driver atp870u_driver = {
...
@@ -2721,14 +3178,688 @@ static struct pci_driver atp870u_driver = {
static
int
__init
atp870u_init
(
void
)
static
int
__init
atp870u_init
(
void
)
{
{
return
pci_module_init
(
&
atp870u_driver
);
#ifdef ED_DBGP
printk
(
"atp870u_init: Entry
\n
"
);
#endif
return
pci_register_driver
(
&
atp870u_driver
);
}
}
static
void
__exit
atp870u_exit
(
void
)
static
void
__exit
atp870u_exit
(
void
)
{
{
#ifdef ED_DBGP
printk
(
"atp870u_exit: Entry
\n
"
);
#endif
pci_unregister_driver
(
&
atp870u_driver
);
pci_unregister_driver
(
&
atp870u_driver
);
}
}
void
tscam_885
(
void
)
{
unsigned
char
i
;
for
(
i
=
0
;
i
<
0x2
;
i
++
)
{
mdelay
(
300
);
}
return
;
}
void
is885
(
struct
atp_unit
*
dev
,
unsigned
int
wkport
,
unsigned
char
c
)
{
unsigned
int
tmport
;
unsigned
char
i
,
j
,
k
,
rmb
,
n
,
lvdmode
;
unsigned
short
int
m
;
static
unsigned
char
mbuf
[
512
];
static
unsigned
char
satn
[
9
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
6
,
6
};
static
unsigned
char
inqd
[
9
]
=
{
0x12
,
0
,
0
,
0
,
0x24
,
0
,
0
,
0x24
,
6
};
static
unsigned
char
synn
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x19
,
0x0e
};
unsigned
char
synu
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0a
,
0x0e
};
static
unsigned
char
synw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x19
,
0x0e
};
unsigned
char
synuw
[
6
]
=
{
0x80
,
1
,
3
,
1
,
0x0a
,
0x0e
};
static
unsigned
char
wide
[
6
]
=
{
0x80
,
1
,
2
,
3
,
1
,
0
};
static
unsigned
char
u3
[
9
]
=
{
0x80
,
1
,
6
,
4
,
0x09
,
00
,
0x0e
,
0x01
,
0x02
};
lvdmode
=
inb
(
wkport
+
0x1b
)
>>
7
;
for
(
i
=
0
;
i
<
16
;
i
++
)
{
m
=
1
;
m
=
m
<<
i
;
if
((
m
&
dev
->
active_id
[
c
])
!=
0
)
{
continue
;
}
if
(
i
==
dev
->
host_id
[
c
])
{
printk
(
KERN_INFO
" ID: %2d Host Adapter
\n
"
,
dev
->
host_id
[
c
]);
continue
;
}
tmport
=
wkport
+
0x1b
;
outb
(
0x01
,
tmport
);
tmport
=
wkport
+
0x01
;
outb
(
0x08
,
tmport
++
);
outb
(
0x7f
,
tmport
++
);
outb
(
satn
[
0
],
tmport
++
);
outb
(
satn
[
1
],
tmport
++
);
outb
(
satn
[
2
],
tmport
++
);
outb
(
satn
[
3
],
tmport
++
);
outb
(
satn
[
4
],
tmport
++
);
outb
(
satn
[
5
],
tmport
++
);
tmport
+=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x02
;
outb
(
dev
->
id
[
c
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
j
=
i
;
if
((
j
&
0x08
)
!=
0
)
{
j
=
(
j
&
0x07
)
|
0x40
;
}
outb
(
j
,
tmport
);
tmport
+=
0x03
;
outb
(
satn
[
8
],
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
((
inb
(
tmport
)
!=
0x11
)
&&
(
inb
(
tmport
)
!=
0x8e
))
{
continue
;
}
while
(
inb
(
tmport
)
!=
0x8e
);
dev
->
active_id
[
c
]
|=
m
;
tmport
=
wkport
+
0x10
;
outb
(
0x30
,
tmport
);
tmport
=
wkport
+
0x14
;
outb
(
0x00
,
tmport
);
phase_cmd:
tmport
=
wkport
+
0x18
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
!=
0x16
)
{
tmport
=
wkport
+
0x10
;
outb
(
0x41
,
tmport
);
goto
phase_cmd
;
}
sel_ok:
tmport
=
wkport
+
0x03
;
outb
(
inqd
[
0
],
tmport
++
);
outb
(
inqd
[
1
],
tmport
++
);
outb
(
inqd
[
2
],
tmport
++
);
outb
(
inqd
[
3
],
tmport
++
);
outb
(
inqd
[
4
],
tmport
++
);
outb
(
inqd
[
5
],
tmport
);
tmport
+=
0x07
;
outb
(
0
,
tmport
);
tmport
+=
0x02
;
outb
(
dev
->
id
[
c
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
inqd
[
6
],
tmport
++
);
outb
(
inqd
[
7
],
tmport
++
);
tmport
+=
0x03
;
outb
(
inqd
[
8
],
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
((
inb
(
tmport
)
!=
0x11
)
&&
(
inb
(
tmport
)
!=
0x8e
))
{
continue
;
}
while
(
inb
(
tmport
)
!=
0x8e
);
tmport
=
wkport
+
0x1b
;
outb
(
0x00
,
tmport
);
tmport
=
wkport
+
0x18
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
j
=
0
;
rd_inq_data:
k
=
inb
(
tmport
);
if
((
k
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
mbuf
[
j
++
]
=
inb
(
tmport
);
tmport
+=
0x06
;
goto
rd_inq_data
;
}
if
((
k
&
0x80
)
==
0
)
{
goto
rd_inq_data
;
}
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
==
0x16
)
{
goto
inq_ok
;
}
tmport
=
wkport
+
0x10
;
outb
(
0x46
,
tmport
);
tmport
+=
0x02
;
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
0
,
tmport
++
);
tmport
+=
0x03
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
(
inb
(
tmport
)
!=
0x16
)
{
goto
sel_ok
;
}
inq_ok:
mbuf
[
36
]
=
0
;
printk
(
KERN_INFO
" ID: %2d %s
\n
"
,
i
,
&
mbuf
[
8
]);
dev
->
id
[
c
][
i
].
devtype
=
mbuf
[
0
];
rmb
=
mbuf
[
1
];
n
=
mbuf
[
7
];
if
((
mbuf
[
7
]
&
0x60
)
==
0
)
{
goto
not_wide
;
}
if
((
i
<
8
)
&&
((
dev
->
global_map
[
c
]
&
0x20
)
==
0
))
{
goto
not_wide
;
}
if
(
lvdmode
==
0
)
{
goto
chg_wide
;
}
if
(
dev
->
sp
[
c
][
i
]
!=
0x04
)
{
// force u2
goto
chg_wide
;
}
tmport
=
wkport
+
0x1b
;
outb
(
0x01
,
tmport
);
tmport
=
wkport
+
0x03
;
outb
(
satn
[
0
],
tmport
++
);
outb
(
satn
[
1
],
tmport
++
);
outb
(
satn
[
2
],
tmport
++
);
outb
(
satn
[
3
],
tmport
++
);
outb
(
satn
[
4
],
tmport
++
);
outb
(
satn
[
5
],
tmport
++
);
tmport
+=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x02
;
outb
(
dev
->
id
[
c
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
tmport
+=
0x03
;
outb
(
satn
[
8
],
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
((
inb
(
tmport
)
!=
0x11
)
&&
(
inb
(
tmport
)
!=
0x8e
))
{
continue
;
}
while
(
inb
(
tmport
)
!=
0x8e
);
try_u3:
j
=
0
;
tmport
=
wkport
+
0x14
;
outb
(
0x09
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
outb
(
u3
[
j
++
],
tmport
);
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
u3p_in
;
}
if
(
j
==
0x0a
)
{
goto
u3p_cmd
;
}
if
(
j
==
0x0e
)
{
goto
try_u3
;
}
continue
;
u3p_out:
tmport
=
wkport
+
0x18
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
u3p_in
;
}
if
(
j
==
0x0a
)
{
goto
u3p_cmd
;
}
if
(
j
==
0x0e
)
{
goto
u3p_out
;
}
continue
;
u3p_in:
tmport
=
wkport
+
0x14
;
outb
(
0x09
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
k
=
0
;
u3p_in1:
j
=
inb
(
tmport
);
if
((
j
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
mbuf
[
k
++
]
=
inb
(
tmport
);
tmport
+=
0x06
;
goto
u3p_in1
;
}
if
((
j
&
0x80
)
==
0x00
)
{
goto
u3p_in1
;
}
tmport
-=
0x08
;
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
u3p_in
;
}
if
(
j
==
0x0a
)
{
goto
u3p_cmd
;
}
if
(
j
==
0x0e
)
{
goto
u3p_out
;
}
continue
;
u3p_cmd:
tmport
=
wkport
+
0x10
;
outb
(
0x30
,
tmport
);
tmport
=
wkport
+
0x14
;
outb
(
0x00
,
tmport
);
tmport
+=
0x04
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
!=
0x16
)
{
if
(
j
==
0x4e
)
{
goto
u3p_out
;
}
continue
;
}
if
(
mbuf
[
0
]
!=
0x01
)
{
goto
chg_wide
;
}
if
(
mbuf
[
1
]
!=
0x06
)
{
goto
chg_wide
;
}
if
(
mbuf
[
2
]
!=
0x04
)
{
goto
chg_wide
;
}
if
(
mbuf
[
3
]
==
0x09
)
{
m
=
1
;
m
=
m
<<
i
;
dev
->
wide_id
[
c
]
|=
m
;
dev
->
id
[
c
][
i
].
devsp
=
0xce
;
#ifdef ED_DBGP
printk
(
"dev->id[%2d][%2d].devsp = %2x
\n
"
,
c
,
i
,
dev
->
id
[
c
][
i
].
devsp
);
#endif
continue
;
}
chg_wide:
tmport
=
wkport
+
0x1b
;
outb
(
0x01
,
tmport
);
tmport
=
wkport
+
0x03
;
outb
(
satn
[
0
],
tmport
++
);
outb
(
satn
[
1
],
tmport
++
);
outb
(
satn
[
2
],
tmport
++
);
outb
(
satn
[
3
],
tmport
++
);
outb
(
satn
[
4
],
tmport
++
);
outb
(
satn
[
5
],
tmport
++
);
tmport
+=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x02
;
outb
(
dev
->
id
[
c
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
tmport
+=
0x03
;
outb
(
satn
[
8
],
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
((
inb
(
tmport
)
!=
0x11
)
&&
(
inb
(
tmport
)
!=
0x8e
))
{
continue
;
}
while
(
inb
(
tmport
)
!=
0x8e
);
try_wide:
j
=
0
;
tmport
=
wkport
+
0x14
;
outb
(
0x05
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
outb
(
wide
[
j
++
],
tmport
);
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
widep_in
;
}
if
(
j
==
0x0a
)
{
goto
widep_cmd
;
}
if
(
j
==
0x0e
)
{
goto
try_wide
;
}
continue
;
widep_out:
tmport
=
wkport
+
0x18
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
widep_in
;
}
if
(
j
==
0x0a
)
{
goto
widep_cmd
;
}
if
(
j
==
0x0e
)
{
goto
widep_out
;
}
continue
;
widep_in:
tmport
=
wkport
+
0x14
;
outb
(
0xff
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
k
=
0
;
widep_in1:
j
=
inb
(
tmport
);
if
((
j
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
mbuf
[
k
++
]
=
inb
(
tmport
);
tmport
+=
0x06
;
goto
widep_in1
;
}
if
((
j
&
0x80
)
==
0x00
)
{
goto
widep_in1
;
}
tmport
-=
0x08
;
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
widep_in
;
}
if
(
j
==
0x0a
)
{
goto
widep_cmd
;
}
if
(
j
==
0x0e
)
{
goto
widep_out
;
}
continue
;
widep_cmd:
tmport
=
wkport
+
0x10
;
outb
(
0x30
,
tmport
);
tmport
=
wkport
+
0x14
;
outb
(
0x00
,
tmport
);
tmport
+=
0x04
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
!=
0x16
)
{
if
(
j
==
0x4e
)
{
goto
widep_out
;
}
continue
;
}
if
(
mbuf
[
0
]
!=
0x01
)
{
goto
not_wide
;
}
if
(
mbuf
[
1
]
!=
0x02
)
{
goto
not_wide
;
}
if
(
mbuf
[
2
]
!=
0x03
)
{
goto
not_wide
;
}
if
(
mbuf
[
3
]
!=
0x01
)
{
goto
not_wide
;
}
m
=
1
;
m
=
m
<<
i
;
dev
->
wide_id
[
c
]
|=
m
;
not_wide:
if
((
dev
->
id
[
c
][
i
].
devtype
==
0x00
)
||
(
dev
->
id
[
c
][
i
].
devtype
==
0x07
)
||
((
dev
->
id
[
c
][
i
].
devtype
==
0x05
)
&&
((
n
&
0x10
)
!=
0
)))
{
m
=
1
;
m
=
m
<<
i
;
if
((
dev
->
async
[
c
]
&
m
)
!=
0
)
{
goto
set_sync
;
}
}
continue
;
set_sync:
if
(
dev
->
sp
[
c
][
i
]
==
0x02
)
{
synu
[
4
]
=
0x0c
;
synuw
[
4
]
=
0x0c
;
}
else
{
if
(
dev
->
sp
[
c
][
i
]
>=
0x03
)
{
synu
[
4
]
=
0x0a
;
synuw
[
4
]
=
0x0a
;
}
}
tmport
=
wkport
+
0x1b
;
j
=
0
;
if
((
m
&
dev
->
wide_id
[
c
])
!=
0
)
{
j
|=
0x01
;
}
outb
(
j
,
tmport
);
tmport
=
wkport
+
0x03
;
outb
(
satn
[
0
],
tmport
++
);
outb
(
satn
[
1
],
tmport
++
);
outb
(
satn
[
2
],
tmport
++
);
outb
(
satn
[
3
],
tmport
++
);
outb
(
satn
[
4
],
tmport
++
);
outb
(
satn
[
5
],
tmport
++
);
tmport
+=
0x06
;
outb
(
0
,
tmport
);
tmport
+=
0x02
;
outb
(
dev
->
id
[
c
][
i
].
devsp
,
tmport
++
);
outb
(
0
,
tmport
++
);
outb
(
satn
[
6
],
tmport
++
);
outb
(
satn
[
7
],
tmport
++
);
tmport
+=
0x03
;
outb
(
satn
[
8
],
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
if
((
inb
(
tmport
)
!=
0x11
)
&&
(
inb
(
tmport
)
!=
0x8e
))
{
continue
;
}
while
(
inb
(
tmport
)
!=
0x8e
);
try_sync:
j
=
0
;
tmport
=
wkport
+
0x14
;
outb
(
0x06
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0
)
{
tmport
-=
0x06
;
if
((
m
&
dev
->
wide_id
[
c
])
!=
0
)
{
if
((
m
&
dev
->
ultra_map
[
c
])
!=
0
)
{
outb
(
synuw
[
j
++
],
tmport
);
}
else
{
outb
(
synw
[
j
++
],
tmport
);
}
}
else
{
if
((
m
&
dev
->
ultra_map
[
c
])
!=
0
)
{
outb
(
synu
[
j
++
],
tmport
);
}
else
{
outb
(
synn
[
j
++
],
tmport
);
}
}
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
j
=
inb
(
tmport
)
&
0x0f
;
if
(
j
==
0x0f
)
{
goto
phase_ins
;
}
if
(
j
==
0x0a
)
{
goto
phase_cmds
;
}
if
(
j
==
0x0e
)
{
goto
try_sync
;
}
continue
;
phase_outs:
tmport
=
wkport
+
0x18
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
)
{
if
((
inb
(
tmport
)
&
0x01
)
!=
0x00
)
{
tmport
-=
0x06
;
outb
(
0x00
,
tmport
);
tmport
+=
0x06
;
}
}
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
==
0x85
)
{
goto
tar_dcons
;
}
j
&=
0x0f
;
if
(
j
==
0x0f
)
{
goto
phase_ins
;
}
if
(
j
==
0x0a
)
{
goto
phase_cmds
;
}
if
(
j
==
0x0e
)
{
goto
phase_outs
;
}
continue
;
phase_ins:
tmport
=
wkport
+
0x14
;
outb
(
0x06
,
tmport
);
tmport
+=
0x04
;
outb
(
0x20
,
tmport
);
tmport
+=
0x07
;
k
=
0
;
phase_ins1:
j
=
inb
(
tmport
);
if
((
j
&
0x01
)
!=
0x00
)
{
tmport
-=
0x06
;
mbuf
[
k
++
]
=
inb
(
tmport
);
tmport
+=
0x06
;
goto
phase_ins1
;
}
if
((
j
&
0x80
)
==
0x00
)
{
goto
phase_ins1
;
}
tmport
-=
0x08
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
j
=
inb
(
tmport
);
if
(
j
==
0x85
)
{
goto
tar_dcons
;
}
j
&=
0x0f
;
if
(
j
==
0x0f
)
{
goto
phase_ins
;
}
if
(
j
==
0x0a
)
{
goto
phase_cmds
;
}
if
(
j
==
0x0e
)
{
goto
phase_outs
;
}
continue
;
phase_cmds:
tmport
=
wkport
+
0x10
;
outb
(
0x30
,
tmport
);
tar_dcons:
tmport
=
wkport
+
0x14
;
outb
(
0x00
,
tmport
);
tmport
+=
0x04
;
outb
(
0x08
,
tmport
);
tmport
+=
0x07
;
while
((
inb
(
tmport
)
&
0x80
)
==
0x00
);
tmport
-=
0x08
;
j
=
inb
(
tmport
);
if
(
j
!=
0x16
)
{
continue
;
}
if
(
mbuf
[
0
]
!=
0x01
)
{
continue
;
}
if
(
mbuf
[
1
]
!=
0x03
)
{
continue
;
}
if
(
mbuf
[
4
]
==
0x00
)
{
continue
;
}
if
(
mbuf
[
3
]
>
0x64
)
{
continue
;
}
if
(
mbuf
[
4
]
>
0x0e
)
{
mbuf
[
4
]
=
0x0e
;
}
dev
->
id
[
c
][
i
].
devsp
=
mbuf
[
4
];
if
(
mbuf
[
3
]
<
0x0c
){
j
=
0xb0
;
goto
set_syn_ok
;
}
if
((
mbuf
[
3
]
<
0x0d
)
&&
(
rmb
==
0
))
{
j
=
0xa0
;
goto
set_syn_ok
;
}
if
(
mbuf
[
3
]
<
0x1a
)
{
j
=
0x20
;
goto
set_syn_ok
;
}
if
(
mbuf
[
3
]
<
0x33
)
{
j
=
0x40
;
goto
set_syn_ok
;
}
if
(
mbuf
[
3
]
<
0x4c
)
{
j
=
0x50
;
goto
set_syn_ok
;
}
j
=
0x60
;
set_syn_ok:
dev
->
id
[
c
][
i
].
devsp
=
(
dev
->
id
[
c
][
i
].
devsp
&
0x0f
)
|
j
;
#ifdef ED_DBGP
printk
(
"dev->id[%2d][%2d].devsp = %2x
\n
"
,
c
,
i
,
dev
->
id
[
c
][
i
].
devsp
);
#endif
}
tmport
=
wkport
+
0x16
;
outb
(
0x80
,
tmport
);
}
module_init
(
atp870u_init
);
module_init
(
atp870u_init
);
module_exit
(
atp870u_exit
);
module_exit
(
atp870u_exit
);
drivers/scsi/atp870u.h
View file @
ef4333ae
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#define _ATP870U_H
#define _ATP870U_H
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
/* I/O Port */
/* I/O Port */
...
@@ -11,39 +12,52 @@
...
@@ -11,39 +12,52 @@
#define ATP870U_SCATTER 128
#define ATP870U_SCATTER 128
#define ATP870U_CMDLUN 1
#define ATP870U_CMDLUN 1
struct
atp_unit
{
#define MAX_ADAPTER 8
unsigned
long
ioport
;
#define MAX_SCSI_ID 16
unsigned
long
pciport
;
#define ATP870U_MAX_SECTORS 128
unsigned
char
last_cmd
;
unsigned
char
in_snd
;
#define ATP885_DEVID 0x808A
unsigned
char
in_int
;
#define ATP880_DEVID1 0x8080
unsigned
char
quhdu
;
#define ATP880_DEVID2 0x8081
unsigned
char
quendu
;
//#define ED_DBGP
struct
atp_unit
{
unsigned
long
baseport
;
unsigned
long
ioport
[
2
];
unsigned
long
pciport
[
2
];
unsigned
long
irq
;
unsigned
char
last_cmd
[
2
];
unsigned
char
in_snd
[
2
];
unsigned
char
in_int
[
2
];
unsigned
char
quhd
[
2
];
unsigned
char
quend
[
2
];
unsigned
char
global_map
[
2
];
unsigned
char
chip_ver
;
unsigned
char
scam_on
;
unsigned
char
scam_on
;
unsigned
char
global_map
;
unsigned
char
host_id
[
2
];
unsigned
char
chip_veru
;
unsigned
int
working
[
2
];
unsigned
char
host_idu
;
unsigned
short
wide_id
[
2
];
volatile
int
working
;
unsigned
short
active_id
[
2
];
unsigned
short
wide_idu
;
unsigned
short
ultra_map
[
2
];
unsigned
short
active_idu
;
unsigned
short
async
[
2
];
unsigned
short
ultra_map
;
unsigned
short
dev_id
;
unsigned
short
async
;
unsigned
char
sp
[
2
][
16
];
unsigned
short
deviceid
;
unsigned
char
r1f
[
2
][
16
];
unsigned
char
ata_cdbu
[
16
];
struct
scsi_cmnd
*
quereq
[
2
][
qcnt
];
unsigned
char
sp
[
16
];
struct
atp_id
struct
scsi_cmnd
*
querequ
[
qcnt
];
{
struct
atp_id
{
unsigned
char
dirct
;
unsigned
char
dirctu
;
unsigned
char
devsp
;
unsigned
char
devspu
;
unsigned
char
devtype
;
unsigned
char
devtypeu
;
unsigned
long
tran_len
;
unsigned
long
prdaddru
;
unsigned
long
last_len
;
unsigned
long
tran_lenu
;
unsigned
char
*
prd_pos
;
unsigned
long
last_lenu
;
unsigned
char
*
prd_table
;
unsigned
char
*
prd_posu
;
dma_addr_t
prdaddr
;
unsigned
char
*
prd_tableu
;
dma_addr_t
prd_phys
;
struct
scsi_cmnd
*
curr_req
;
struct
scsi_cmnd
*
curr_req
;
}
id
[
16
];
}
id
[
2
][
16
];
struct
Scsi_Host
*
host
;
struct
Scsi_Host
*
host
;
struct
pci_dev
*
pdev
;
struct
pci_dev
*
pdev
;
unsigned
int
unit
;
unsigned
int
unit
;
...
...
drivers/usb/media/Kconfig
View file @
ef4333ae
...
@@ -175,3 +175,39 @@ config USB_W9968CF
...
@@ -175,3 +175,39 @@ config USB_W9968CF
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called w9968cf.
module will be called w9968cf.
config USB_PWC
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
---help---
Say Y or M here if you want to use one of these Philips & OEM
webcams:
* Philips PCA645, PCA646
* Philips PCVC675, PCVC680, PCVC690
* Philips PCVC720/40, PCVC730, PCVC740, PCVC750
* Askey VC010
* Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
and 'Orbit'/'Sphere'
* Samsung MPC-C10, MPC-C30
* Creative Webcam 5, Pro Ex
* SOTEC Afina Eye
* Visionite VCS-UC300, VCS-UM100
The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
and never will be, but the 665 and 720/20 are supported by other
drivers.
See <file:Documentation/usb/philips.txt> for more information and
installation instructions.
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called pwc.
drivers/usb/media/Makefile
View file @
ef4333ae
...
@@ -14,3 +14,4 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102.o
...
@@ -14,3 +14,4 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102.o
obj-$(CONFIG_USB_STV680)
+=
stv680.o
obj-$(CONFIG_USB_STV680)
+=
stv680.o
obj-$(CONFIG_USB_VICAM)
+=
vicam.o usbvideo.o
obj-$(CONFIG_USB_VICAM)
+=
vicam.o usbvideo.o
obj-$(CONFIG_USB_W9968CF)
+=
w9968cf.o
obj-$(CONFIG_USB_W9968CF)
+=
w9968cf.o
obj-$(CONFIG_USB_PWC)
+=
pwc/
drivers/usb/media/pwc/ChangeLog
0 → 100644
View file @
ef4333ae
9.0.2
* Adding #ifdef to compile PWC before and after 2.6.5
9.0.1
9.0
8.12
* Implement motorized pan/tilt feature for Logitech QuickCam Orbit/Spere.
8.11.1
* Fix for PCVC720/40, would not be able to set videomode
* Fix for Samsung MPC models, appearantly they are based on a newer chipset
8.11
* 20 dev_hints (per request)
* Hot unplugging should be better, no more dangling pointers or memory leaks
* Added reserved Logitech webcam IDs
* Device now remembers size & fps between close()/open()
* Removed palette stuff altogether
8.10.1
* Added IDs for PCVC720K/40 and Creative Labs Webcam Pro
8.10
* Fixed ID for QuickCam Notebook pro
* Added GREALSIZE ioctl() call
* Fixed bug in case PWCX was not loaded and invalid size was set
8.9
* Merging with kernel 2.5.49
* Adding IDs for QuickCam Zoom & QuickCam Notebook
8.8
* Fixing 'leds' parameter
* Adding IDs for Logitech QuickCam Pro 4000
* Making URB init/cleanup a little nicer
8.7
* Incorporating changes in ioctl() parameter passing
* Also changes to URB mechanism
8.6
* Added ID's for Visionite VCS UM100 and UC300
* Removed YUV420-interlaced palette altogether (was confusing)
* Removed MIRROR stuff as it didn't work anyway
* Fixed a problem with the 'leds' parameter (wouldn't blink)
* Added ioctl()s for advanced features: 'extended' whitebalance ioctl()s,
CONTOUR, BACKLIGHT, FLICKER, DYNNOISE.
* VIDIOCGCAP.name now contains real camera model name instead of
'Philips xxx webcam'
* Added PROBE ioctl (see previous point & API doc)
8.5
* Adding IDs for Creative Labs Webcam 5
* Adding IDs for SOTEC CMS-001 webcam
* Solving possible hang in VIDIOCSYNC when unplugging the cam
* Forgot to return structure in VIDIOCPWCGAWB, oops
* Time interval for the LEDs are now in milliseconds
8.4
* Fixing power_save option for Vesta range
* Handling new error codes in ISOC callback
* Adding dev_hint module parameter, to specify /dev/videoX device nodes
8.3
* Adding Samsung C10 and C30 cameras
* Removing palette module parameter
* Fixed typo in ID of QuickCam 3000 Pro
* Adding LED settings (blinking while in use) for ToUCam cameras.
* Turns LED off when camera is not in use.
8.2
* Making module more silent when trace = 0
* Adding QuickCam 3000 Pro IDs
* Chrominance control for the Vesta cameras
* Hopefully fixed problems on machines with BIGMEM and > 1GB of RAM
* Included Oliver Neukem's lock_kernel() patch
* Allocates less memory for image buffers
* Adds ioctl()s for the whitebalancing
8.1
* Adding support for 750
* Adding V4L GAUDIO/SAUDIO/UNIT ioctl() calls
8.0
* 'damage control' after inclusion in 2.4.5.
* Changed wait-queue mechanism in read/mmap/poll according to the book.
* Included YUV420P palette.
* Changed interface to decompressor module.
* Cleaned up pwc structure a bit.
7.0
* Fixed bug in vcvt_420i_yuyv; extra variables on stack were misaligned.
* There is now a clear error message when an image size is selected that
is only supported using the decompressor, and the decompressor isn't
loaded.
* When the decompressor wasn't loaded, selecting large image size
would create skewed or double images.
6.3
* Introduced spinlocks for the buffer pointer manipulation; a number of
reports seem to suggest the down()/up() semaphores were the cause of
lockups, since they are not suitable for interrupt/user locking.
* Separated decompressor and core code into 2 modules.
6.2
* Non-integral image sizes are now padded with gray or black.
* Added SHUTTERSPEED ioctl().
* Fixed buglet in VIDIOCPWCSAGC; the function would always return an error,
even though the call succeeded.
* Added hotplug support for 2.4.*.
* Memory: the 645/646 uses less memory now.
6.1
* VIDIOCSPICT returns -EINVAL with invalid palettes.
* Added saturation control.
* Split decompressors from rest.
* Fixed bug that would reset the framerate to the default framerate if
the rate field was set to 0 (which is not what I intended, nl. do not
change the framerate!).
* VIDIOCPWCSCQUAL (setting compression quality) now takes effect immediately.
* Workaround for a bug in the 730 sensor.
drivers/usb/media/pwc/Makefile
0 → 100644
View file @
ef4333ae
ifneq
($(KERNELRELEASE),)
pwc-objs
:=
pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
obj-$(CONFIG_USB_PWC)
+=
pwc.o
else
KDIR
:=
/lib/modules/
$(
shell
uname
-r
)
/build
PWD
:=
$(
shell
pwd
)
default
:
$(MAKE)
-C
$(KDIR)
SUBDIRS
=
$(PWD)
modules
endif
clean
:
rm
-f
*
.[oas] .
*
.flags
*
.ko .
*
.cmd .
*
.d .
*
.tmp
*
.mod.c
rm
-rf
.tmp_versions
drivers/usb/media/pwc/philips.txt
0 → 100644
View file @
ef4333ae
This file contains some additional information for the Philips and OEM webcams.
E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
Site: http://www.smcc.demon.nl/webcam/
As of this moment, the following cameras are supported:
* Philips PCA645
* Philips PCA646
* Philips PCVC675
* Philips PCVC680
* Philips PCVC690
* Philips PCVC720/40
* Philips PCVC730
* Philips PCVC740
* Philips PCVC750
* Askey VC010
* Creative Labs Webcam 5
* Creative Labs Webcam Pro Ex
* Logitech QuickCam 3000 Pro
* Logitech QuickCam 4000 Pro
* Logitech QuickCam Notebook Pro
* Logitech QuickCam Zoom
* Logitech QuickCam Orbit
* Logitech QuickCam Sphere
* Samsung MPC-C10
* Samsung MPC-C30
* Sotec Afina Eye
* AME CU-001
* Visionite VCS-UM100
* Visionite VCS-UC300
The main webpage for the Philips driver is at the address above. It contains
a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
contains decompression routines that allow you to use higher image sizes and
framerates; in addition the webcam uses less bandwidth on the USB bus (handy
if you want to run more than 1 camera simultaneously). These routines fall
under a NDA, and may therefor not be distributed as source; however, its use
is completely optional.
You can build this code either into your kernel, or as a module. I recommend
the latter, since it makes troubleshooting a lot easier. The built-in
microphone is supported through the USB Audio class.
When you load the module you can set some default settings for the
camera; some programs depend on a particular image-size or -format and
don't know how to set it properly in the driver. The options are:
size
Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
'vga', for an image size of resp. 128x96, 160x120, 176x144,
320x240, 352x288 and 640x480 (of course, only for those cameras that
support these resolutions).
fps
Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs
This paramter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from
the cam is a bit slow or momentarely busy. However, on slow machines it
only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5.
mbufs
This is an integer between 1 and 10. It will tell the module the number of
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
The default is 2, which is adequate for most applications (double
buffering).
Should you experience a lot of 'Dumping frame...' messages during
grabbing with a tool that uses mmap(), you might want to increase if.
However, it doesn't really buffer images, it just gives you a bit more
slack when your program is behind. But you need a multi-threaded or
forked program to really take advantage of these buffers.
The absolute maximum is 10, but don't set it too high! Every buffer takes
up 460 KB of RAM, so unless you have a lot of memory setting this to
something more than 4 is an absolute waste. This memory is only
allocated during open(), so nothing is wasted when the camera is not in
use.
power_save
When power_save is enabled (set to 1), the module will try to shut down
the cam on close() and re-activate on open(). This will save power and
turn off the LED. Not all cameras support this though (the 645 and 646
don't have power saving at all), and some models don't work either (they
will shut down, but never wake up). Consider this experimental. By
default this option is disabled.
compression (only useful with the plugin)
With this option you can control the compression factor that the camera
uses to squeeze the image through the USB bus. You can set the
parameter between 0 and 3:
0 = prefer uncompressed images; if the requested mode is not available
in an uncompressed format, the driver will silently switch to low
compression.
1 = low compression.
2 = medium compression.
3 = high compression.
High compression takes less bandwidth of course, but it could also
introduce some unwanted artefacts. The default is 2, medium compression.
See the FAQ on the website for an overview of which modes require
compression.
The compression parameter does not apply to the 645 and 646 cameras
and OEM models derived from those (only a few). Most cams honour this
parameter.
leds
This settings takes 2 integers, that define the on/off time for the LED
(in milliseconds). One of the interesting things that you can do with
this is let the LED blink while the camera is in use. This:
leds=500,500
will blink the LED once every second. But with:
leds=0,0
the LED never goes on, making it suitable for silent surveillance.
By default the camera's LED is on solid while in use, and turned off
when the camera is not used anymore.
This parameter works only with the ToUCam range of cameras (720, 730, 740,
750) and OEMs. For other cameras this command is silently ignored, and
the LED cannot be controlled.
Finally: this parameters does not take effect UNTIL the first time you
open the camera device. Until then, the LED remains on.
dev_hint
A long standing problem with USB devices is their dynamic nature: you
never know what device a camera gets assigned; it depends on module load
order, the hub configuration, the order in which devices are plugged in,
and the phase of the moon (i.e. it can be random). With this option you
can give the driver a hint as to what video device node (/dev/videoX) it
should use with a specific camera. This is also handy if you have two
cameras of the same model.
A camera is specified by its type (the number from the camera model,
like PCA645, PCVC750VC, etc) and optionally the serial number (visible
in /proc/bus/usb/devices). A hint consists of a string with the following
format:
[type[.serialnumber]:]node
The square brackets mean that both the type and the serialnumber are
optional, but a serialnumber cannot be specified without a type (which
would be rather pointless). The serialnumber is separated from the type
by a '.'; the node number by a ':'.
This somewhat cryptic syntax is best explained by a few examples:
dev_hint=3,5 The first detected cam gets assigned
/dev/video3, the second /dev/video5. Any
other cameras will get the first free
available slot (see below).
dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
and a PCVC680 /dev/video2.
dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
0123 goes to /dev/video3, the same
camera model with the 4567 serial
gets /dev/video0.
dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
next 3 Philips cams will use /dev/video4
through /dev/video6.
Some points worth knowing:
- Serialnumbers are case sensitive and must be written full, including
leading zeroes (it's treated as a string).
- If a device node is already occupied, registration will fail and
the webcam is not available.
- You can have up to 64 video devices; be sure to make enough device
nodes in /dev if you want to spread the numbers (this does not apply
to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
- If a camera does not match any dev_hint, it will simply get assigned
the first available device node, just as it used to be.
trace
In order to better detect problems, it is now possible to turn on a
'trace' of some of the calls the module makes; it logs all items in your
kernel log at debug level.
The trace variable is a bitmask; each bit represents a certain feature.
If you want to trace something, look up the bit value(s) in the table
below, add the values together and supply that to the trace variable.
Value Value Description Default
(dec) (hex)
1 0x1 Module initialization; this will log messages On
while loading and unloading the module
2 0x2 probe() and disconnect() traces On
4 0x4 Trace open() and close() calls Off
8 0x8 read(), mmap() and associated ioctl() calls Off
16 0x10 Memory allocation of buffers, etc. Off
32 0x20 Showing underflow, overflow and Dumping frame On
messages
64 0x40 Show viewport and image sizes Off
128 0x80 PWCX debugging Off
For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
so you would supply trace=12 during insmod or modprobe. If
you want to turn the initialization and probing tracing off, set trace=0.
The default value for trace is 35 (0x23).
Example:
# modprobe pwc size=cif fps=15 power_save=1
The fbufs, mbufs and trace parameters are global and apply to all connected
cameras. Each camera has its own set of buffers.
size and fps only specify defaults when you open() the device; this is to
accommodate some tools that don't set the size. You can change these
settings after open() with the Video4Linux ioctl() calls. The default of
defaults is QCIF size at 10 fps.
The compression parameter is semiglobal; it sets the initial compression
preference for all camera's, but this parameter can be set per camera with
the VIDIOCPWCSCQUAL ioctl() call.
All parameters are optional.
drivers/usb/media/pwc/pwc-ctrl.c
0 → 100644
View file @
ef4333ae
/* Driver for Philips webcam
Functions that send various control messages to the webcam, including
video modes.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
Changes
2001/08/03 Alvarado Added methods for changing white balance and
red/green gains
*/
/* Control functions for the cam; brightness, contrast, video mode, etc. */
#ifdef __KERNEL__
#include <asm/uaccess.h>
#endif
#include <asm/errno.h>
#include <linux/version.h>
#include "pwc.h"
#include "pwc-ioctl.h"
#include "pwc-uncompress.h"
#include "pwc-kiara.h"
#include "pwc-timon.h"
#include "pwc-dec1.h"
#include "pwc-dec23.h"
/* Request types: video */
#define SET_LUM_CTL 0x01
#define GET_LUM_CTL 0x02
#define SET_CHROM_CTL 0x03
#define GET_CHROM_CTL 0x04
#define SET_STATUS_CTL 0x05
#define GET_STATUS_CTL 0x06
#define SET_EP_STREAM_CTL 0x07
#define GET_EP_STREAM_CTL 0x08
#define SET_MPT_CTL 0x0D
#define GET_MPT_CTL 0x0E
/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
#define AGC_MODE_FORMATTER 0x2000
#define PRESET_AGC_FORMATTER 0x2100
#define SHUTTER_MODE_FORMATTER 0x2200
#define PRESET_SHUTTER_FORMATTER 0x2300
#define PRESET_CONTOUR_FORMATTER 0x2400
#define AUTO_CONTOUR_FORMATTER 0x2500
#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
#define CONTRAST_FORMATTER 0x2700
#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
#define FLICKERLESS_MODE_FORMATTER 0x2900
#define AE_CONTROL_SPEED 0x2A00
#define BRIGHTNESS_FORMATTER 0x2B00
#define GAMMA_FORMATTER 0x2C00
/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
#define WB_MODE_FORMATTER 0x1000
#define AWB_CONTROL_SPEED_FORMATTER 0x1100
#define AWB_CONTROL_DELAY_FORMATTER 0x1200
#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
#define COLOUR_MODE_FORMATTER 0x1500
#define SATURATION_MODE_FORMATTER1 0x1600
#define SATURATION_MODE_FORMATTER2 0x1700
/* Selectors for the Status controls [GS]ET_STATUS_CTL */
#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
#define READ_AGC_FORMATTER 0x0500
#define READ_SHUTTER_FORMATTER 0x0600
#define READ_RED_GAIN_FORMATTER 0x0700
#define READ_BLUE_GAIN_FORMATTER 0x0800
#define SENSOR_TYPE_FORMATTER1 0x0C00
#define READ_RAW_Y_MEAN_FORMATTER 0x3100
#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
#define MIRROR_IMAGE_FORMATTER 0x3300
#define LED_FORMATTER 0x3400
#define SENSOR_TYPE_FORMATTER2 0x3700
/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
#define PT_RELATIVE_CONTROL_FORMATTER 0x01
#define PT_RESET_CONTROL_FORMATTER 0x02
#define PT_STATUS_FORMATTER 0x03
static
char
*
size2name
[
PSZ_MAX
]
=
{
"subQCIF"
,
"QSIF"
,
"QCIF"
,
"SIF"
,
"CIF"
,
"VGA"
,
};
/********/
/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
preferences, so you either get compressed or non-compressed streams.
An alternate value of 0 means this mode is not available at all.
*/
struct
Nala_table_entry
{
char
alternate
;
/* USB alternate setting */
int
compressed
;
/* Compressed yes/no */
unsigned
char
mode
[
3
];
/* precomputed mode table */
};
static
struct
Nala_table_entry
Nala_table
[
PSZ_MAX
][
8
]
=
{
#include "pwc-nala.h"
};
/****************************************************************************/
#define SendControlMsg(request, value, buflen) \
usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
request, \
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
value, \
pdev->vcinterface, \
&buf, buflen, HZ / 2)
#define RecvControlMsg(request, value, buflen) \
usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
request, \
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
value, \
pdev->vcinterface, \
&buf, buflen, HZ / 2)
#if PWC_DEBUG
void
pwc_hexdump
(
void
*
p
,
int
len
)
{
int
i
;
unsigned
char
*
s
;
char
buf
[
100
],
*
d
;
s
=
(
unsigned
char
*
)
p
;
d
=
buf
;
*
d
=
'\0'
;
Debug
(
"Doing hexdump @ %p, %d bytes.
\n
"
,
p
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
d
+=
sprintf
(
d
,
"%02X "
,
*
s
++
);
if
((
i
&
0xF
)
==
0xF
)
{
Debug
(
"%s
\n
"
,
buf
);
d
=
buf
;
*
d
=
'\0'
;
}
}
if
((
i
&
0xF
)
!=
0
)
Debug
(
"%s
\n
"
,
buf
);
}
#endif
static
inline
int
send_video_command
(
struct
usb_device
*
udev
,
int
index
,
void
*
buf
,
int
buflen
)
{
return
usb_control_msg
(
udev
,
usb_sndctrlpipe
(
udev
,
0
),
SET_EP_STREAM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
VIDEO_OUTPUT_CONTROL_FORMATTER
,
index
,
buf
,
buflen
,
HZ
);
}
static
inline
int
set_video_mode_Nala
(
struct
pwc_device
*
pdev
,
int
size
,
int
frames
)
{
unsigned
char
buf
[
3
];
int
ret
,
fps
;
struct
Nala_table_entry
*
pEntry
;
int
frames2frames
[
31
]
=
{
/* closest match of framerate */
0
,
0
,
0
,
0
,
4
,
/* 0-4 */
5
,
5
,
7
,
7
,
10
,
/* 5-9 */
10
,
10
,
12
,
12
,
15
,
/* 10-14 */
15
,
15
,
15
,
20
,
20
,
/* 15-19 */
20
,
20
,
20
,
24
,
24
,
/* 20-24 */
24
,
24
,
24
,
24
,
24
,
/* 25-29 */
24
/* 30 */
};
int
frames2table
[
31
]
=
{
0
,
0
,
0
,
0
,
0
,
/* 0-4 */
1
,
1
,
1
,
2
,
2
,
/* 5-9 */
3
,
3
,
4
,
4
,
4
,
/* 10-14 */
5
,
5
,
5
,
5
,
5
,
/* 15-19 */
6
,
6
,
6
,
6
,
7
,
/* 20-24 */
7
,
7
,
7
,
7
,
7
,
/* 25-29 */
7
/* 30 */
};
if
(
size
<
0
||
size
>
PSZ_CIF
||
frames
<
4
||
frames
>
25
)
return
-
EINVAL
;
frames
=
frames2frames
[
frames
];
fps
=
frames2table
[
frames
];
pEntry
=
&
Nala_table
[
size
][
fps
];
if
(
pEntry
->
alternate
==
0
)
return
-
EINVAL
;
if
(
pEntry
->
compressed
)
return
-
ENOENT
;
/* Not supported. */
memcpy
(
buf
,
pEntry
->
mode
,
3
);
ret
=
send_video_command
(
pdev
->
udev
,
pdev
->
vendpoint
,
buf
,
3
);
if
(
ret
<
0
)
{
Debug
(
"Failed to send video command... %d
\n
"
,
ret
);
return
ret
;
}
if
(
pEntry
->
compressed
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
{
switch
(
pdev
->
type
)
{
case
645
:
case
646
:
pwc_dec1_init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
break
;
case
675
:
case
680
:
case
690
:
case
720
:
case
730
:
case
740
:
case
750
:
pwc_dec23_init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
break
;
}
}
pdev
->
cmd_len
=
3
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
3
);
/* Set various parameters */
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
valternate
=
pEntry
->
alternate
;
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
3
)
/
2
;
if
(
pEntry
->
compressed
)
{
if
(
pdev
->
release
<
5
)
{
/* 4 fold compression */
pdev
->
vbandlength
=
528
;
pdev
->
frame_size
/=
4
;
}
else
{
pdev
->
vbandlength
=
704
;
pdev
->
frame_size
/=
3
;
}
}
else
pdev
->
vbandlength
=
0
;
return
0
;
}
static
inline
int
set_video_mode_Timon
(
struct
pwc_device
*
pdev
,
int
size
,
int
frames
,
int
compression
,
int
snapshot
)
{
unsigned
char
buf
[
13
];
const
struct
Timon_table_entry
*
pChoose
;
int
ret
,
fps
;
if
(
size
>=
PSZ_MAX
||
frames
<
5
||
frames
>
30
||
compression
<
0
||
compression
>
3
)
return
-
EINVAL
;
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
return
-
EINVAL
;
fps
=
(
frames
/
5
)
-
1
;
/* Find a supported framerate with progressively higher compression ratios
if the preferred ratio is not available.
*/
pChoose
=
NULL
;
while
(
compression
<=
3
)
{
pChoose
=
&
Timon_table
[
size
][
fps
][
compression
];
if
(
pChoose
->
alternate
!=
0
)
break
;
compression
++
;
}
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
return
-
ENOENT
;
/* Not supported. */
memcpy
(
buf
,
pChoose
->
mode
,
13
);
if
(
snapshot
)
buf
[
0
]
|=
0x80
;
ret
=
send_video_command
(
pdev
->
udev
,
pdev
->
vendpoint
,
buf
,
13
);
if
(
ret
<
0
)
return
ret
;
if
(
pChoose
->
bandlength
>
0
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
pwc_dec23_init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
cmd_len
=
13
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
13
);
/* Set various parameters */
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
vsnapshot
=
snapshot
;
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
vbandlength
=
pChoose
->
bandlength
;
if
(
pChoose
->
bandlength
>
0
)
pdev
->
frame_size
=
(
pChoose
->
bandlength
*
pdev
->
image
.
y
)
/
4
;
else
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
return
0
;
}
static
inline
int
set_video_mode_Kiara
(
struct
pwc_device
*
pdev
,
int
size
,
int
frames
,
int
compression
,
int
snapshot
)
{
const
struct
Kiara_table_entry
*
pChoose
=
0
;
int
fps
,
ret
;
unsigned
char
buf
[
12
];
struct
Kiara_table_entry
RawEntry
=
{
6
,
773
,
1272
,
{
0xAD
,
0xF4
,
0x10
,
0x27
,
0xB6
,
0x24
,
0x96
,
0x02
,
0x30
,
0x05
,
0x03
,
0x80
}};
if
(
size
>=
PSZ_MAX
||
frames
<
5
||
frames
>
30
||
compression
<
0
||
compression
>
3
)
return
-
EINVAL
;
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
return
-
EINVAL
;
fps
=
(
frames
/
5
)
-
1
;
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
if
(
size
==
PSZ_VGA
&&
frames
==
5
&&
snapshot
)
{
/* Only available in case the raw palette is selected or
we have the decompressor available. This mode is
only available in compressed form
*/
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
{
Info
(
"Choosing VGA/5 BAYER mode (%d).
\n
"
,
pdev
->
vpalette
);
pChoose
=
&
RawEntry
;
}
else
{
Info
(
"VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.
\n
"
);
}
}
else
{
/* Find a supported framerate with progressively higher compression ratios
if the preferred ratio is not available.
Skip this step when using RAW modes.
*/
while
(
compression
<=
3
)
{
pChoose
=
&
Kiara_table
[
size
][
fps
][
compression
];
if
(
pChoose
->
alternate
!=
0
)
break
;
compression
++
;
}
}
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
return
-
ENOENT
;
/* Not supported. */
Debug
(
"Using alternate setting %d.
\n
"
,
pChoose
->
alternate
);
/* usb_control_msg won't take staticly allocated arrays as argument?? */
memcpy
(
buf
,
pChoose
->
mode
,
12
);
if
(
snapshot
)
buf
[
0
]
|=
0x80
;
/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
ret
=
send_video_command
(
pdev
->
udev
,
4
/* pdev->vendpoint */
,
buf
,
12
);
if
(
ret
<
0
)
return
ret
;
if
(
pChoose
->
bandlength
>
0
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
pwc_dec23_init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
cmd_len
=
12
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
12
);
/* All set and go */
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
vsnapshot
=
snapshot
;
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
vbandlength
=
pChoose
->
bandlength
;
if
(
pdev
->
vbandlength
>
0
)
pdev
->
frame_size
=
(
pdev
->
vbandlength
*
pdev
->
image
.
y
)
/
4
;
else
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
return
0
;
}
/**
@pdev: device structure
@width: viewport width
@height: viewport height
@frame: framerate, in fps
@compression: preferred compression ratio
@snapshot: snapshot mode or streaming
*/
int
pwc_set_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
frames
,
int
compression
,
int
snapshot
)
{
int
ret
,
size
;
Trace
(
TRACE_FLOW
,
"set_video_mode(%dx%d @ %d, palette %d).
\n
"
,
width
,
height
,
frames
,
pdev
->
vpalette
);
size
=
pwc_decode_size
(
pdev
,
width
,
height
);
if
(
size
<
0
)
{
Debug
(
"Could not find suitable size.
\n
"
);
return
-
ERANGE
;
}
Debug
(
"decode_size = %d.
\n
"
,
size
);
ret
=
-
EINVAL
;
switch
(
pdev
->
type
)
{
case
645
:
case
646
:
ret
=
set_video_mode_Nala
(
pdev
,
size
,
frames
);
break
;
case
675
:
case
680
:
case
690
:
ret
=
set_video_mode_Timon
(
pdev
,
size
,
frames
,
compression
,
snapshot
);
break
;
case
720
:
case
730
:
case
740
:
case
750
:
ret
=
set_video_mode_Kiara
(
pdev
,
size
,
frames
,
compression
,
snapshot
);
break
;
}
if
(
ret
<
0
)
{
if
(
ret
==
-
ENOENT
)
Info
(
"Video mode %s@%d fps is only supported with the decompressor module (pwcx).
\n
"
,
size2name
[
size
],
frames
);
else
{
Err
(
"Failed to set video mode %s@%d fps; return code = %d
\n
"
,
size2name
[
size
],
frames
,
ret
);
}
return
ret
;
}
pdev
->
view
.
x
=
width
;
pdev
->
view
.
y
=
height
;
pdev
->
frame_total_size
=
pdev
->
frame_size
+
pdev
->
frame_header_size
+
pdev
->
frame_trailer_size
;
pwc_set_image_buffer_size
(
pdev
);
Trace
(
TRACE_SIZE
,
"Set viewport to %dx%d, image size is %dx%d.
\n
"
,
width
,
height
,
pwc_image_sizes
[
size
].
x
,
pwc_image_sizes
[
size
].
y
);
return
0
;
}
void
pwc_set_image_buffer_size
(
struct
pwc_device
*
pdev
)
{
int
i
,
factor
=
0
,
filler
=
0
;
/* for PALETTE_YUV420P */
switch
(
pdev
->
vpalette
)
{
case
VIDEO_PALETTE_YUV420P
:
factor
=
6
;
filler
=
128
;
break
;
case
VIDEO_PALETTE_RAW
:
factor
=
6
;
/* can be uncompressed YUV420P */
filler
=
0
;
break
;
}
/* Set sizes in bytes */
pdev
->
image
.
size
=
pdev
->
image
.
x
*
pdev
->
image
.
y
*
factor
/
4
;
pdev
->
view
.
size
=
pdev
->
view
.
x
*
pdev
->
view
.
y
*
factor
/
4
;
/* Align offset, or you'll get some very weird results in
YUV420 mode... x must be multiple of 4 (to get the Y's in
place), and y even (or you'll mixup U & V). This is less of a
problem for YUV420P.
*/
pdev
->
offset
.
x
=
((
pdev
->
view
.
x
-
pdev
->
image
.
x
)
/
2
)
&
0xFFFC
;
pdev
->
offset
.
y
=
((
pdev
->
view
.
y
-
pdev
->
image
.
y
)
/
2
)
&
0xFFFE
;
/* Fill buffers with gray or black */
for
(
i
=
0
;
i
<
MAX_IMAGES
;
i
++
)
{
if
(
pdev
->
image_ptr
[
i
]
!=
NULL
)
memset
(
pdev
->
image_ptr
[
i
],
filler
,
pdev
->
view
.
size
);
}
}
/* BRIGHTNESS */
int
pwc_get_brightness
(
struct
pwc_device
*
pdev
)
{
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
BRIGHTNESS_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
buf
<<
9
;
}
int
pwc_set_brightness
(
struct
pwc_device
*
pdev
,
int
value
)
{
char
buf
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
buf
=
(
value
>>
9
)
&
0x7f
;
return
SendControlMsg
(
SET_LUM_CTL
,
BRIGHTNESS_FORMATTER
,
1
);
}
/* CONTRAST */
int
pwc_get_contrast
(
struct
pwc_device
*
pdev
)
{
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
CONTRAST_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
buf
<<
10
;
}
int
pwc_set_contrast
(
struct
pwc_device
*
pdev
,
int
value
)
{
char
buf
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
buf
=
(
value
>>
10
)
&
0x3f
;
return
SendControlMsg
(
SET_LUM_CTL
,
CONTRAST_FORMATTER
,
1
);
}
/* GAMMA */
int
pwc_get_gamma
(
struct
pwc_device
*
pdev
)
{
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
GAMMA_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
buf
<<
11
;
}
int
pwc_set_gamma
(
struct
pwc_device
*
pdev
,
int
value
)
{
char
buf
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
buf
=
(
value
>>
11
)
&
0x1f
;
return
SendControlMsg
(
SET_LUM_CTL
,
GAMMA_FORMATTER
,
1
);
}
/* SATURATION */
int
pwc_get_saturation
(
struct
pwc_device
*
pdev
)
{
char
buf
;
int
ret
;
if
(
pdev
->
type
<
675
)
return
-
1
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
1
);
if
(
ret
<
0
)
return
ret
;
return
32768
+
buf
*
327
;
}
int
pwc_set_saturation
(
struct
pwc_device
*
pdev
,
int
value
)
{
char
buf
;
if
(
pdev
->
type
<
675
)
return
-
EINVAL
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
/* saturation ranges from -100 to +100 */
buf
=
(
value
-
32768
)
/
327
;
return
SendControlMsg
(
SET_CHROM_CTL
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
1
);
}
/* AGC */
static
inline
int
pwc_set_agc
(
struct
pwc_device
*
pdev
,
int
mode
,
int
value
)
{
char
buf
;
int
ret
;
if
(
mode
)
buf
=
0x0
;
/* auto */
else
buf
=
0xff
;
/* fixed */
ret
=
SendControlMsg
(
SET_LUM_CTL
,
AGC_MODE_FORMATTER
,
1
);
if
(
!
mode
&&
ret
>=
0
)
{
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
buf
=
(
value
>>
10
)
&
0x3F
;
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_AGC_FORMATTER
,
1
);
}
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
inline
int
pwc_get_agc
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
AGC_MODE_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
buf
!=
0
)
{
/* fixed */
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
PRESET_AGC_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
buf
>
0x3F
)
buf
=
0x3F
;
*
value
=
(
buf
<<
10
);
}
else
{
/* auto */
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_AGC_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
/* Gah... this value ranges from 0x00 ... 0x9F */
if
(
buf
>
0x9F
)
buf
=
0x9F
;
*
value
=
-
(
48
+
buf
*
409
);
}
return
0
;
}
static
inline
int
pwc_set_shutter_speed
(
struct
pwc_device
*
pdev
,
int
mode
,
int
value
)
{
char
buf
[
2
];
int
speed
,
ret
;
if
(
mode
)
buf
[
0
]
=
0x0
;
/* auto */
else
buf
[
0
]
=
0xff
;
/* fixed */
ret
=
SendControlMsg
(
SET_LUM_CTL
,
SHUTTER_MODE_FORMATTER
,
1
);
if
(
!
mode
&&
ret
>=
0
)
{
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
switch
(
pdev
->
type
)
{
case
675
:
case
680
:
case
690
:
/* speed ranges from 0x0 to 0x290 (656) */
speed
=
(
value
/
100
);
buf
[
1
]
=
speed
>>
8
;
buf
[
0
]
=
speed
&
0xff
;
break
;
case
720
:
case
730
:
case
740
:
case
750
:
/* speed seems to range from 0x0 to 0xff */
buf
[
1
]
=
0
;
buf
[
0
]
=
value
>>
8
;
break
;
}
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_SHUTTER_FORMATTER
,
2
);
}
return
ret
;
}
/* POWER */
int
pwc_camera_power
(
struct
pwc_device
*
pdev
,
int
power
)
{
char
buf
;
if
(
pdev
->
type
<
675
||
(
pdev
->
type
<
730
&&
pdev
->
release
<
6
))
return
0
;
/* Not supported by Nala or Timon < release 6 */
if
(
power
)
buf
=
0x00
;
/* active */
else
buf
=
0xFF
;
/* power save */
return
SendControlMsg
(
SET_STATUS_CTL
,
SET_POWER_SAVE_MODE_FORMATTER
,
1
);
}
/* private calls */
static
inline
int
pwc_restore_user
(
struct
pwc_device
*
pdev
)
{
char
buf
;
/* dummy */
return
SendControlMsg
(
SET_STATUS_CTL
,
RESTORE_USER_DEFAULTS_FORMATTER
,
0
);
}
static
inline
int
pwc_save_user
(
struct
pwc_device
*
pdev
)
{
char
buf
;
/* dummy */
return
SendControlMsg
(
SET_STATUS_CTL
,
SAVE_USER_DEFAULTS_FORMATTER
,
0
);
}
static
inline
int
pwc_restore_factory
(
struct
pwc_device
*
pdev
)
{
char
buf
;
/* dummy */
return
SendControlMsg
(
SET_STATUS_CTL
,
RESTORE_FACTORY_DEFAULTS_FORMATTER
,
0
);
}
/* ************************************************* */
/* Patch by Alvarado: (not in the original version */
/*
* the camera recognizes modes from 0 to 4:
*
* 00: indoor (incandescant lighting)
* 01: outdoor (sunlight)
* 02: fluorescent lighting
* 03: manual
* 04: auto
*/
static
inline
int
pwc_set_awb
(
struct
pwc_device
*
pdev
,
int
mode
)
{
char
buf
;
int
ret
;
if
(
mode
<
0
)
mode
=
0
;
if
(
mode
>
4
)
mode
=
4
;
buf
=
mode
&
0x07
;
/* just the lowest three bits */
ret
=
SendControlMsg
(
SET_CHROM_CTL
,
WB_MODE_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
inline
int
pwc_get_awb
(
struct
pwc_device
*
pdev
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
WB_MODE_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
buf
;
}
static
inline
int
pwc_set_red_gain
(
struct
pwc_device
*
pdev
,
int
value
)
{
unsigned
char
buf
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
/* only the msb is considered */
buf
=
value
>>
8
;
return
SendControlMsg
(
SET_CHROM_CTL
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
1
);
}
static
inline
int
pwc_get_red_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
<<
8
;
return
0
;
}
static
inline
int
pwc_set_blue_gain
(
struct
pwc_device
*
pdev
,
int
value
)
{
unsigned
char
buf
;
if
(
value
<
0
)
value
=
0
;
if
(
value
>
0xffff
)
value
=
0xffff
;
/* only the msb is considered */
buf
=
value
>>
8
;
return
SendControlMsg
(
SET_CHROM_CTL
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
1
);
}
static
inline
int
pwc_get_blue_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
<<
8
;
return
0
;
}
/* The following two functions are different, since they only read the
internal red/blue gains, which may be different from the manual
gains set or read above.
*/
static
inline
int
pwc_read_red_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_RED_GAIN_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
<<
8
;
return
0
;
}
static
inline
int
pwc_read_blue_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_BLUE_GAIN_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
<<
8
;
return
0
;
}
static
inline
int
pwc_set_wb_speed
(
struct
pwc_device
*
pdev
,
int
speed
)
{
unsigned
char
buf
;
/* useful range is 0x01..0x20 */
buf
=
speed
/
0x7f0
;
return
SendControlMsg
(
SET_CHROM_CTL
,
AWB_CONTROL_SPEED_FORMATTER
,
1
);
}
static
inline
int
pwc_get_wb_speed
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
AWB_CONTROL_SPEED_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
*
0x7f0
;
return
0
;
}
static
inline
int
pwc_set_wb_delay
(
struct
pwc_device
*
pdev
,
int
delay
)
{
unsigned
char
buf
;
/* useful range is 0x01..0x3F */
buf
=
(
delay
>>
10
);
return
SendControlMsg
(
SET_CHROM_CTL
,
AWB_CONTROL_DELAY_FORMATTER
,
1
);
}
static
inline
int
pwc_get_wb_delay
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
AWB_CONTROL_DELAY_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
value
=
buf
<<
10
;
return
0
;
}
int
pwc_set_leds
(
struct
pwc_device
*
pdev
,
int
on_value
,
int
off_value
)
{
unsigned
char
buf
[
2
];
if
(
pdev
->
type
<
730
)
return
0
;
on_value
/=
100
;
off_value
/=
100
;
if
(
on_value
<
0
)
on_value
=
0
;
if
(
on_value
>
0xff
)
on_value
=
0xff
;
if
(
off_value
<
0
)
off_value
=
0
;
if
(
off_value
>
0xff
)
off_value
=
0xff
;
buf
[
0
]
=
on_value
;
buf
[
1
]
=
off_value
;
return
SendControlMsg
(
SET_STATUS_CTL
,
LED_FORMATTER
,
2
);
}
int
pwc_get_leds
(
struct
pwc_device
*
pdev
,
int
*
on_value
,
int
*
off_value
)
{
unsigned
char
buf
[
2
];
int
ret
;
if
(
pdev
->
type
<
730
)
{
*
on_value
=
-
1
;
*
off_value
=
-
1
;
return
0
;
}
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
LED_FORMATTER
,
2
);
if
(
ret
<
0
)
return
ret
;
*
on_value
=
buf
[
0
]
*
100
;
*
off_value
=
buf
[
1
]
*
100
;
return
0
;
}
static
inline
int
pwc_set_contour
(
struct
pwc_device
*
pdev
,
int
contour
)
{
unsigned
char
buf
;
int
ret
;
if
(
contour
<
0
)
buf
=
0xff
;
/* auto contour on */
else
buf
=
0x0
;
/* auto contour off */
ret
=
SendControlMsg
(
SET_LUM_CTL
,
AUTO_CONTOUR_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
contour
<
0
)
return
0
;
if
(
contour
>
0xffff
)
contour
=
0xffff
;
buf
=
(
contour
>>
10
);
/* contour preset is [0..3f] */
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_CONTOUR_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
inline
int
pwc_get_contour
(
struct
pwc_device
*
pdev
,
int
*
contour
)
{
unsigned
char
buf
;
int
ret
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
AUTO_CONTOUR_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
buf
==
0
)
{
/* auto mode off, query current preset value */
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
PRESET_CONTOUR_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
contour
=
buf
<<
10
;
}
else
*
contour
=
-
1
;
return
0
;
}
static
inline
int
pwc_set_backlight
(
struct
pwc_device
*
pdev
,
int
backlight
)
{
unsigned
char
buf
;
if
(
backlight
)
buf
=
0xff
;
else
buf
=
0x0
;
return
SendControlMsg
(
SET_LUM_CTL
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
1
);
}
static
inline
int
pwc_get_backlight
(
struct
pwc_device
*
pdev
,
int
*
backlight
)
{
int
ret
;
unsigned
char
buf
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
backlight
=
buf
;
return
0
;
}
static
inline
int
pwc_set_flicker
(
struct
pwc_device
*
pdev
,
int
flicker
)
{
unsigned
char
buf
;
if
(
flicker
)
buf
=
0xff
;
else
buf
=
0x0
;
return
SendControlMsg
(
SET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
}
static
inline
int
pwc_get_flicker
(
struct
pwc_device
*
pdev
,
int
*
flicker
)
{
int
ret
;
unsigned
char
buf
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
flicker
=
buf
;
return
0
;
}
static
inline
int
pwc_set_dynamic_noise
(
struct
pwc_device
*
pdev
,
int
noise
)
{
unsigned
char
buf
;
if
(
noise
<
0
)
noise
=
0
;
if
(
noise
>
3
)
noise
=
3
;
buf
=
noise
;
return
SendControlMsg
(
SET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
}
static
inline
int
pwc_get_dynamic_noise
(
struct
pwc_device
*
pdev
,
int
*
noise
)
{
int
ret
;
unsigned
char
buf
;
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
if
(
ret
<
0
)
return
ret
;
*
noise
=
buf
;
return
0
;
}
int
pwc_mpt_reset
(
struct
pwc_device
*
pdev
,
int
flags
)
{
unsigned
char
buf
;
buf
=
flags
&
0x03
;
// only lower two bits are currently used
return
SendControlMsg
(
SET_MPT_CTL
,
PT_RESET_CONTROL_FORMATTER
,
1
);
}
static
inline
int
pwc_mpt_set_angle
(
struct
pwc_device
*
pdev
,
int
pan
,
int
tilt
)
{
unsigned
char
buf
[
4
];
/* set new relative angle; angles are expressed in degrees * 100,
but cam as .5 degree resolution, hence devide by 200. Also
the angle must be multiplied by 64 before it's send to
the cam (??)
*/
pan
=
64
*
pan
/
100
;
tilt
=
-
64
*
tilt
/
100
;
/* positive tilt is down, which is not what the user would expect */
buf
[
0
]
=
pan
&
0xFF
;
buf
[
1
]
=
(
pan
>>
8
)
&
0xFF
;
buf
[
2
]
=
tilt
&
0xFF
;
buf
[
3
]
=
(
tilt
>>
8
)
&
0xFF
;
return
SendControlMsg
(
SET_MPT_CTL
,
PT_RELATIVE_CONTROL_FORMATTER
,
4
);
}
static
inline
int
pwc_mpt_get_status
(
struct
pwc_device
*
pdev
,
struct
pwc_mpt_status
*
status
)
{
int
ret
;
unsigned
char
buf
[
5
];
ret
=
RecvControlMsg
(
GET_MPT_CTL
,
PT_STATUS_FORMATTER
,
5
);
if
(
ret
<
0
)
return
ret
;
status
->
status
=
buf
[
0
]
&
0x7
;
// 3 bits are used for reporting
status
->
time_pan
=
(
buf
[
1
]
<<
8
)
+
buf
[
2
];
status
->
time_tilt
=
(
buf
[
3
]
<<
8
)
+
buf
[
4
];
return
0
;
}
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
,
int
*
sensor
)
{
unsigned
char
buf
;
int
ret
=
-
1
,
request
;
if
(
pdev
->
type
<
675
)
request
=
SENSOR_TYPE_FORMATTER1
;
else
if
(
pdev
->
type
<
730
)
return
-
1
;
/* The Vesta series doesn't have this call */
else
request
=
SENSOR_TYPE_FORMATTER2
;
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
request
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
pdev
->
type
<
675
)
*
sensor
=
buf
|
0x100
;
else
*
sensor
=
buf
;
return
0
;
}
/* End of Add-Ons */
/* ************************************************* */
/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
ioctl() calls. With 2.4, you have to do tedious copy_from_user()
and copy_to_user() calls. With these macros we circumvent this,
and let me maintain only one source file. The functionality is
exactly the same otherwise.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
/* define local variable for arg */
#define ARG_DEF(ARG_type, ARG_name)\
ARG_type *ARG_name = arg;
/* copy arg to local variable */
#define ARG_IN(ARG_name)
/* nothing */
/* argument itself (referenced) */
#define ARGR(ARG_name) (*ARG_name)
/* argument address */
#define ARGA(ARG_name) ARG_name
/* copy local variable to arg */
#define ARG_OUT(ARG_name)
/* nothing */
#else
#define ARG_DEF(ARG_type, ARG_name)\
ARG_type ARG_name;
#define ARG_IN(ARG_name)\
if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
ret = -EFAULT;\
break;\
}
#define ARGR(ARG_name) ARG_name
#define ARGA(ARG_name) &ARG_name
#define ARG_OUT(ARG_name)\
if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
ret = -EFAULT;\
break;\
}
#endif
int
pwc_ioctl
(
struct
pwc_device
*
pdev
,
unsigned
int
cmd
,
void
*
arg
)
{
int
ret
=
0
;
switch
(
cmd
)
{
case
VIDIOCPWCRUSER
:
{
if
(
pwc_restore_user
(
pdev
))
ret
=
-
EINVAL
;
break
;
}
case
VIDIOCPWCSUSER
:
{
if
(
pwc_save_user
(
pdev
))
ret
=
-
EINVAL
;
break
;
}
case
VIDIOCPWCFACTORY
:
{
if
(
pwc_restore_factory
(
pdev
))
ret
=
-
EINVAL
;
break
;
}
case
VIDIOCPWCSCQUAL
:
{
ARG_DEF
(
int
,
qual
)
ARG_IN
(
qual
)
if
(
ARGR
(
qual
)
<
0
||
ARGR
(
qual
)
>
3
)
ret
=
-
EINVAL
;
else
ret
=
pwc_try_video_mode
(
pdev
,
pdev
->
view
.
x
,
pdev
->
view
.
y
,
pdev
->
vframes
,
ARGR
(
qual
),
pdev
->
vsnapshot
);
if
(
ret
>=
0
)
pdev
->
vcompression
=
ARGR
(
qual
);
break
;
}
case
VIDIOCPWCGCQUAL
:
{
ARG_DEF
(
int
,
qual
)
ARGR
(
qual
)
=
pdev
->
vcompression
;
ARG_OUT
(
qual
)
break
;
}
case
VIDIOCPWCPROBE
:
{
ARG_DEF
(
struct
pwc_probe
,
probe
)
strcpy
(
ARGR
(
probe
).
name
,
pdev
->
vdev
->
name
);
ARGR
(
probe
).
type
=
pdev
->
type
;
ARG_OUT
(
probe
)
break
;
}
case
VIDIOCPWCGSERIAL
:
{
ARG_DEF
(
struct
pwc_serial
,
serial
)
strcpy
(
ARGR
(
serial
).
serial
,
pdev
->
serial
);
ARG_OUT
(
serial
)
break
;
}
case
VIDIOCPWCSAGC
:
{
ARG_DEF
(
int
,
agc
)
ARG_IN
(
agc
)
if
(
pwc_set_agc
(
pdev
,
ARGR
(
agc
)
<
0
?
1
:
0
,
ARGR
(
agc
)))
ret
=
-
EINVAL
;
break
;
}
case
VIDIOCPWCGAGC
:
{
ARG_DEF
(
int
,
agc
)
if
(
pwc_get_agc
(
pdev
,
ARGA
(
agc
)))
ret
=
-
EINVAL
;
ARG_OUT
(
agc
)
break
;
}
case
VIDIOCPWCSSHUTTER
:
{
ARG_DEF
(
int
,
shutter_speed
)
ARG_IN
(
shutter_speed
)
ret
=
pwc_set_shutter_speed
(
pdev
,
ARGR
(
shutter_speed
)
<
0
?
1
:
0
,
ARGR
(
shutter_speed
));
break
;
}
case
VIDIOCPWCSAWB
:
{
ARG_DEF
(
struct
pwc_whitebalance
,
wb
)
ARG_IN
(
wb
)
ret
=
pwc_set_awb
(
pdev
,
ARGR
(
wb
).
mode
);
if
(
ret
>=
0
&&
ARGR
(
wb
).
mode
==
PWC_WB_MANUAL
)
{
pwc_set_red_gain
(
pdev
,
ARGR
(
wb
).
manual_red
);
pwc_set_blue_gain
(
pdev
,
ARGR
(
wb
).
manual_blue
);
}
break
;
}
case
VIDIOCPWCGAWB
:
{
ARG_DEF
(
struct
pwc_whitebalance
,
wb
)
memset
(
ARGA
(
wb
),
0
,
sizeof
(
struct
pwc_whitebalance
));
ARGR
(
wb
).
mode
=
pwc_get_awb
(
pdev
);
if
(
ARGR
(
wb
).
mode
<
0
)
ret
=
-
EINVAL
;
else
{
if
(
ARGR
(
wb
).
mode
==
PWC_WB_MANUAL
)
{
ret
=
pwc_get_red_gain
(
pdev
,
&
ARGR
(
wb
).
manual_red
);
if
(
ret
<
0
)
break
;
ret
=
pwc_get_blue_gain
(
pdev
,
&
ARGR
(
wb
).
manual_blue
);
if
(
ret
<
0
)
break
;
}
if
(
ARGR
(
wb
).
mode
==
PWC_WB_AUTO
)
{
ret
=
pwc_read_red_gain
(
pdev
,
&
ARGR
(
wb
).
read_red
);
if
(
ret
<
0
)
break
;
ret
=
pwc_read_blue_gain
(
pdev
,
&
ARGR
(
wb
).
read_blue
);
if
(
ret
<
0
)
break
;
}
}
ARG_OUT
(
wb
)
break
;
}
case
VIDIOCPWCSAWBSPEED
:
{
ARG_DEF
(
struct
pwc_wb_speed
,
wbs
)
if
(
ARGR
(
wbs
).
control_speed
>
0
)
{
ret
=
pwc_set_wb_speed
(
pdev
,
ARGR
(
wbs
).
control_speed
);
}
if
(
ARGR
(
wbs
).
control_delay
>
0
)
{
ret
=
pwc_set_wb_delay
(
pdev
,
ARGR
(
wbs
).
control_delay
);
}
break
;
}
case
VIDIOCPWCGAWBSPEED
:
{
ARG_DEF
(
struct
pwc_wb_speed
,
wbs
)
ret
=
pwc_get_wb_speed
(
pdev
,
&
ARGR
(
wbs
).
control_speed
);
if
(
ret
<
0
)
break
;
ret
=
pwc_get_wb_delay
(
pdev
,
&
ARGR
(
wbs
).
control_delay
);
if
(
ret
<
0
)
break
;
ARG_OUT
(
wbs
)
break
;
}
case
VIDIOCPWCSLED
:
{
ARG_DEF
(
struct
pwc_leds
,
leds
)
ARG_IN
(
leds
)
ret
=
pwc_set_leds
(
pdev
,
ARGR
(
leds
).
led_on
,
ARGR
(
leds
).
led_off
);
break
;
}
case
VIDIOCPWCGLED
:
{
ARG_DEF
(
struct
pwc_leds
,
leds
)
ret
=
pwc_get_leds
(
pdev
,
&
ARGR
(
leds
).
led_on
,
&
ARGR
(
leds
).
led_off
);
ARG_OUT
(
leds
)
break
;
}
case
VIDIOCPWCSCONTOUR
:
{
ARG_DEF
(
int
,
contour
)
ARG_IN
(
contour
)
ret
=
pwc_set_contour
(
pdev
,
ARGR
(
contour
));
break
;
}
case
VIDIOCPWCGCONTOUR
:
{
ARG_DEF
(
int
,
contour
)
ret
=
pwc_get_contour
(
pdev
,
ARGA
(
contour
));
ARG_OUT
(
contour
)
break
;
}
case
VIDIOCPWCSBACKLIGHT
:
{
ARG_DEF
(
int
,
backlight
)
ARG_IN
(
backlight
)
ret
=
pwc_set_backlight
(
pdev
,
ARGR
(
backlight
));
break
;
}
case
VIDIOCPWCGBACKLIGHT
:
{
ARG_DEF
(
int
,
backlight
)
ret
=
pwc_get_backlight
(
pdev
,
ARGA
(
backlight
));
ARG_OUT
(
backlight
)
break
;
}
case
VIDIOCPWCSFLICKER
:
{
ARG_DEF
(
int
,
flicker
)
ARG_IN
(
flicker
)
ret
=
pwc_set_flicker
(
pdev
,
ARGR
(
flicker
));
break
;
}
case
VIDIOCPWCGFLICKER
:
{
ARG_DEF
(
int
,
flicker
)
ret
=
pwc_get_flicker
(
pdev
,
ARGA
(
flicker
));
ARG_OUT
(
flicker
)
break
;
}
case
VIDIOCPWCSDYNNOISE
:
{
ARG_DEF
(
int
,
dynnoise
)
ARG_IN
(
dynnoise
)
ret
=
pwc_set_dynamic_noise
(
pdev
,
ARGR
(
dynnoise
));
break
;
}
case
VIDIOCPWCGDYNNOISE
:
{
ARG_DEF
(
int
,
dynnoise
)
ret
=
pwc_get_dynamic_noise
(
pdev
,
ARGA
(
dynnoise
));
ARG_OUT
(
dynnoise
);
break
;
}
case
VIDIOCPWCGREALSIZE
:
{
ARG_DEF
(
struct
pwc_imagesize
,
size
)
ARGR
(
size
).
width
=
pdev
->
image
.
x
;
ARGR
(
size
).
height
=
pdev
->
image
.
y
;
ARG_OUT
(
size
)
break
;
}
case
VIDIOCPWCMPTRESET
:
{
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
ARG_DEF
(
int
,
flags
)
ARG_IN
(
flags
)
ret
=
pwc_mpt_reset
(
pdev
,
ARGR
(
flags
));
if
(
ret
>=
0
)
{
pdev
->
pan_angle
=
0
;
pdev
->
tilt_angle
=
0
;
}
}
else
{
ret
=
-
ENXIO
;
}
break
;
}
case
VIDIOCPWCMPTGRANGE
:
{
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
ARG_DEF
(
struct
pwc_mpt_range
,
range
)
ARGR
(
range
)
=
pdev
->
angle_range
;
ARG_OUT
(
range
)
}
else
{
ret
=
-
ENXIO
;
}
break
;
}
case
VIDIOCPWCMPTSANGLE
:
{
int
new_pan
,
new_tilt
;
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
ARG_DEF
(
struct
pwc_mpt_angles
,
angles
)
ARG_IN
(
angles
)
/* The camera can only set relative angles, so
do some calculations when getting an absolute angle .
*/
if
(
ARGR
(
angles
).
absolute
)
{
new_pan
=
ARGR
(
angles
).
pan
;
new_tilt
=
ARGR
(
angles
).
tilt
;
}
else
{
new_pan
=
pdev
->
pan_angle
+
ARGR
(
angles
).
pan
;
new_tilt
=
pdev
->
tilt_angle
+
ARGR
(
angles
).
tilt
;
}
/* check absolute ranges */
if
(
new_pan
<
pdev
->
angle_range
.
pan_min
||
new_pan
>
pdev
->
angle_range
.
pan_max
||
new_tilt
<
pdev
->
angle_range
.
tilt_min
||
new_tilt
>
pdev
->
angle_range
.
tilt_max
)
{
ret
=
-
ERANGE
;
}
else
{
/* go to relative range, check again */
new_pan
-=
pdev
->
pan_angle
;
new_tilt
-=
pdev
->
tilt_angle
;
/* angles are specified in degrees * 100, thus the limit = 36000 */
if
(
new_pan
<
-
36000
||
new_pan
>
36000
||
new_tilt
<
-
36000
||
new_tilt
>
36000
)
ret
=
-
ERANGE
;
}
if
(
ret
==
0
)
/* no errors so far */
{
ret
=
pwc_mpt_set_angle
(
pdev
,
new_pan
,
new_tilt
);
if
(
ret
>=
0
)
{
pdev
->
pan_angle
+=
new_pan
;
pdev
->
tilt_angle
+=
new_tilt
;
}
if
(
ret
==
-
EPIPE
)
/* stall -> out of range */
ret
=
-
ERANGE
;
}
}
else
{
ret
=
-
ENXIO
;
}
break
;
}
case
VIDIOCPWCMPTGANGLE
:
{
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
ARG_DEF
(
struct
pwc_mpt_angles
,
angles
)
ARGR
(
angles
).
absolute
=
1
;
ARGR
(
angles
).
pan
=
pdev
->
pan_angle
;
ARGR
(
angles
).
tilt
=
pdev
->
tilt_angle
;
ARG_OUT
(
angles
)
}
else
{
ret
=
-
ENXIO
;
}
break
;
}
case
VIDIOCPWCMPTSTATUS
:
{
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
ARG_DEF
(
struct
pwc_mpt_status
,
status
)
ret
=
pwc_mpt_get_status
(
pdev
,
ARGA
(
status
));
ARG_OUT
(
status
)
}
else
{
ret
=
-
ENXIO
;
}
break
;
}
case
VIDIOCPWCGVIDCMD
:
{
ARG_DEF
(
struct
pwc_video_command
,
cmd
);
ARGR
(
cmd
).
type
=
pdev
->
type
;
ARGR
(
cmd
).
release
=
pdev
->
release
;
ARGR
(
cmd
).
command_len
=
pdev
->
cmd_len
;
memcpy
(
&
ARGR
(
cmd
).
command_buf
,
pdev
->
cmd_buf
,
pdev
->
cmd_len
);
ARGR
(
cmd
).
bandlength
=
pdev
->
vbandlength
;
ARGR
(
cmd
).
frame_size
=
pdev
->
frame_size
;
ARG_OUT
(
cmd
)
break
;
}
/*
case VIDIOCPWCGVIDTABLE:
{
ARG_DEF(struct pwc_table_init_buffer, table);
ARGR(table).len = pdev->cmd_len;
memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
ARG_OUT(table)
break;
}
*/
default:
ret
=
-
ENOIOCTLCMD
;
break
;
}
if
(
ret
>
0
)
return
0
;
return
ret
;
}
drivers/usb/media/pwc/pwc-dec1.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
Decompression for chipset version 1
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pwc-dec1.h"
void
pwc_dec1_init
(
int
type
,
int
release
,
void
*
buffer
,
void
*
table
)
{
}
void
pwc_dec1_exit
(
void
)
{
}
drivers/usb/media/pwc/pwc-dec1.h
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PWC_DEC1_H
#define PWC_DEC1_H
void
pwc_dec1_init
(
int
type
,
int
release
,
void
*
buffer
,
void
*
private_data
);
void
pwc_dec1_exit
(
void
);
#endif
drivers/usb/media/pwc/pwc-dec23.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
Decompression for chipset version 2 et 3
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "pwc-timon.h"
#include "pwc-kiara.h"
#include "pwc-dec23.h"
#include "pwc-ioctl.h"
#include <linux/string.h>
/****
*
*
*
*/
static
void
fill_table_a000
(
unsigned
int
*
p
)
{
static
unsigned
int
initial_values
[
12
]
=
{
0xFFAD9B00
,
0xFFDDEE00
,
0x00221200
,
0x00526500
,
0xFFC21E00
,
0x003DE200
,
0xFF924B80
,
0xFFD2A300
,
0x002D5D00
,
0x006DB480
,
0xFFED3E00
,
0x0012C200
};
static
unsigned
int
values_derivated
[
12
]
=
{
0x0000A4CA
,
0x00004424
,
0xFFFFBBDC
,
0xFFFF5B36
,
0x00007BC4
,
0xFFFF843C
,
0x0000DB69
,
0x00005ABA
,
0xFFFFA546
,
0xFFFF2497
,
0x00002584
,
0xFFFFDA7C
};
unsigned
int
temp_values
[
12
];
int
i
,
j
;
memcpy
(
temp_values
,
initial_values
,
sizeof
(
initial_values
));
for
(
i
=
0
;
i
<
256
;
i
++
)
{
for
(
j
=
0
;
j
<
12
;
j
++
)
{
*
p
++
=
temp_values
[
j
];
temp_values
[
j
]
+=
values_derivated
[
j
];
}
}
}
static
void
fill_table_d000
(
unsigned
char
*
p
)
{
int
bit
,
byte
;
for
(
bit
=
0
;
bit
<
8
;
bit
++
)
{
unsigned
char
bitpower
=
1
<<
bit
;
unsigned
char
mask
=
bitpower
-
1
;
for
(
byte
=
0
;
byte
<
256
;
byte
++
)
{
if
(
byte
&
bitpower
)
*
p
++
=
-
(
byte
&
mask
);
else
*
p
++
=
(
byte
&
mask
);
}
}
}
/*
*
* Kiara: 0 <= ver <= 7
* Timon: 0 <= ver <= 15
*
*/
void
fill_table_color
(
unsigned
int
version
,
const
unsigned
int
*
romtable
,
unsigned
char
*
p0004
,
unsigned
char
*
p8004
)
{
const
unsigned
int
*
table
;
unsigned
char
*
p0
,
*
p8
;
int
i
,
j
,
k
;
int
dl
,
bit
,
pw
;
romtable
+=
version
*
256
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
table
=
romtable
+
i
*
128
;
for
(
dl
=
0
;
dl
<
16
;
dl
++
)
{
p0
=
p0004
+
(
i
<<
14
)
+
(
dl
<<
10
);
p8
=
p8004
+
(
i
<<
12
)
+
(
dl
<<
8
);
for
(
j
=
0
;
j
<
8
;
j
++
,
table
++
,
p0
+=
128
)
{
for
(
k
=
0
;
k
<
16
;
k
++
)
{
if
(
k
==
0
)
bit
=
1
;
else
if
(
k
>=
1
&&
k
<
3
)
bit
=
(
table
[
0
]
>>
15
)
&
7
;
else
if
(
k
>=
3
&&
k
<
6
)
bit
=
(
table
[
0
]
>>
12
)
&
7
;
else
if
(
k
>=
6
&&
k
<
10
)
bit
=
(
table
[
0
]
>>
9
)
&
7
;
else
if
(
k
>=
10
&&
k
<
13
)
bit
=
(
table
[
0
]
>>
6
)
&
7
;
else
if
(
k
>=
13
&&
k
<
15
)
bit
=
(
table
[
0
]
>>
3
)
&
7
;
else
bit
=
(
table
[
0
])
&
7
;
if
(
k
==
0
)
*
(
unsigned
char
*
)
p8
++
=
8
;
else
*
(
unsigned
char
*
)
p8
++
=
j
-
bit
;
*
(
unsigned
char
*
)
p8
++
=
bit
;
pw
=
1
<<
bit
;
p0
[
k
+
0x00
]
=
(
1
*
pw
)
+
0x80
;
p0
[
k
+
0x10
]
=
(
2
*
pw
)
+
0x80
;
p0
[
k
+
0x20
]
=
(
3
*
pw
)
+
0x80
;
p0
[
k
+
0x30
]
=
(
4
*
pw
)
+
0x80
;
p0
[
k
+
0x40
]
=
(
-
pw
)
+
0x80
;
p0
[
k
+
0x50
]
=
(
2
*-
pw
)
+
0x80
;
p0
[
k
+
0x60
]
=
(
3
*-
pw
)
+
0x80
;
p0
[
k
+
0x70
]
=
(
4
*-
pw
)
+
0x80
;
}
/* end of for (k=0; k<16; k++, p8++) */
}
/* end of for (j=0; j<8; j++ , table++) */
}
/* end of for (dl=0; dl<16; dl++) */
}
/* end of for (i=0; i<2; i++) */
}
/*
* precision = (pdev->xx + pdev->yy)
*
*/
void
fill_table_dc00_d800
(
unsigned
int
precision
,
unsigned
int
*
pdc00
,
unsigned
int
*
pd800
)
{
int
i
;
unsigned
int
offset1
,
offset2
;
for
(
i
=
0
,
offset1
=
0x4000
,
offset2
=
0
;
i
<
256
;
i
++
,
offset1
+=
0x7BC4
,
offset2
+=
0x7BC4
)
{
unsigned
int
msb
=
offset1
>>
15
;
if
(
msb
>
255
)
{
if
(
msb
)
msb
=
0
;
else
msb
=
255
;
}
*
pdc00
++
=
msb
<<
precision
;
*
pd800
++
=
offset2
;
}
}
/*
* struct {
* unsigned char op; // operation to execute
* unsigned char bits; // bits use to perform operation
* unsigned char offset1; // offset to add to access in the table_0004 % 16
* unsigned char offset2; // offset to add to access in the table_0004
* }
*
*/
static
unsigned
int
table_ops
[]
=
{
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x10
,
0x00
,
0x06
,
0x01
,
0x30
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x01
,
0x20
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x50
,
0x00
,
0x05
,
0x02
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x03
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x10
,
0x00
,
0x06
,
0x02
,
0x10
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x01
,
0x60
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x50
,
0x00
,
0x05
,
0x02
,
0x40
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x03
,
0x40
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x10
,
0x00
,
0x06
,
0x01
,
0x70
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x01
,
0x20
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x50
,
0x00
,
0x05
,
0x02
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x03
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x10
,
0x00
,
0x06
,
0x02
,
0x50
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x01
,
0x60
,
0x01
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x00
,
0x00
,
0x04
,
0x01
,
0x50
,
0x00
,
0x05
,
0x02
,
0x40
,
0x02
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x01
,
0x40
,
0x00
,
0x05
,
0x03
,
0x40
,
0x01
,
0x00
,
0x00
,
0x00
};
/*
* TODO: multiply by 4 all values
*
*/
static
unsigned
int
MulIdx
[
256
]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
2
,
3
,
0
,
1
,
2
,
3
,
0
,
1
,
2
,
3
,
0
,
1
,
2
,
3
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
1
,
2
,
2
,
2
,
2
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
5
,
4
,
4
,
4
,
4
,
6
,
7
,
8
,
9
,
7
,
10
,
11
,
8
,
8
,
11
,
10
,
7
,
9
,
8
,
7
,
6
,
4
,
5
,
5
,
4
,
4
,
5
,
5
,
4
,
4
,
5
,
5
,
4
,
4
,
5
,
5
,
4
,
1
,
3
,
0
,
2
,
1
,
3
,
0
,
2
,
1
,
3
,
0
,
2
,
1
,
3
,
0
,
2
,
0
,
3
,
3
,
0
,
1
,
2
,
2
,
1
,
2
,
1
,
1
,
2
,
3
,
0
,
0
,
3
,
0
,
1
,
2
,
3
,
3
,
2
,
1
,
0
,
3
,
2
,
1
,
0
,
0
,
1
,
2
,
3
,
1
,
1
,
1
,
1
,
3
,
3
,
3
,
3
,
0
,
0
,
0
,
0
,
2
,
2
,
2
,
2
,
7
,
10
,
11
,
8
,
9
,
8
,
7
,
6
,
6
,
7
,
8
,
9
,
8
,
11
,
10
,
7
,
4
,
5
,
5
,
4
,
5
,
4
,
4
,
5
,
5
,
4
,
4
,
5
,
4
,
5
,
5
,
4
,
7
,
9
,
6
,
8
,
10
,
8
,
7
,
11
,
11
,
7
,
8
,
10
,
8
,
6
,
9
,
7
,
1
,
3
,
0
,
2
,
2
,
0
,
3
,
1
,
2
,
0
,
3
,
1
,
1
,
3
,
0
,
2
,
1
,
2
,
2
,
1
,
3
,
0
,
0
,
3
,
0
,
3
,
3
,
0
,
2
,
1
,
1
,
2
,
10
,
8
,
7
,
11
,
8
,
6
,
9
,
7
,
7
,
9
,
6
,
8
,
11
,
7
,
8
,
10
};
void
pwc_dec23_init
(
int
type
,
int
release
,
unsigned
char
*
mode
,
void
*
data
)
{
int
flags
;
struct
pwc_dec23_private
*
pdev
=
data
;
release
=
release
;
switch
(
type
)
{
case
720
:
case
730
:
case
740
:
case
750
:
flags
=
mode
[
2
]
&
0x18
;
/* our: flags = 8, mode[2]==e8 */
if
(
flags
==
8
)
pdev
->
zz
=
7
;
else
if
(
flags
==
0x10
)
pdev
->
zz
=
8
;
else
pdev
->
zz
=
6
;
flags
=
mode
[
2
]
>>
5
;
/* our: 7 */
fill_table_color
(
flags
,
(
unsigned
int
*
)
KiaraRomTable
,
pdev
->
table_0004
,
pdev
->
table_8004
);
break
;
case
675
:
case
680
:
case
690
:
flags
=
mode
[
2
]
&
6
;
if
(
flags
==
2
)
pdev
->
zz
=
7
;
else
if
(
flags
==
4
)
pdev
->
zz
=
8
;
else
pdev
->
zz
=
6
;
flags
=
mode
[
2
]
>>
3
;
fill_table_color
(
flags
,
(
unsigned
int
*
)
TimonRomTable
,
pdev
->
table_0004
,
pdev
->
table_8004
);
break
;
default:
/* Not supported */
return
;
}
/* * * * ** */
pdev
->
xx
=
8
-
pdev
->
zz
;
pdev
->
yy
=
15
-
pdev
->
xx
;
pdev
->
zzmask
=
0xFF
>>
pdev
->
xx
;
//pdev->zzmask = (1U<<pdev->zz)-1;
fill_table_dc00_d800
(
pdev
->
xx
+
pdev
->
yy
,
pdev
->
table_dc00
,
pdev
->
table_d800
);
fill_table_a000
(
pdev
->
table_a004
);
fill_table_d000
(
pdev
->
table_d004
);
}
/*
* To manage the stream, we keep in a 32 bits variables,
* the next bits in the stream. fill_reservoir() add to
* the reservoir at least wanted nbits.
*
*
*/
#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
while (nbits_in_reservoir<nbits_wanted) \
{ \
reservoir |= (*(stream)++) << nbits_in_reservoir; \
nbits_in_reservoir+=8; \
} \
} while(0);
#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \
result = (reservoir) & ((1U<<nbits_wanted)-1); \
reservoir >>= nbits_wanted; \
nbits_in_reservoir -= nbits_wanted; \
} while(0);
static
void
DecompressBand23
(
const
struct
pwc_dec23_private
*
pdev
,
const
unsigned
char
*
rawyuv
,
unsigned
char
*
planar_y
,
unsigned
char
*
planar_u
,
unsigned
char
*
planar_v
,
unsigned
int
image_x
,
/* aka number of pixels wanted ??? */
unsigned
int
pixels_per_line
,
/* aka number of pixels per line */
int
flags
)
{
unsigned
int
reservoir
,
nbits_in_reservoir
;
int
first_4_bits
;
unsigned
int
bytes_per_channel
;
int
line_size
;
/* size of the line (4Y+U+V) */
int
passes
;
const
unsigned
char
*
ptable0004
,
*
ptable8004
;
int
even_line
;
unsigned
int
temp_colors
[
16
];
int
nblocks
;
const
unsigned
char
*
stream
;
unsigned
char
*
dest_y
,
*
dest_u
=
NULL
,
*
dest_v
=
NULL
;
unsigned
int
offset_to_plane_u
,
offset_to_plane_v
;
int
i
;
reservoir
=
0
;
nbits_in_reservoir
=
0
;
stream
=
rawyuv
+
1
;
/* The first byte of the stream is skipped */
even_line
=
1
;
get_nbits
(
reservoir
,
nbits_in_reservoir
,
stream
,
4
,
first_4_bits
);
line_size
=
pixels_per_line
*
3
;
for
(
passes
=
0
;
passes
<
2
;
passes
++
)
{
if
(
passes
==
0
)
{
bytes_per_channel
=
pixels_per_line
;
dest_y
=
planar_y
;
nblocks
=
image_x
/
4
;
}
else
{
/* Format planar: All Y, then all U, then all V */
bytes_per_channel
=
pixels_per_line
/
2
;
dest_u
=
planar_u
;
dest_v
=
planar_v
;
dest_y
=
dest_u
;
nblocks
=
image_x
/
8
;
}
offset_to_plane_u
=
bytes_per_channel
*
2
;
offset_to_plane_v
=
bytes_per_channel
*
3
;
/*
printf("bytes_per_channel = %d\n",bytes_per_channel);
printf("offset_to_plane_u = %d\n",offset_to_plane_u);
printf("offset_to_plane_v = %d\n",offset_to_plane_v);
*/
while
(
nblocks
-->
0
)
{
unsigned
int
gray_index
;
fill_nbits
(
reservoir
,
nbits_in_reservoir
,
stream
,
16
);
gray_index
=
reservoir
&
pdev
->
zzmask
;
reservoir
>>=
pdev
->
zz
;
nbits_in_reservoir
-=
pdev
->
zz
;
fill_nbits
(
reservoir
,
nbits_in_reservoir
,
stream
,
2
);
if
(
(
reservoir
&
3
)
==
0
)
{
reservoir
>>=
2
;
nbits_in_reservoir
-=
2
;
for
(
i
=
0
;
i
<
16
;
i
++
)
temp_colors
[
i
]
=
pdev
->
table_dc00
[
gray_index
];
}
else
{
unsigned
int
channel_v
,
offset1
;
/* swap bit 0 and 2 of offset_OR */
channel_v
=
((
reservoir
&
1
)
<<
2
)
|
(
reservoir
&
2
)
|
((
reservoir
&
4
)
>>
2
);
reservoir
>>=
3
;
nbits_in_reservoir
-=
3
;
for
(
i
=
0
;
i
<
16
;
i
++
)
temp_colors
[
i
]
=
pdev
->
table_d800
[
gray_index
];
ptable0004
=
pdev
->
table_0004
+
(
passes
*
16384
)
+
(
first_4_bits
*
1024
)
+
(
channel_v
*
128
);
ptable8004
=
pdev
->
table_8004
+
(
passes
*
4096
)
+
(
first_4_bits
*
256
)
+
(
channel_v
*
32
);
offset1
=
0
;
while
(
1
)
{
unsigned
int
index_in_table_ops
,
op
,
rows
=
0
;
fill_nbits
(
reservoir
,
nbits_in_reservoir
,
stream
,
16
);
/* mode is 0,1 or 2 */
index_in_table_ops
=
(
reservoir
&
0x3F
);
op
=
table_ops
[
index_in_table_ops
*
4
];
if
(
op
==
2
)
{
reservoir
>>=
2
;
nbits_in_reservoir
-=
2
;
break
;
/* exit the while(1) */
}
if
(
op
==
0
)
{
unsigned
int
shift
;
offset1
=
(
offset1
+
table_ops
[
index_in_table_ops
*
4
+
2
])
&
0x0F
;
shift
=
table_ops
[
index_in_table_ops
*
4
+
1
];
reservoir
>>=
shift
;
nbits_in_reservoir
-=
shift
;
rows
=
ptable0004
[
offset1
+
table_ops
[
index_in_table_ops
*
4
+
3
]
];
}
if
(
op
==
1
)
{
/* 10bits [ xxxx xxxx yyyy 000 ]
* yyy => offset in the table8004
* xxx => offset in the tabled004
*/
unsigned
int
mask
,
shift
;
unsigned
int
col1
,
row1
,
total_bits
;
offset1
=
(
offset1
+
((
reservoir
>>
3
)
&
0x0F
)
+
1
)
&
0x0F
;
col1
=
(
reservoir
>>
7
)
&
0xFF
;
row1
=
ptable8004
[
offset1
*
2
];
/* Bit mask table */
mask
=
pdev
->
table_d004
[
(
row1
<<
8
)
+
col1
];
shift
=
ptable8004
[
offset1
*
2
+
1
];
rows
=
((
mask
<<
shift
)
+
0x80
)
&
0xFF
;
total_bits
=
row1
+
8
;
reservoir
>>=
total_bits
;
nbits_in_reservoir
-=
total_bits
;
}
{
const
unsigned
int
*
table_a004
=
pdev
->
table_a004
+
rows
*
12
;
unsigned
int
*
poffset
=
MulIdx
+
offset1
*
16
;
/* 64/4 (int) */
for
(
i
=
0
;
i
<
16
;
i
++
)
{
temp_colors
[
i
]
+=
table_a004
[
*
poffset
];
poffset
++
;
}
}
}
}
#define USE_SIGNED_INT_FOR_COLOR
#ifdef USE_SIGNED_INT_FOR_COLOR
# define CLAMP(x) ((x)>255?255:((x)<0?0:x))
#else
# define CLAMP(x) ((x)>255?255:x)
#endif
if
(
passes
==
0
)
{
#ifdef USE_SIGNED_INT_FOR_COLOR
const
int
*
c
=
temp_colors
;
#else
const
unsigned
int
*
c
=
temp_colors
;
#endif
unsigned
char
*
d
;
d
=
dest_y
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c
++
)
*
d
++
=
CLAMP
((
*
c
)
>>
pdev
->
yy
);
d
=
dest_y
+
bytes_per_channel
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c
++
)
*
d
++
=
CLAMP
((
*
c
)
>>
pdev
->
yy
);
d
=
dest_y
+
offset_to_plane_u
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c
++
)
*
d
++
=
CLAMP
((
*
c
)
>>
pdev
->
yy
);
d
=
dest_y
+
offset_to_plane_v
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c
++
)
*
d
++
=
CLAMP
((
*
c
)
>>
pdev
->
yy
);
dest_y
+=
4
;
}
else
if
(
passes
==
1
)
{
#ifdef USE_SIGNED_INT_FOR_COLOR
int
*
c1
=
temp_colors
;
int
*
c2
=
temp_colors
+
4
;
#else
unsigned
int
*
c1
=
temp_colors
;
unsigned
int
*
c2
=
temp_colors
+
4
;
#endif
unsigned
char
*
d
;
d
=
dest_y
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c1
++
,
c2
++
)
{
*
d
++
=
CLAMP
((
*
c1
)
>>
pdev
->
yy
);
*
d
++
=
CLAMP
((
*
c2
)
>>
pdev
->
yy
);
}
c1
=
temp_colors
+
12
;
//c2 = temp_colors+8;
d
=
dest_y
+
bytes_per_channel
;
for
(
i
=
0
;
i
<
4
;
i
++
,
c1
++
,
c2
++
)
{
*
d
++
=
CLAMP
((
*
c1
)
>>
pdev
->
yy
);
*
d
++
=
CLAMP
((
*
c2
)
>>
pdev
->
yy
);
}
if
(
even_line
)
/* Each line, swap u/v */
{
even_line
=
0
;
dest_y
=
dest_v
;
dest_u
+=
8
;
}
else
{
even_line
=
1
;
dest_y
=
dest_u
;
dest_v
+=
8
;
}
}
}
/* end of while (nblocks-->0) */
}
/* end of for (passes=0;passes<2;passes++) */
}
/**
*
* image: size of the image wanted
* view : size of the image returned by the camera
* offset: (x,y) to displayer image in the view
*
* src: raw data
* dst: image output
* flags: PWCX_FLAG_PLANAR
* pdev: private buffer
* bandlength:
*
*/
void
pwc_dec23_decompress
(
const
struct
pwc_coord
*
image
,
const
struct
pwc_coord
*
view
,
const
struct
pwc_coord
*
offset
,
const
void
*
src
,
void
*
dst
,
int
flags
,
const
void
*
data
,
int
bandlength
)
{
const
struct
pwc_dec23_private
*
pdev
=
data
;
unsigned
char
*
pout
,
*
pout_planar_y
=
NULL
,
*
pout_planar_u
=
NULL
,
*
pout_planar_v
=
NULL
;
int
i
,
n
,
stride
,
pixel_size
;
if
(
flags
&
PWCX_FLAG_BAYER
)
{
pout
=
dst
+
(
view
->
x
*
offset
->
y
)
+
offset
->
x
;
pixel_size
=
view
->
x
*
4
;
}
else
{
n
=
view
->
x
*
view
->
y
;
/* offset in Y plane */
stride
=
view
->
x
*
offset
->
y
;
pout_planar_y
=
dst
+
stride
+
offset
->
x
;
/* offsets in U/V planes */
stride
=
(
view
->
x
*
offset
->
y
)
/
4
+
offset
->
x
/
2
;
pout_planar_u
=
dst
+
n
+
+
stride
;
pout_planar_v
=
dst
+
n
+
n
/
4
+
stride
;
pixel_size
=
view
->
x
*
4
;
}
for
(
i
=
0
;
i
<
image
->
y
;
i
+=
4
)
{
if
(
flags
&
PWCX_FLAG_BAYER
)
{
//TODO:
//DecompressBandBayer(pdev,src,pout,image.x,view->x,flags);
src
+=
bandlength
;
pout
+=
pixel_size
;
}
else
{
DecompressBand23
(
pdev
,
src
,
pout_planar_y
,
pout_planar_u
,
pout_planar_v
,
image
->
x
,
view
->
x
,
flags
);
src
+=
bandlength
;
pout_planar_y
+=
pixel_size
;
pout_planar_u
+=
view
->
x
;
pout_planar_v
+=
view
->
x
;
}
}
}
void
pwc_dec23_exit
(
void
)
{
/* Do nothing */
}
drivers/usb/media/pwc/pwc-dec23.h
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PWC_DEC23_H
#define PWC_DEC23_H
struct
pwc_dec23_private
{
unsigned
char
xx
,
yy
,
zz
,
zzmask
;
unsigned
char
table_0004
[
2
*
0x4000
];
unsigned
char
table_8004
[
2
*
0x1000
];
unsigned
int
table_a004
[
256
*
12
];
unsigned
char
table_d004
[
8
*
256
];
unsigned
int
table_d800
[
256
];
unsigned
int
table_dc00
[
256
];
};
void
pwc_dec23_init
(
int
type
,
int
release
,
unsigned
char
*
buffer
,
void
*
private_data
);
void
pwc_dec23_exit
(
void
);
void
pwc_dec23_decompress
(
const
struct
pwc_coord
*
image
,
const
struct
pwc_coord
*
view
,
const
struct
pwc_coord
*
offset
,
const
void
*
src
,
void
*
dst
,
int
flags
,
const
void
*
data
,
int
bandlength
);
#endif
drivers/usb/media/pwc/pwc-if.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
USB and Video4Linux interface part.
(C) 1999-2004 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
This code forms the interface between the USB layers and the Philips
specific stuff. Some adanved stuff of the driver falls under an
NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
is thus not distributed in source form. The binary pwcx.o module
contains the code that falls under the NDA.
In case you're wondering: 'pwc' stands for "Philips WebCam", but
I really didn't want to type 'philips_web_cam' every time (I'm lazy as
any Linux kernel hacker, but I don't like uncomprehensible abbreviations
without explanation).
Oh yes, convention: to disctinguish between all the various pointers to
device-structures, I use these names for the pointer variables:
udev: struct usb_device *
vdev: struct video_device *
pdev: struct pwc_devive *
*/
/* Contributors:
- Alvarado: adding whitebalance code
- Alistar Moire: QuickCam 3000 Pro device/product ID
- Tony Hoyle: Creative Labs Webcam 5 device/product ID
- Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
- Jk Fang: Sotec Afina Eye ID
- Xavier Roche: QuickCam Pro 4000 ID
- Jens Knudsen: QuickCam Zoom ID
- J. Debert: QuickCam for Notebooks ID
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include "pwc.h"
#include "pwc-ioctl.h"
#include "pwc-kiara.h"
#include "pwc-timon.h"
#include "pwc-dec23.h"
#include "pwc-dec1.h"
#include "pwc-uncompress.h"
/* Function prototypes and driver templates */
/* hotplug device table support */
static
struct
usb_device_id
pwc_device_table
[]
=
{
{
USB_DEVICE
(
0x0471
,
0x0302
)
},
/* Philips models */
{
USB_DEVICE
(
0x0471
,
0x0303
)
},
{
USB_DEVICE
(
0x0471
,
0x0304
)
},
{
USB_DEVICE
(
0x0471
,
0x0307
)
},
{
USB_DEVICE
(
0x0471
,
0x0308
)
},
{
USB_DEVICE
(
0x0471
,
0x030C
)
},
{
USB_DEVICE
(
0x0471
,
0x0310
)
},
{
USB_DEVICE
(
0x0471
,
0x0311
)
},
{
USB_DEVICE
(
0x0471
,
0x0312
)
},
{
USB_DEVICE
(
0x0471
,
0x0313
)
},
/* the 'new' 720K */
{
USB_DEVICE
(
0x069A
,
0x0001
)
},
/* Askey */
{
USB_DEVICE
(
0x046D
,
0x08B0
)
},
/* Logitech QuickCam Pro 3000 */
{
USB_DEVICE
(
0x046D
,
0x08B1
)
},
/* Logitech QuickCam Notebook Pro */
{
USB_DEVICE
(
0x046D
,
0x08B2
)
},
/* Logitech QuickCam Pro 4000 */
{
USB_DEVICE
(
0x046D
,
0x08B3
)
},
/* Logitech QuickCam Zoom (old model) */
{
USB_DEVICE
(
0x046D
,
0x08B4
)
},
/* Logitech QuickCam Zoom (new model) */
{
USB_DEVICE
(
0x046D
,
0x08B5
)
},
/* Logitech QuickCam Orbit/Sphere */
{
USB_DEVICE
(
0x046D
,
0x08B6
)
},
/* Logitech (reserved) */
{
USB_DEVICE
(
0x046D
,
0x08B7
)
},
/* Logitech (reserved) */
{
USB_DEVICE
(
0x046D
,
0x08B8
)
},
/* Logitech (reserved) */
{
USB_DEVICE
(
0x055D
,
0x9000
)
},
/* Samsung */
{
USB_DEVICE
(
0x055D
,
0x9001
)
},
{
USB_DEVICE
(
0x041E
,
0x400C
)
},
/* Creative Webcam 5 */
{
USB_DEVICE
(
0x041E
,
0x4011
)
},
/* Creative Webcam Pro Ex */
{
USB_DEVICE
(
0x04CC
,
0x8116
)
},
/* Afina Eye */
{
USB_DEVICE
(
0x06BE
,
0x8116
)
},
/* new Afina Eye */
{
USB_DEVICE
(
0x0d81
,
0x1910
)
},
/* Visionite */
{
USB_DEVICE
(
0x0d81
,
0x1900
)
},
{
}
};
MODULE_DEVICE_TABLE
(
usb
,
pwc_device_table
);
static
int
usb_pwc_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
void
usb_pwc_disconnect
(
struct
usb_interface
*
intf
);
static
struct
usb_driver
pwc_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"Philips webcam"
,
/* name */
.
id_table
=
pwc_device_table
,
.
probe
=
usb_pwc_probe
,
/* probe() */
.
disconnect
=
usb_pwc_disconnect
,
/* disconnect() */
};
#define MAX_DEV_HINTS 20
#define MAX_ISOC_ERRORS 20
static
int
default_size
=
PSZ_QCIF
;
static
int
default_fps
=
10
;
static
int
default_fbufs
=
3
;
/* Default number of frame buffers */
static
int
default_mbufs
=
2
;
/* Default number of mmap() buffers */
int
pwc_trace
=
TRACE_MODULE
|
TRACE_FLOW
|
TRACE_PWCX
;
static
int
power_save
=
0
;
static
int
led_on
=
100
,
led_off
=
0
;
/* defaults to LED that is on while in use */
int
pwc_preferred_compression
=
2
;
/* 0..3 = uncompressed..high */
static
struct
{
int
type
;
char
serial_number
[
30
];
int
device_node
;
struct
pwc_device
*
pdev
;
}
device_hint
[
MAX_DEV_HINTS
];
/***/
static
int
pwc_video_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
pwc_video_close
(
struct
inode
*
inode
,
struct
file
*
file
);
static
ssize_t
pwc_video_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
);
static
unsigned
int
pwc_video_poll
(
struct
file
*
file
,
poll_table
*
wait
);
static
int
pwc_video_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
ioctlnr
,
unsigned
long
arg
);
static
int
pwc_video_mmap
(
struct
file
*
file
,
struct
vm_area_struct
*
vma
);
static
struct
file_operations
pwc_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
pwc_video_open
,
.
release
=
pwc_video_close
,
.
read
=
pwc_video_read
,
.
poll
=
pwc_video_poll
,
.
mmap
=
pwc_video_mmap
,
.
ioctl
=
pwc_video_ioctl
,
.
llseek
=
no_llseek
,
};
static
struct
video_device
pwc_template
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"Philips Webcam"
,
/* Filled in later */
.
type
=
VID_TYPE_CAPTURE
,
.
hardware
=
VID_HARDWARE_PWC
,
.
release
=
video_device_release
,
.
fops
=
&
pwc_fops
,
.
minor
=
-
1
,
};
/***************************************************************************/
/* Okay, this is some magic that I worked out and the reasoning behind it...
The biggest problem with any USB device is of course: "what to do
when the user unplugs the device while it is in use by an application?"
We have several options:
1) Curse them with the 7 plagues when they do (requires divine intervention)
2) Tell them not to (won't work: they'll do it anyway)
3) Oops the kernel (this will have a negative effect on a user's uptime)
4) Do something sensible.
Of course, we go for option 4.
It happens that this device will be linked to two times, once from
usb_device and once from the video_device in their respective 'private'
pointers. This is done when the device is probed() and all initialization
succeeded. The pwc_device struct links back to both structures.
When a device is unplugged while in use it will be removed from the
list of known USB devices; I also de-register it as a V4L device, but
unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works.
A small 'advantage' is that if a user unplugs the cam and plugs it back
in, it should get assigned the same video device minor, but unfortunately
it's non-trivial to re-link the cam back to the video device... (that
would surely be magic! :))
*/
/***************************************************************************/
/* Private functions */
/* Here we want the physical address of the memory.
* This is used when initializing the contents of the area.
*/
static
inline
unsigned
long
kvirt_to_pa
(
unsigned
long
adr
)
{
unsigned
long
kva
,
ret
;
kva
=
(
unsigned
long
)
page_address
(
vmalloc_to_page
((
void
*
)
adr
));
kva
|=
adr
&
(
PAGE_SIZE
-
1
);
/* restore the offset */
ret
=
__pa
(
kva
);
return
ret
;
}
static
void
*
rvmalloc
(
unsigned
long
size
)
{
void
*
mem
;
unsigned
long
adr
;
size
=
PAGE_ALIGN
(
size
);
mem
=
vmalloc_32
(
size
);
if
(
mem
)
{
memset
(
mem
,
0
,
size
);
/* Clear the ram out, no junk to the user */
adr
=
(
unsigned
long
)
mem
;
while
(
size
>
0
)
{
SetPageReserved
(
vmalloc_to_page
((
void
*
)
adr
));
adr
+=
PAGE_SIZE
;
size
-=
PAGE_SIZE
;
}
}
return
mem
;
}
static
void
rvfree
(
void
*
mem
,
unsigned
long
size
)
{
unsigned
long
adr
;
if
(
mem
)
{
adr
=
(
unsigned
long
)
mem
;
while
((
long
)
size
>
0
)
{
ClearPageReserved
(
vmalloc_to_page
((
void
*
)
adr
));
adr
+=
PAGE_SIZE
;
size
-=
PAGE_SIZE
;
}
vfree
(
mem
);
}
}
static
int
pwc_allocate_buffers
(
struct
pwc_device
*
pdev
)
{
int
i
;
void
*
kbuf
;
Trace
(
TRACE_MEMORY
,
">> pwc_allocate_buffers(pdev = 0x%p)
\n
"
,
pdev
);
if
(
pdev
==
NULL
)
return
-
ENXIO
;
#ifdef PWC_MAGIC
if
(
pdev
->
magic
!=
PWC_MAGIC
)
{
Err
(
"allocate_buffers(): magic failed.
\n
"
);
return
-
ENXIO
;
}
#endif
/* Allocate Isochronuous pipe buffers */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
if
(
pdev
->
sbuf
[
i
].
data
==
NULL
)
{
kbuf
=
kmalloc
(
ISO_BUFFER_SIZE
,
GFP_KERNEL
);
if
(
kbuf
==
NULL
)
{
Err
(
"Failed to allocate iso buffer %d.
\n
"
,
i
);
return
-
ENOMEM
;
}
Trace
(
TRACE_MEMORY
,
"Allocated iso buffer at %p.
\n
"
,
kbuf
);
pdev
->
sbuf
[
i
].
data
=
kbuf
;
memset
(
kbuf
,
0
,
ISO_BUFFER_SIZE
);
}
}
/* Allocate frame buffer structure */
if
(
pdev
->
fbuf
==
NULL
)
{
kbuf
=
kmalloc
(
default_fbufs
*
sizeof
(
struct
pwc_frame_buf
),
GFP_KERNEL
);
if
(
kbuf
==
NULL
)
{
Err
(
"Failed to allocate frame buffer structure.
\n
"
);
return
-
ENOMEM
;
}
Trace
(
TRACE_MEMORY
,
"Allocated frame buffer structure at %p.
\n
"
,
kbuf
);
pdev
->
fbuf
=
kbuf
;
memset
(
kbuf
,
0
,
default_fbufs
*
sizeof
(
struct
pwc_frame_buf
));
}
/* create frame buffers, and make circular ring */
for
(
i
=
0
;
i
<
default_fbufs
;
i
++
)
{
if
(
pdev
->
fbuf
[
i
].
data
==
NULL
)
{
kbuf
=
vmalloc
(
PWC_FRAME_SIZE
);
/* need vmalloc since frame buffer > 128K */
if
(
kbuf
==
NULL
)
{
Err
(
"Failed to allocate frame buffer %d.
\n
"
,
i
);
return
-
ENOMEM
;
}
Trace
(
TRACE_MEMORY
,
"Allocated frame buffer %d at %p.
\n
"
,
i
,
kbuf
);
pdev
->
fbuf
[
i
].
data
=
kbuf
;
memset
(
kbuf
,
128
,
PWC_FRAME_SIZE
);
}
}
/* Allocate decompressor table space */
kbuf
=
NULL
;
switch
(
pdev
->
type
)
{
case
675
:
case
680
:
case
690
:
case
720
:
case
730
:
case
740
:
case
750
:
Trace
(
TRACE_MEMORY
,
"private_data(%d)
\n
"
,
sizeof
(
struct
pwc_dec23_private
));
kbuf
=
kmalloc
(
sizeof
(
struct
pwc_dec23_private
),
GFP_KERNEL
);
/* Timon & Kiara */
break
;
case
645
:
case
646
:
/* TODO & FIXME */
kbuf
=
kmalloc
(
sizeof
(
struct
pwc_dec23_private
),
GFP_KERNEL
);
break
;
}
if
(
kbuf
==
NULL
)
{
Err
(
"Failed to allocate decompress table.
\n
"
);
return
-
ENOMEM
;
}
pdev
->
decompress_data
=
kbuf
;
/* Allocate image buffer; double buffer for mmap() */
kbuf
=
rvmalloc
(
default_mbufs
*
pdev
->
len_per_image
);
if
(
kbuf
==
NULL
)
{
Err
(
"Failed to allocate image buffer(s). needed (%d)
\n
"
,
default_mbufs
*
pdev
->
len_per_image
);
return
-
ENOMEM
;
}
Trace
(
TRACE_MEMORY
,
"Allocated image buffer at %p.
\n
"
,
kbuf
);
pdev
->
image_data
=
kbuf
;
for
(
i
=
0
;
i
<
default_mbufs
;
i
++
)
pdev
->
image_ptr
[
i
]
=
kbuf
+
i
*
pdev
->
len_per_image
;
for
(;
i
<
MAX_IMAGES
;
i
++
)
pdev
->
image_ptr
[
i
]
=
NULL
;
kbuf
=
NULL
;
Trace
(
TRACE_MEMORY
,
"<< pwc_allocate_buffers()
\n
"
);
return
0
;
}
static
void
pwc_free_buffers
(
struct
pwc_device
*
pdev
)
{
int
i
;
Trace
(
TRACE_MEMORY
,
"Entering free_buffers(%p).
\n
"
,
pdev
);
if
(
pdev
==
NULL
)
return
;
#ifdef PWC_MAGIC
if
(
pdev
->
magic
!=
PWC_MAGIC
)
{
Err
(
"free_buffers(): magic failed.
\n
"
);
return
;
}
#endif
/* Release Iso-pipe buffers */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
if
(
pdev
->
sbuf
[
i
].
data
!=
NULL
)
{
Trace
(
TRACE_MEMORY
,
"Freeing ISO buffer at %p.
\n
"
,
pdev
->
sbuf
[
i
].
data
);
kfree
(
pdev
->
sbuf
[
i
].
data
);
pdev
->
sbuf
[
i
].
data
=
NULL
;
}
/* The same for frame buffers */
if
(
pdev
->
fbuf
!=
NULL
)
{
for
(
i
=
0
;
i
<
default_fbufs
;
i
++
)
{
if
(
pdev
->
fbuf
[
i
].
data
!=
NULL
)
{
Trace
(
TRACE_MEMORY
,
"Freeing frame buffer %d at %p.
\n
"
,
i
,
pdev
->
fbuf
[
i
].
data
);
vfree
(
pdev
->
fbuf
[
i
].
data
);
pdev
->
fbuf
[
i
].
data
=
NULL
;
}
}
kfree
(
pdev
->
fbuf
);
pdev
->
fbuf
=
NULL
;
}
/* Intermediate decompression buffer & tables */
if
(
pdev
->
decompress_data
!=
NULL
)
{
Trace
(
TRACE_MEMORY
,
"Freeing decompression buffer at %p.
\n
"
,
pdev
->
decompress_data
);
kfree
(
pdev
->
decompress_data
);
pdev
->
decompress_data
=
NULL
;
}
pdev
->
decompressor
=
NULL
;
/* Release image buffers */
if
(
pdev
->
image_data
!=
NULL
)
{
Trace
(
TRACE_MEMORY
,
"Freeing image buffer at %p.
\n
"
,
pdev
->
image_data
);
rvfree
(
pdev
->
image_data
,
default_mbufs
*
pdev
->
len_per_image
);
}
pdev
->
image_data
=
NULL
;
Trace
(
TRACE_MEMORY
,
"Leaving free_buffers().
\n
"
);
}
/* The frame & image buffer mess.
Yes, this is a mess. Well, it used to be simple, but alas... In this
module, 3 buffers schemes are used to get the data from the USB bus to
the user program. The first scheme involves the ISO buffers (called thus
since they transport ISO data from the USB controller), and not really
interesting. Suffices to say the data from this buffer is quickly
gathered in an interrupt handler (pwc_isoc_handler) and placed into the
frame buffer.
The frame buffer is the second scheme, and is the central element here.
It collects the data from a single frame from the camera (hence, the
name). Frames are delimited by the USB camera with a short USB packet,
so that's easy to detect. The frame buffers form a list that is filled
by the camera+USB controller and drained by the user process through
either read() or mmap().
The image buffer is the third scheme, in which frames are decompressed
and converted into planar format. For mmap() there is more than
one image buffer available.
The frame buffers provide the image buffering. In case the user process
is a bit slow, this introduces lag and some undesired side-effects.
The problem arises when the frame buffer is full. I used to drop the last
frame, which makes the data in the queue stale very quickly. But dropping
the frame at the head of the queue proved to be a litte bit more difficult.
I tried a circular linked scheme, but this introduced more problems than
it solved.
Because filling and draining are completely asynchronous processes, this
requires some fiddling with pointers and mutexes.
Eventually, I came up with a system with 2 lists: an 'empty' frame list
and a 'full' frame list:
* Initially, all frame buffers but one are on the 'empty' list; the one
remaining buffer is our initial fill frame.
* If a frame is needed for filling, we try to take it from the 'empty'
list, unless that list is empty, in which case we take the buffer at
the head of the 'full' list.
* When our fill buffer has been filled, it is appended to the 'full'
list.
* If a frame is needed by read() or mmap(), it is taken from the head of
the 'full' list, handled, and then appended to the 'empty' list. If no
buffer is present on the 'full' list, we wait.
The advantage is that the buffer that is currently being decompressed/
converted, is on neither list, and thus not in our way (any other scheme
I tried had the problem of old data lingering in the queue).
Whatever strategy you choose, it always remains a tradeoff: with more
frame buffers the chances of a missed frame are reduced. On the other
hand, on slower machines it introduces lag because the queue will
always be full.
*/
/**
\brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
*/
static
inline
int
pwc_next_fill_frame
(
struct
pwc_device
*
pdev
)
{
int
ret
;
unsigned
long
flags
;
ret
=
0
;
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
if
(
pdev
->
fill_frame
!=
NULL
)
{
/* append to 'full' list */
if
(
pdev
->
full_frames
==
NULL
)
{
pdev
->
full_frames
=
pdev
->
fill_frame
;
pdev
->
full_frames_tail
=
pdev
->
full_frames
;
}
else
{
pdev
->
full_frames_tail
->
next
=
pdev
->
fill_frame
;
pdev
->
full_frames_tail
=
pdev
->
fill_frame
;
}
}
if
(
pdev
->
empty_frames
!=
NULL
)
{
/* We have empty frames available. That's easy */
pdev
->
fill_frame
=
pdev
->
empty_frames
;
pdev
->
empty_frames
=
pdev
->
empty_frames
->
next
;
}
else
{
/* Hmm. Take it from the full list */
#if PWC_DEBUG
/* sanity check */
if
(
pdev
->
full_frames
==
NULL
)
{
Err
(
"Neither empty or full frames available!
\n
"
);
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
return
-
EINVAL
;
}
#endif
pdev
->
fill_frame
=
pdev
->
full_frames
;
pdev
->
full_frames
=
pdev
->
full_frames
->
next
;
ret
=
1
;
}
pdev
->
fill_frame
->
next
=
NULL
;
#if PWC_DEBUG
Trace
(
TRACE_SEQUENCE
,
"Assigning sequence number %d.
\n
"
,
pdev
->
sequence
);
pdev
->
fill_frame
->
sequence
=
pdev
->
sequence
++
;
#endif
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
return
ret
;
}
/**
\brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
*/
static
void
pwc_reset_buffers
(
struct
pwc_device
*
pdev
)
{
int
i
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
pdev
->
full_frames
=
NULL
;
pdev
->
full_frames_tail
=
NULL
;
for
(
i
=
0
;
i
<
default_fbufs
;
i
++
)
{
pdev
->
fbuf
[
i
].
filled
=
0
;
if
(
i
>
0
)
pdev
->
fbuf
[
i
].
next
=
&
pdev
->
fbuf
[
i
-
1
];
else
pdev
->
fbuf
->
next
=
NULL
;
}
pdev
->
empty_frames
=
&
pdev
->
fbuf
[
default_fbufs
-
1
];
pdev
->
empty_frames_tail
=
pdev
->
fbuf
;
pdev
->
read_frame
=
NULL
;
pdev
->
fill_frame
=
pdev
->
empty_frames
;
pdev
->
empty_frames
=
pdev
->
empty_frames
->
next
;
pdev
->
image_read_pos
=
0
;
pdev
->
fill_image
=
0
;
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
}
/**
\brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
*/
static
int
pwc_handle_frame
(
struct
pwc_device
*
pdev
)
{
int
ret
=
0
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
/* First grab our read_frame; this is removed from all lists, so
we can release the lock after this without problems */
if
(
pdev
->
read_frame
!=
NULL
)
{
/* This can't theoretically happen */
Err
(
"Huh? Read frame still in use?
\n
"
);
}
else
{
if
(
pdev
->
full_frames
==
NULL
)
{
Err
(
"Woops. No frames ready.
\n
"
);
}
else
{
pdev
->
read_frame
=
pdev
->
full_frames
;
pdev
->
full_frames
=
pdev
->
full_frames
->
next
;
pdev
->
read_frame
->
next
=
NULL
;
}
if
(
pdev
->
read_frame
!=
NULL
)
{
#if PWC_DEBUG
Trace
(
TRACE_SEQUENCE
,
"Decompressing frame %d
\n
"
,
pdev
->
read_frame
->
sequence
);
#endif
/* Decompression is a lenghty process, so it's outside of the lock.
This gives the isoc_handler the opportunity to fill more frames
in the mean time.
*/
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
ret
=
pwc_decompress
(
pdev
);
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
/* We're done with read_buffer, tack it to the end of the empty buffer list */
if
(
pdev
->
empty_frames
==
NULL
)
{
pdev
->
empty_frames
=
pdev
->
read_frame
;
pdev
->
empty_frames_tail
=
pdev
->
empty_frames
;
}
else
{
pdev
->
empty_frames_tail
->
next
=
pdev
->
read_frame
;
pdev
->
empty_frames_tail
=
pdev
->
read_frame
;
}
pdev
->
read_frame
=
NULL
;
}
}
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
return
ret
;
}
/**
\brief Advance pointers of image buffer (after each user request)
*/
static
inline
void
pwc_next_image
(
struct
pwc_device
*
pdev
)
{
pdev
->
image_used
[
pdev
->
fill_image
]
=
0
;
pdev
->
fill_image
=
(
pdev
->
fill_image
+
1
)
%
default_mbufs
;
}
/* This gets called for the Isochronous pipe (video). This is done in
* interrupt time, so it has to be fast, not crash, and not stall. Neat.
*/
static
void
pwc_isoc_handler
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
pwc_device
*
pdev
;
int
i
,
fst
,
flen
;
int
awake
;
struct
pwc_frame_buf
*
fbuf
;
unsigned
char
*
fillptr
=
0
,
*
iso_buf
=
0
;
awake
=
0
;
pdev
=
(
struct
pwc_device
*
)
urb
->
context
;
if
(
pdev
==
NULL
)
{
Err
(
"isoc_handler() called with NULL device?!
\n
"
);
return
;
}
#ifdef PWC_MAGIC
if
(
pdev
->
magic
!=
PWC_MAGIC
)
{
Err
(
"isoc_handler() called with bad magic!
\n
"
);
return
;
}
#endif
if
(
urb
->
status
==
-
ENOENT
||
urb
->
status
==
-
ECONNRESET
)
{
Trace
(
TRACE_OPEN
,
"pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.
\n
"
,
urb
,
urb
->
status
==
-
ENOENT
?
""
:
"a"
);
return
;
}
if
(
urb
->
status
!=
-
EINPROGRESS
&&
urb
->
status
!=
0
)
{
const
char
*
errmsg
;
errmsg
=
"Unknown"
;
switch
(
urb
->
status
)
{
case
-
ENOSR
:
errmsg
=
"Buffer error (overrun)"
;
break
;
case
-
EPIPE
:
errmsg
=
"Stalled (device not responding)"
;
break
;
case
-
EOVERFLOW
:
errmsg
=
"Babble (bad cable?)"
;
break
;
case
-
EPROTO
:
errmsg
=
"Bit-stuff error (bad cable?)"
;
break
;
case
-
EILSEQ
:
errmsg
=
"CRC/Timeout (could be anything)"
;
break
;
case
-
ETIMEDOUT
:
errmsg
=
"NAK (device does not respond)"
;
break
;
}
Trace
(
TRACE_FLOW
,
"pwc_isoc_handler() called with status %d [%s].
\n
"
,
urb
->
status
,
errmsg
);
/* Give up after a number of contiguous errors on the USB bus.
Appearantly something is wrong so we simulate an unplug event.
*/
if
(
++
pdev
->
visoc_errors
>
MAX_ISOC_ERRORS
)
{
Info
(
"Too many ISOC errors, bailing out.
\n
"
);
pdev
->
error_status
=
EIO
;
awake
=
1
;
wake_up_interruptible
(
&
pdev
->
frameq
);
}
goto
handler_end
;
// ugly, but practical
}
fbuf
=
pdev
->
fill_frame
;
if
(
fbuf
==
NULL
)
{
Err
(
"pwc_isoc_handler without valid fill frame.
\n
"
);
awake
=
1
;
goto
handler_end
;
}
else
{
fillptr
=
fbuf
->
data
+
fbuf
->
filled
;
}
/* Reset ISOC error counter. We did get here, after all. */
pdev
->
visoc_errors
=
0
;
/* vsync: 0 = don't copy data
1 = sync-hunt
2 = synched
*/
/* Compact data */
for
(
i
=
0
;
i
<
urb
->
number_of_packets
;
i
++
)
{
fst
=
urb
->
iso_frame_desc
[
i
].
status
;
flen
=
urb
->
iso_frame_desc
[
i
].
actual_length
;
iso_buf
=
urb
->
transfer_buffer
+
urb
->
iso_frame_desc
[
i
].
offset
;
if
(
fst
==
0
)
{
if
(
flen
>
0
)
{
/* if valid data... */
if
(
pdev
->
vsync
>
0
)
{
/* ...and we are not sync-hunting... */
pdev
->
vsync
=
2
;
/* ...copy data to frame buffer, if possible */
if
(
flen
+
fbuf
->
filled
>
pdev
->
frame_total_size
)
{
Trace
(
TRACE_FLOW
,
"Frame buffer overflow (flen = %d, frame_total_size = %d).
\n
"
,
flen
,
pdev
->
frame_total_size
);
pdev
->
vsync
=
0
;
/* Hmm, let's wait for an EOF (end-of-frame) */
pdev
->
vframes_error
++
;
}
else
{
memmove
(
fillptr
,
iso_buf
,
flen
);
fillptr
+=
flen
;
}
}
fbuf
->
filled
+=
flen
;
}
/* ..flen > 0 */
if
(
flen
<
pdev
->
vlast_packet_size
)
{
/* Shorter packet... We probably have the end of an image-frame;
wake up read() process and let select()/poll() do something.
Decompression is done in user time over there.
*/
if
(
pdev
->
vsync
==
2
)
{
/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
frames on the USB wire after an exposure change. This conditition is
however detected in the cam and a bit is set in the header.
*/
if
(
pdev
->
type
==
730
)
{
unsigned
char
*
ptr
=
(
unsigned
char
*
)
fbuf
->
data
;
if
(
ptr
[
1
]
==
1
&&
ptr
[
0
]
&
0x10
)
{
#if PWC_DEBUG
Debug
(
"Hyundai CMOS sensor bug. Dropping frame %d.
\n
"
,
fbuf
->
sequence
);
#endif
pdev
->
drop_frames
+=
2
;
pdev
->
vframes_error
++
;
}
if
((
ptr
[
0
]
^
pdev
->
vmirror
)
&
0x01
)
{
if
(
ptr
[
0
]
&
0x01
)
Info
(
"Snapshot button pressed.
\n
"
);
else
Info
(
"Snapshot button released.
\n
"
);
}
if
((
ptr
[
0
]
^
pdev
->
vmirror
)
&
0x02
)
{
if
(
ptr
[
0
]
&
0x02
)
Info
(
"Image is mirrored.
\n
"
);
else
Info
(
"Image is normal.
\n
"
);
}
pdev
->
vmirror
=
ptr
[
0
]
&
0x03
;
/* Sometimes the trailer of the 730 is still sent as a 4 byte packet
after a short frame; this condition is filtered out specifically. A 4 byte
frame doesn't make sense anyway.
So we get either this sequence:
drop_bit set -> 4 byte frame -> short frame -> good frame
Or this one:
drop_bit set -> short frame -> good frame
So we drop either 3 or 2 frames in all!
*/
if
(
fbuf
->
filled
==
4
)
pdev
->
drop_frames
++
;
}
/* In case we were instructed to drop the frame, do so silently.
The buffer pointers are not updated either (but the counters are reset below).
*/
if
(
pdev
->
drop_frames
>
0
)
pdev
->
drop_frames
--
;
else
{
/* Check for underflow first */
if
(
fbuf
->
filled
<
pdev
->
frame_total_size
)
{
Trace
(
TRACE_FLOW
,
"Frame buffer underflow (%d bytes); discarded.
\n
"
,
fbuf
->
filled
);
pdev
->
vframes_error
++
;
}
else
{
/* Send only once per EOF */
awake
=
1
;
/* delay wake_ups */
/* Find our next frame to fill. This will always succeed, since we
* nick a frame from either empty or full list, but if we had to
* take it from the full list, it means a frame got dropped.
*/
if
(
pwc_next_fill_frame
(
pdev
))
{
pdev
->
vframes_dumped
++
;
if
((
pdev
->
vframe_count
>
FRAME_LOWMARK
)
&&
(
pwc_trace
&
TRACE_FLOW
))
{
if
(
pdev
->
vframes_dumped
<
20
)
Trace
(
TRACE_FLOW
,
"Dumping frame %d.
\n
"
,
pdev
->
vframe_count
);
if
(
pdev
->
vframes_dumped
==
20
)
Trace
(
TRACE_FLOW
,
"Dumping frame %d (last message).
\n
"
,
pdev
->
vframe_count
);
}
}
fbuf
=
pdev
->
fill_frame
;
}
}
/* !drop_frames */
pdev
->
vframe_count
++
;
}
fbuf
->
filled
=
0
;
fillptr
=
fbuf
->
data
;
pdev
->
vsync
=
1
;
}
/* .. flen < last_packet_size */
pdev
->
vlast_packet_size
=
flen
;
}
/* ..status == 0 */
#if PWC_DEBUG
/* This is normally not interesting to the user, unless you are really debugging something */
else
{
static
int
iso_error
=
0
;
iso_error
++
;
if
(
iso_error
<
20
)
Trace
(
TRACE_FLOW
,
"Iso frame %d of USB has error %d
\n
"
,
i
,
fst
);
}
#endif
}
handler_end:
if
(
awake
)
wake_up_interruptible
(
&
pdev
->
frameq
);
urb
->
dev
=
pdev
->
udev
;
i
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
i
!=
0
)
Err
(
"Error (%d) re-submitting urb in pwc_isoc_handler.
\n
"
,
i
);
}
static
int
pwc_isoc_init
(
struct
pwc_device
*
pdev
)
{
struct
usb_device
*
udev
;
struct
urb
*
urb
;
int
i
,
j
,
ret
;
struct
usb_interface
*
intf
;
struct
usb_host_interface
*
idesc
=
NULL
;
if
(
pdev
==
NULL
)
return
-
EFAULT
;
if
(
pdev
->
iso_init
)
return
0
;
pdev
->
vsync
=
0
;
udev
=
pdev
->
udev
;
/* Get the current alternate interface, adjust packet size */
if
(
!
udev
->
actconfig
)
return
-
EFAULT
;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
idesc
=
&
udev
->
actconfig
->
interface
[
0
]
->
altsetting
[
pdev
->
valternate
];
#else
intf
=
usb_ifnum_to_if
(
udev
,
0
);
if
(
intf
)
idesc
=
usb_altnum_to_altsetting
(
intf
,
pdev
->
valternate
);
#endif
if
(
!
idesc
)
return
-
EFAULT
;
/* Search video endpoint */
pdev
->
vmax_packet_size
=
-
1
;
for
(
i
=
0
;
i
<
idesc
->
desc
.
bNumEndpoints
;
i
++
)
if
((
idesc
->
endpoint
[
i
].
desc
.
bEndpointAddress
&
0xF
)
==
pdev
->
vendpoint
)
{
pdev
->
vmax_packet_size
=
idesc
->
endpoint
[
i
].
desc
.
wMaxPacketSize
;
break
;
}
if
(
pdev
->
vmax_packet_size
<
0
||
pdev
->
vmax_packet_size
>
ISO_MAX_FRAME_SIZE
)
{
Err
(
"Failed to find packet size for video endpoint in current alternate setting.
\n
"
);
return
-
ENFILE
;
/* Odd error, that should be noticable */
}
/* Set alternate interface */
ret
=
0
;
Trace
(
TRACE_OPEN
,
"Setting alternate interface %d
\n
"
,
pdev
->
valternate
);
ret
=
usb_set_interface
(
pdev
->
udev
,
0
,
pdev
->
valternate
);
if
(
ret
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
urb
=
usb_alloc_urb
(
ISO_FRAMES_PER_DESC
,
GFP_KERNEL
);
if
(
urb
==
NULL
)
{
Err
(
"Failed to allocate urb %d
\n
"
,
i
);
ret
=
-
ENOMEM
;
break
;
}
pdev
->
sbuf
[
i
].
urb
=
urb
;
Trace
(
TRACE_MEMORY
,
"Allocated URB at 0x%p
\n
"
,
urb
);
}
if
(
ret
)
{
/* De-allocate in reverse order */
while
(
i
>=
0
)
{
if
(
pdev
->
sbuf
[
i
].
urb
!=
NULL
)
usb_free_urb
(
pdev
->
sbuf
[
i
].
urb
);
pdev
->
sbuf
[
i
].
urb
=
NULL
;
i
--
;
}
return
ret
;
}
/* init URB structure */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
urb
=
pdev
->
sbuf
[
i
].
urb
;
urb
->
interval
=
1
;
// devik
urb
->
dev
=
udev
;
urb
->
pipe
=
usb_rcvisocpipe
(
udev
,
pdev
->
vendpoint
);
urb
->
transfer_flags
=
URB_ISO_ASAP
;
urb
->
transfer_buffer
=
pdev
->
sbuf
[
i
].
data
;
urb
->
transfer_buffer_length
=
ISO_BUFFER_SIZE
;
urb
->
complete
=
pwc_isoc_handler
;
urb
->
context
=
pdev
;
urb
->
start_frame
=
0
;
urb
->
number_of_packets
=
ISO_FRAMES_PER_DESC
;
for
(
j
=
0
;
j
<
ISO_FRAMES_PER_DESC
;
j
++
)
{
urb
->
iso_frame_desc
[
j
].
offset
=
j
*
ISO_MAX_FRAME_SIZE
;
urb
->
iso_frame_desc
[
j
].
length
=
pdev
->
vmax_packet_size
;
}
}
/* link */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
ret
=
usb_submit_urb
(
pdev
->
sbuf
[
i
].
urb
,
GFP_KERNEL
);
if
(
ret
)
Err
(
"isoc_init() submit_urb %d failed with error %d
\n
"
,
i
,
ret
);
else
Trace
(
TRACE_MEMORY
,
"URB 0x%p submitted.
\n
"
,
pdev
->
sbuf
[
i
].
urb
);
}
/* All is done... */
pdev
->
iso_init
=
1
;
Trace
(
TRACE_OPEN
,
"<< pwc_isoc_init()
\n
"
);
return
0
;
}
static
void
pwc_isoc_cleanup
(
struct
pwc_device
*
pdev
)
{
int
i
;
Trace
(
TRACE_OPEN
,
">> pwc_isoc_cleanup()
\n
"
);
if
(
pdev
==
NULL
)
return
;
/* Unlinking ISOC buffers one by one */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
struct
urb
*
urb
;
urb
=
pdev
->
sbuf
[
i
].
urb
;
if
(
urb
!=
0
)
{
if
(
pdev
->
iso_init
)
{
Trace
(
TRACE_MEMORY
,
"Unlinking URB %p
\n
"
,
urb
);
usb_kill_urb
(
urb
);
}
Trace
(
TRACE_MEMORY
,
"Freeing URB
\n
"
);
usb_free_urb
(
urb
);
pdev
->
sbuf
[
i
].
urb
=
NULL
;
}
}
/* Stop camera, but only if we are sure the camera is still there (unplug
is signalled by EPIPE)
*/
if
(
pdev
->
error_status
&&
pdev
->
error_status
!=
EPIPE
)
{
Trace
(
TRACE_OPEN
,
"Setting alternate interface 0.
\n
"
);
usb_set_interface
(
pdev
->
udev
,
0
,
0
);
}
pdev
->
iso_init
=
0
;
Trace
(
TRACE_OPEN
,
"<< pwc_isoc_cleanup()
\n
"
);
}
int
pwc_try_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
new_fps
,
int
new_compression
,
int
new_snapshot
)
{
int
ret
,
start
;
/* Stop isoc stuff */
pwc_isoc_cleanup
(
pdev
);
/* Reset parameters */
pwc_reset_buffers
(
pdev
);
/* Try to set video mode... */
start
=
ret
=
pwc_set_video_mode
(
pdev
,
width
,
height
,
new_fps
,
new_compression
,
new_snapshot
);
if
(
ret
)
{
Trace
(
TRACE_FLOW
,
"pwc_set_video_mode attempt 1 failed.
\n
"
);
/* That failed... restore old mode (we know that worked) */
start
=
pwc_set_video_mode
(
pdev
,
pdev
->
view
.
x
,
pdev
->
view
.
y
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
if
(
start
)
{
Trace
(
TRACE_FLOW
,
"pwc_set_video_mode attempt 2 failed.
\n
"
);
}
}
if
(
start
==
0
)
{
if
(
pwc_isoc_init
(
pdev
)
<
0
)
{
Info
(
"Failed to restart ISOC transfers in pwc_try_video_mode.
\n
"
);
ret
=
-
EAGAIN
;
/* let's try again, who knows if it works a second time */
}
}
pdev
->
drop_frames
++
;
/* try to avoid garbage during switch */
return
ret
;
/* Return original error code */
}
/***************************************************************************/
/* Video4Linux functions */
static
int
pwc_video_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
i
;
struct
video_device
*
vdev
=
video_devdata
(
file
);
struct
pwc_device
*
pdev
;
Trace
(
TRACE_OPEN
,
">> video_open called(vdev = 0x%p).
\n
"
,
vdev
);
pdev
=
(
struct
pwc_device
*
)
vdev
->
priv
;
if
(
pdev
==
NULL
)
BUG
();
if
(
pdev
->
vopen
)
return
-
EBUSY
;
down
(
&
pdev
->
modlock
);
if
(
!
pdev
->
usb_init
)
{
Trace
(
TRACE_OPEN
,
"Doing first time initialization.
\n
"
);
pdev
->
usb_init
=
1
;
if
(
pwc_trace
&
TRACE_OPEN
)
{
/* Query sensor type */
const
char
*
sensor_type
=
NULL
;
int
ret
;
ret
=
pwc_get_cmos_sensor
(
pdev
,
&
i
);
if
(
ret
>=
0
)
{
switch
(
i
)
{
case
0x00
:
sensor_type
=
"Hyundai CMOS sensor"
;
break
;
case
0x20
:
sensor_type
=
"Sony CCD sensor + TDA8787"
;
break
;
case
0x2E
:
sensor_type
=
"Sony CCD sensor + Exas 98L59"
;
break
;
case
0x2F
:
sensor_type
=
"Sony CCD sensor + ADI 9804"
;
break
;
case
0x30
:
sensor_type
=
"Sharp CCD sensor + TDA8787"
;
break
;
case
0x3E
:
sensor_type
=
"Sharp CCD sensor + Exas 98L59"
;
break
;
case
0x3F
:
sensor_type
=
"Sharp CCD sensor + ADI 9804"
;
break
;
case
0x40
:
sensor_type
=
"UPA 1021 sensor"
;
break
;
case
0x100
:
sensor_type
=
"VGA sensor"
;
break
;
case
0x101
:
sensor_type
=
"PAL MR sensor"
;
break
;
default:
sensor_type
=
"unknown type of sensor"
;
break
;
}
}
if
(
sensor_type
!=
NULL
)
Info
(
"This %s camera is equipped with a %s (%d).
\n
"
,
pdev
->
vdev
->
name
,
sensor_type
,
i
);
}
}
/* Turn on camera */
if
(
power_save
)
{
i
=
pwc_camera_power
(
pdev
,
1
);
if
(
i
<
0
)
Info
(
"Failed to restore power to the camera! (%d)
\n
"
,
i
);
}
/* Set LED on/off time */
if
(
pwc_set_leds
(
pdev
,
led_on
,
led_off
)
<
0
)
Info
(
"Failed to set LED on/off time.
\n
"
);
pwc_construct
(
pdev
);
/* set min/max sizes correct */
/* So far, so good. Allocate memory. */
i
=
pwc_allocate_buffers
(
pdev
);
if
(
i
<
0
)
{
Trace
(
TRACE_OPEN
,
"Failed to allocate buffer memory.
\n
"
);
up
(
&
pdev
->
modlock
);
return
i
;
}
/* Reset buffers & parameters */
pwc_reset_buffers
(
pdev
);
for
(
i
=
0
;
i
<
default_mbufs
;
i
++
)
pdev
->
image_used
[
i
]
=
0
;
pdev
->
vframe_count
=
0
;
pdev
->
vframes_dumped
=
0
;
pdev
->
vframes_error
=
0
;
pdev
->
visoc_errors
=
0
;
pdev
->
error_status
=
0
;
#if PWC_DEBUG
pdev
->
sequence
=
0
;
#endif
pwc_construct
(
pdev
);
/* set min/max sizes correct */
/* Set some defaults */
pdev
->
vsnapshot
=
0
;
/* Start iso pipe for video; first try the last used video size
(or the default one); if that fails try QCIF/10 or QSIF/10;
it that fails too, give up.
*/
i
=
pwc_set_video_mode
(
pdev
,
pwc_image_sizes
[
pdev
->
vsize
].
x
,
pwc_image_sizes
[
pdev
->
vsize
].
y
,
pdev
->
vframes
,
pdev
->
vcompression
,
0
);
if
(
i
)
{
Trace
(
TRACE_OPEN
,
"First attempt at set_video_mode failed.
\n
"
);
if
(
pdev
->
type
==
730
||
pdev
->
type
==
740
||
pdev
->
type
==
750
)
i
=
pwc_set_video_mode
(
pdev
,
pwc_image_sizes
[
PSZ_QSIF
].
x
,
pwc_image_sizes
[
PSZ_QSIF
].
y
,
10
,
pdev
->
vcompression
,
0
);
else
i
=
pwc_set_video_mode
(
pdev
,
pwc_image_sizes
[
PSZ_QCIF
].
x
,
pwc_image_sizes
[
PSZ_QCIF
].
y
,
10
,
pdev
->
vcompression
,
0
);
}
if
(
i
)
{
Trace
(
TRACE_OPEN
,
"Second attempt at set_video_mode failed.
\n
"
);
up
(
&
pdev
->
modlock
);
return
i
;
}
i
=
pwc_isoc_init
(
pdev
);
if
(
i
)
{
Trace
(
TRACE_OPEN
,
"Failed to init ISOC stuff = %d.
\n
"
,
i
);
up
(
&
pdev
->
modlock
);
return
i
;
}
pdev
->
vopen
++
;
file
->
private_data
=
vdev
;
up
(
&
pdev
->
modlock
);
Trace
(
TRACE_OPEN
,
"<< video_open() returns 0.
\n
"
);
return
0
;
}
/* Note that all cleanup is done in the reverse order as in _open */
static
int
pwc_video_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
video_device
*
vdev
=
file
->
private_data
;
struct
pwc_device
*
pdev
;
int
i
;
Trace
(
TRACE_OPEN
,
">> video_close called(vdev = 0x%p).
\n
"
,
vdev
);
pdev
=
(
struct
pwc_device
*
)
vdev
->
priv
;
if
(
pdev
->
vopen
==
0
)
Info
(
"video_close() called on closed device?
\n
"
);
/* Dump statistics, but only if a reasonable amount of frames were
processed (to prevent endless log-entries in case of snap-shot
programs)
*/
if
(
pdev
->
vframe_count
>
20
)
Info
(
"Closing video device: %d frames received, dumped %d frames, %d frames with errors.
\n
"
,
pdev
->
vframe_count
,
pdev
->
vframes_dumped
,
pdev
->
vframes_error
);
switch
(
pdev
->
type
)
{
case
675
:
case
680
:
case
690
:
case
720
:
case
730
:
case
740
:
case
750
:
pwc_dec23_exit
();
/* Timon & Kiara */
break
;
case
645
:
case
646
:
pwc_dec1_exit
();
break
;
}
pwc_isoc_cleanup
(
pdev
);
pwc_free_buffers
(
pdev
);
/* Turn off LEDS and power down camera, but only when not unplugged */
if
(
pdev
->
error_status
!=
EPIPE
)
{
/* Turn LEDs off */
if
(
pwc_set_leds
(
pdev
,
0
,
0
)
<
0
)
Info
(
"Failed to set LED on/off time.
\n
"
);
if
(
power_save
)
{
i
=
pwc_camera_power
(
pdev
,
0
);
if
(
i
<
0
)
Err
(
"Failed to power down camera (%d)
\n
"
,
i
);
}
}
pdev
->
vopen
=
0
;
Trace
(
TRACE_OPEN
,
"<< video_close()
\n
"
);
return
0
;
}
/*
* FIXME: what about two parallel reads ????
* ANSWER: Not supported. You can't open the device more than once,
despite what the V4L1 interface says. First, I don't see
the need, second there's no mechanism of alerting the
2nd/3rd/... process of events like changing image size.
And I don't see the point of blocking that for the
2nd/3rd/... process.
In multi-threaded environments reading parallel from any
device is tricky anyhow.
*/
static
ssize_t
pwc_video_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
video_device
*
vdev
=
file
->
private_data
;
struct
pwc_device
*
pdev
;
int
noblock
=
file
->
f_flags
&
O_NONBLOCK
;
DECLARE_WAITQUEUE
(
wait
,
current
);
int
bytes_to_read
;
Trace
(
TRACE_READ
,
"video_read(0x%p, %p, %d) called.
\n
"
,
vdev
,
buf
,
count
);
if
(
vdev
==
NULL
)
return
-
EFAULT
;
pdev
=
vdev
->
priv
;
if
(
pdev
==
NULL
)
return
-
EFAULT
;
if
(
pdev
->
error_status
)
return
-
pdev
->
error_status
;
/* Something happened, report what. */
/* In case we're doing partial reads, we don't have to wait for a frame */
if
(
pdev
->
image_read_pos
==
0
)
{
/* Do wait queueing according to the (doc)book */
add_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
while
(
pdev
->
full_frames
==
NULL
)
{
/* Check for unplugged/etc. here */
if
(
pdev
->
error_status
)
{
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
return
-
pdev
->
error_status
;
}
if
(
noblock
)
{
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
return
-
EWOULDBLOCK
;
}
if
(
signal_pending
(
current
))
{
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
return
-
ERESTARTSYS
;
}
schedule
();
set_current_state
(
TASK_INTERRUPTIBLE
);
}
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
/* Decompress and release frame */
if
(
pwc_handle_frame
(
pdev
))
return
-
EFAULT
;
}
Trace
(
TRACE_READ
,
"Copying data to user space.
\n
"
);
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
bytes_to_read
=
pdev
->
frame_size
;
else
bytes_to_read
=
pdev
->
view
.
size
;
/* copy bytes to user space; we allow for partial reads */
if
(
count
+
pdev
->
image_read_pos
>
bytes_to_read
)
count
=
bytes_to_read
-
pdev
->
image_read_pos
;
if
(
copy_to_user
(
buf
,
pdev
->
image_ptr
[
pdev
->
fill_image
]
+
pdev
->
image_read_pos
,
count
))
return
-
EFAULT
;
pdev
->
image_read_pos
+=
count
;
if
(
pdev
->
image_read_pos
>=
bytes_to_read
)
{
/* All data has been read */
pdev
->
image_read_pos
=
0
;
pwc_next_image
(
pdev
);
}
return
count
;
}
static
unsigned
int
pwc_video_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
struct
video_device
*
vdev
=
file
->
private_data
;
struct
pwc_device
*
pdev
;
if
(
vdev
==
NULL
)
return
-
EFAULT
;
pdev
=
vdev
->
priv
;
if
(
pdev
==
NULL
)
return
-
EFAULT
;
poll_wait
(
file
,
&
pdev
->
frameq
,
wait
);
if
(
pdev
->
error_status
)
return
POLLERR
;
if
(
pdev
->
full_frames
!=
NULL
)
/* we have frames waiting */
return
(
POLLIN
|
POLLRDNORM
);
return
0
;
}
static
int
pwc_video_do_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
void
*
arg
)
{
struct
video_device
*
vdev
=
file
->
private_data
;
struct
pwc_device
*
pdev
;
DECLARE_WAITQUEUE
(
wait
,
current
);
if
(
vdev
==
NULL
)
return
-
EFAULT
;
pdev
=
vdev
->
priv
;
if
(
pdev
==
NULL
)
return
-
EFAULT
;
switch
(
cmd
)
{
/* Query cabapilities */
case
VIDIOCGCAP
:
{
struct
video_capability
*
caps
=
arg
;
strcpy
(
caps
->
name
,
vdev
->
name
);
caps
->
type
=
VID_TYPE_CAPTURE
;
caps
->
channels
=
1
;
caps
->
audios
=
1
;
caps
->
minwidth
=
pdev
->
view_min
.
x
;
caps
->
minheight
=
pdev
->
view_min
.
y
;
caps
->
maxwidth
=
pdev
->
view_max
.
x
;
caps
->
maxheight
=
pdev
->
view_max
.
y
;
break
;
}
/* Channel functions (simulate 1 channel) */
case
VIDIOCGCHAN
:
{
struct
video_channel
*
v
=
arg
;
if
(
v
->
channel
!=
0
)
return
-
EINVAL
;
v
->
flags
=
0
;
v
->
tuners
=
0
;
v
->
type
=
VIDEO_TYPE_CAMERA
;
strcpy
(
v
->
name
,
"Webcam"
);
return
0
;
}
case
VIDIOCSCHAN
:
{
/* The spec says the argument is an integer, but
the bttv driver uses a video_channel arg, which
makes sense becasue it also has the norm flag.
*/
struct
video_channel
*
v
=
arg
;
if
(
v
->
channel
!=
0
)
return
-
EINVAL
;
return
0
;
}
/* Picture functions; contrast etc. */
case
VIDIOCGPICT
:
{
struct
video_picture
*
p
=
arg
;
int
val
;
val
=
pwc_get_brightness
(
pdev
);
if
(
val
>=
0
)
p
->
brightness
=
val
;
else
p
->
brightness
=
0xffff
;
val
=
pwc_get_contrast
(
pdev
);
if
(
val
>=
0
)
p
->
contrast
=
val
;
else
p
->
contrast
=
0xffff
;
/* Gamma, Whiteness, what's the difference? :) */
val
=
pwc_get_gamma
(
pdev
);
if
(
val
>=
0
)
p
->
whiteness
=
val
;
else
p
->
whiteness
=
0xffff
;
val
=
pwc_get_saturation
(
pdev
);
if
(
val
>=
0
)
p
->
colour
=
val
;
else
p
->
colour
=
0xffff
;
p
->
depth
=
24
;
p
->
palette
=
pdev
->
vpalette
;
p
->
hue
=
0xFFFF
;
/* N/A */
break
;
}
case
VIDIOCSPICT
:
{
struct
video_picture
*
p
=
arg
;
/*
* FIXME: Suppose we are mid read
ANSWER: No problem: the firmware of the camera
can handle brightness/contrast/etc
changes at _any_ time, and the palette
is used exactly once in the uncompress
routine.
*/
pwc_set_brightness
(
pdev
,
p
->
brightness
);
pwc_set_contrast
(
pdev
,
p
->
contrast
);
pwc_set_gamma
(
pdev
,
p
->
whiteness
);
pwc_set_saturation
(
pdev
,
p
->
colour
);
if
(
p
->
palette
&&
p
->
palette
!=
pdev
->
vpalette
)
{
switch
(
p
->
palette
)
{
case
VIDEO_PALETTE_YUV420P
:
case
VIDEO_PALETTE_RAW
:
pdev
->
vpalette
=
p
->
palette
;
return
pwc_try_video_mode
(
pdev
,
pdev
->
image
.
x
,
pdev
->
image
.
y
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
break
;
default:
return
-
EINVAL
;
break
;
}
}
break
;
}
/* Window/size parameters */
case
VIDIOCGWIN
:
{
struct
video_window
*
vw
=
arg
;
vw
->
x
=
0
;
vw
->
y
=
0
;
vw
->
width
=
pdev
->
view
.
x
;
vw
->
height
=
pdev
->
view
.
y
;
vw
->
chromakey
=
0
;
vw
->
flags
=
(
pdev
->
vframes
<<
PWC_FPS_SHIFT
)
|
(
pdev
->
vsnapshot
?
PWC_FPS_SNAPSHOT
:
0
);
break
;
}
case
VIDIOCSWIN
:
{
struct
video_window
*
vw
=
arg
;
int
fps
,
snapshot
,
ret
;
fps
=
(
vw
->
flags
&
PWC_FPS_FRMASK
)
>>
PWC_FPS_SHIFT
;
snapshot
=
vw
->
flags
&
PWC_FPS_SNAPSHOT
;
if
(
fps
==
0
)
fps
=
pdev
->
vframes
;
if
(
pdev
->
view
.
x
==
vw
->
width
&&
pdev
->
view
.
y
&&
fps
==
pdev
->
vframes
&&
snapshot
==
pdev
->
vsnapshot
)
return
0
;
ret
=
pwc_try_video_mode
(
pdev
,
vw
->
width
,
vw
->
height
,
fps
,
pdev
->
vcompression
,
snapshot
);
if
(
ret
)
return
ret
;
break
;
}
/* We don't have overlay support (yet) */
case
VIDIOCGFBUF
:
{
struct
video_buffer
*
vb
=
arg
;
memset
(
vb
,
0
,
sizeof
(
*
vb
));
break
;
}
/* mmap() functions */
case
VIDIOCGMBUF
:
{
/* Tell the user program how much memory is needed for a mmap() */
struct
video_mbuf
*
vm
=
arg
;
int
i
;
memset
(
vm
,
0
,
sizeof
(
*
vm
));
vm
->
size
=
default_mbufs
*
pdev
->
len_per_image
;
vm
->
frames
=
default_mbufs
;
/* double buffering should be enough for most applications */
for
(
i
=
0
;
i
<
default_mbufs
;
i
++
)
vm
->
offsets
[
i
]
=
i
*
pdev
->
len_per_image
;
break
;
}
case
VIDIOCMCAPTURE
:
{
/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
struct
video_mmap
*
vm
=
arg
;
Trace
(
TRACE_READ
,
"VIDIOCMCAPTURE: %dx%d, frame %d, format %d
\n
"
,
vm
->
width
,
vm
->
height
,
vm
->
frame
,
vm
->
format
);
if
(
vm
->
frame
<
0
||
vm
->
frame
>=
default_mbufs
)
return
-
EINVAL
;
/* xawtv is nasty. It probes the available palettes
by setting a very small image size and trying
various palettes... The driver doesn't support
such small images, so I'm working around it.
*/
if
(
vm
->
format
)
{
switch
(
vm
->
format
)
{
case
VIDEO_PALETTE_YUV420P
:
case
VIDEO_PALETTE_RAW
:
break
;
default:
return
-
EINVAL
;
break
;
}
}
if
((
vm
->
width
!=
pdev
->
view
.
x
||
vm
->
height
!=
pdev
->
view
.
y
)
&&
(
vm
->
width
>=
pdev
->
view_min
.
x
&&
vm
->
height
>=
pdev
->
view_min
.
y
))
{
int
ret
;
Trace
(
TRACE_OPEN
,
"VIDIOCMCAPTURE: changing size to please xawtv :-(.
\n
"
);
ret
=
pwc_try_video_mode
(
pdev
,
vm
->
width
,
vm
->
height
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
if
(
ret
)
return
ret
;
}
/* ... size mismatch */
/* FIXME: should we lock here? */
if
(
pdev
->
image_used
[
vm
->
frame
])
return
-
EBUSY
;
/* buffer wasn't available. Bummer */
pdev
->
image_used
[
vm
->
frame
]
=
1
;
/* Okay, we're done here. In the SYNC call we wait until a
frame comes available, then expand image into the given
buffer.
In contrast to the CPiA cam the Philips cams deliver a
constant stream, almost like a grabber card. Also,
we have separate buffers for the rawdata and the image,
meaning we can nearly always expand into the requested buffer.
*/
Trace
(
TRACE_READ
,
"VIDIOCMCAPTURE done.
\n
"
);
break
;
}
case
VIDIOCSYNC
:
{
/* The doc says: "Whenever a buffer is used it should
call VIDIOCSYNC to free this frame up and continue."
The only odd thing about this whole procedure is
that MCAPTURE flags the buffer as "in use", and
SYNC immediately unmarks it, while it isn't
after SYNC that you know that the buffer actually
got filled! So you better not start a CAPTURE in
the same frame immediately (use double buffering).
This is not a problem for this cam, since it has
extra intermediate buffers, but a hardware
grabber card will then overwrite the buffer
you're working on.
*/
int
*
mbuf
=
arg
;
int
ret
;
Trace
(
TRACE_READ
,
"VIDIOCSYNC called (%d).
\n
"
,
*
mbuf
);
/* bounds check */
if
(
*
mbuf
<
0
||
*
mbuf
>=
default_mbufs
)
return
-
EINVAL
;
/* check if this buffer was requested anyway */
if
(
pdev
->
image_used
[
*
mbuf
]
==
0
)
return
-
EINVAL
;
/* Add ourselves to the frame wait-queue.
FIXME: needs auditing for safety.
QUESTION: In what respect? I think that using the
frameq is safe now.
*/
add_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
while
(
pdev
->
full_frames
==
NULL
)
{
if
(
pdev
->
error_status
)
{
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
return
-
pdev
->
error_status
;
}
if
(
signal_pending
(
current
))
{
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
return
-
ERESTARTSYS
;
}
schedule
();
set_current_state
(
TASK_INTERRUPTIBLE
);
}
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
/* The frame is ready. Expand in the image buffer
requested by the user. I don't care if you
mmap() 5 buffers and request data in this order:
buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
Grabber hardware may not be so forgiving.
*/
Trace
(
TRACE_READ
,
"VIDIOCSYNC: frame ready.
\n
"
);
pdev
->
fill_image
=
*
mbuf
;
/* tell in which buffer we want the image to be expanded */
/* Decompress, etc */
ret
=
pwc_handle_frame
(
pdev
);
pdev
->
image_used
[
*
mbuf
]
=
0
;
if
(
ret
)
return
-
EFAULT
;
break
;
}
case
VIDIOCGAUDIO
:
{
struct
video_audio
*
v
=
arg
;
strcpy
(
v
->
name
,
"Microphone"
);
v
->
audio
=
-
1
;
/* unknown audio minor */
v
->
flags
=
0
;
v
->
mode
=
VIDEO_SOUND_MONO
;
v
->
volume
=
0
;
v
->
bass
=
0
;
v
->
treble
=
0
;
v
->
balance
=
0x8000
;
v
->
step
=
1
;
break
;
}
case
VIDIOCSAUDIO
:
{
/* Dummy: nothing can be set */
break
;
}
case
VIDIOCGUNIT
:
{
struct
video_unit
*
vu
=
arg
;
vu
->
video
=
pdev
->
vdev
->
minor
&
0x3F
;
vu
->
audio
=
-
1
;
/* not known yet */
vu
->
vbi
=
-
1
;
vu
->
radio
=
-
1
;
vu
->
teletext
=
-
1
;
break
;
}
default:
return
pwc_ioctl
(
pdev
,
cmd
,
arg
);
}
/* ..switch */
return
0
;
}
static
int
pwc_video_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
video_usercopy
(
inode
,
file
,
cmd
,
arg
,
pwc_video_do_ioctl
);
}
static
int
pwc_video_mmap
(
struct
file
*
file
,
struct
vm_area_struct
*
vma
)
{
struct
video_device
*
vdev
=
file
->
private_data
;
struct
pwc_device
*
pdev
;
unsigned
long
start
=
vma
->
vm_start
;
unsigned
long
size
=
vma
->
vm_end
-
vma
->
vm_start
;
unsigned
long
page
,
pos
;
Trace
(
TRACE_MEMORY
,
"mmap(0x%p, 0x%lx, %lu) called.
\n
"
,
vdev
,
start
,
size
);
pdev
=
vdev
->
priv
;
vma
->
vm_flags
|=
VM_IO
;
pos
=
(
unsigned
long
)
pdev
->
image_data
;
while
(
size
>
0
)
{
page
=
vmalloc_to_pfn
((
void
*
)
pos
);
if
(
remap_pfn_range
(
vma
,
start
,
page
,
PAGE_SIZE
,
PAGE_SHARED
))
return
-
EAGAIN
;
start
+=
PAGE_SIZE
;
pos
+=
PAGE_SIZE
;
if
(
size
>
PAGE_SIZE
)
size
-=
PAGE_SIZE
;
else
size
=
0
;
}
return
0
;
}
/***************************************************************************/
/* USB functions */
/* This function gets called when a new device is plugged in or the usb core
* is loaded.
*/
static
int
usb_pwc_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
struct
pwc_device
*
pdev
=
NULL
;
int
vendor_id
,
product_id
,
type_id
;
int
i
,
hint
;
int
features
=
0
;
int
video_nr
=
-
1
;
/* default: use next available device */
char
serial_number
[
30
],
*
name
;
/* Check if we can handle this device */
Trace
(
TRACE_PROBE
,
"probe() called [%04X %04X], if %d
\n
"
,
udev
->
descriptor
.
idVendor
,
udev
->
descriptor
.
idProduct
,
intf
->
altsetting
->
desc
.
bInterfaceNumber
);
/* the interfaces are probed one by one. We are only interested in the
video interface (0) now.
Interface 1 is the Audio Control, and interface 2 Audio itself.
*/
if
(
intf
->
altsetting
->
desc
.
bInterfaceNumber
>
0
)
return
-
ENODEV
;
vendor_id
=
udev
->
descriptor
.
idVendor
;
product_id
=
udev
->
descriptor
.
idProduct
;
if
(
vendor_id
==
0x0471
)
{
switch
(
product_id
)
{
case
0x0302
:
Info
(
"Philips PCA645VC USB webcam detected.
\n
"
);
name
=
"Philips 645 webcam"
;
type_id
=
645
;
break
;
case
0x0303
:
Info
(
"Philips PCA646VC USB webcam detected.
\n
"
);
name
=
"Philips 646 webcam"
;
type_id
=
646
;
break
;
case
0x0304
:
Info
(
"Askey VC010 type 2 USB webcam detected.
\n
"
);
name
=
"Askey VC010 webcam"
;
type_id
=
646
;
break
;
case
0x0307
:
Info
(
"Philips PCVC675K (Vesta) USB webcam detected.
\n
"
);
name
=
"Philips 675 webcam"
;
type_id
=
675
;
break
;
case
0x0308
:
Info
(
"Philips PCVC680K (Vesta Pro) USB webcam detected.
\n
"
);
name
=
"Philips 680 webcam"
;
type_id
=
680
;
break
;
case
0x030C
:
Info
(
"Philips PCVC690K (Vesta Pro Scan) USB webcam detected.
\n
"
);
name
=
"Philips 690 webcam"
;
type_id
=
690
;
break
;
case
0x0310
:
Info
(
"Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.
\n
"
);
name
=
"Philips 730 webcam"
;
type_id
=
730
;
break
;
case
0x0311
:
Info
(
"Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.
\n
"
);
name
=
"Philips 740 webcam"
;
type_id
=
740
;
break
;
case
0x0312
:
Info
(
"Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.
\n
"
);
name
=
"Philips 750 webcam"
;
type_id
=
750
;
break
;
case
0x0313
:
Info
(
"Philips PCVC720K/40 (ToUCam XS) USB webcam detected.
\n
"
);
name
=
"Philips 720K/40 webcam"
;
type_id
=
720
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x069A
)
{
switch
(
product_id
)
{
case
0x0001
:
Info
(
"Askey VC010 type 1 USB webcam detected.
\n
"
);
name
=
"Askey VC010 webcam"
;
type_id
=
645
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x046d
)
{
switch
(
product_id
)
{
case
0x08b0
:
Info
(
"Logitech QuickCam Pro 3000 USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Pro 3000"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x08b1
:
Info
(
"Logitech QuickCam Notebook Pro USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Notebook Pro"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x08b2
:
Info
(
"Logitech QuickCam 4000 Pro USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Pro 4000"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x08b3
:
Info
(
"Logitech QuickCam Zoom USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Zoom"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x08B4
:
Info
(
"Logitech QuickCam Zoom (new model) USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Zoom"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x08b5
:
Info
(
"Logitech QuickCam Orbit/Sphere USB webcam detected.
\n
"
);
name
=
"Logitech QuickCam Orbit"
;
type_id
=
740
;
/* CCD sensor */
features
|=
FEATURE_MOTOR_PANTILT
;
break
;
case
0x08b6
:
case
0x08b7
:
case
0x08b8
:
Info
(
"Logitech QuickCam detected (reserved ID).
\n
"
);
name
=
"Logitech QuickCam (res.)"
;
type_id
=
730
;
/* Assuming CMOS */
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x055d
)
{
/* I don't know the difference between the C10 and the C30;
I suppose the difference is the sensor, but both cameras
work equally well with a type_id of 675
*/
switch
(
product_id
)
{
case
0x9000
:
Info
(
"Samsung MPC-C10 USB webcam detected.
\n
"
);
name
=
"Samsung MPC-C10"
;
type_id
=
675
;
break
;
case
0x9001
:
Info
(
"Samsung MPC-C30 USB webcam detected.
\n
"
);
name
=
"Samsung MPC-C30"
;
type_id
=
675
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x041e
)
{
switch
(
product_id
)
{
case
0x400c
:
Info
(
"Creative Labs Webcam 5 detected.
\n
"
);
name
=
"Creative Labs Webcam 5"
;
type_id
=
730
;
break
;
case
0x4011
:
Info
(
"Creative Labs Webcam Pro Ex detected.
\n
"
);
name
=
"Creative Labs Webcam Pro Ex"
;
type_id
=
740
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x04cc
)
{
switch
(
product_id
)
{
case
0x8116
:
Info
(
"Sotec Afina Eye USB webcam detected.
\n
"
);
name
=
"Sotec Afina Eye"
;
type_id
=
730
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x06be
)
{
switch
(
product_id
)
{
case
0x8116
:
/* This is essentially the same cam as the Sotec Afina Eye */
Info
(
"AME Co. Afina Eye USB webcam detected.
\n
"
);
name
=
"AME Co. Afina Eye"
;
type_id
=
750
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x0d81
)
{
switch
(
product_id
)
{
case
0x1900
:
Info
(
"Visionite VCS-UC300 USB webcam detected.
\n
"
);
name
=
"Visionite VCS-UC300"
;
type_id
=
740
;
/* CCD sensor */
break
;
case
0x1910
:
Info
(
"Visionite VCS-UM100 USB webcam detected.
\n
"
);
name
=
"Visionite VCS-UM100"
;
type_id
=
730
;
/* CMOS sensor */
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
return
-
ENODEV
;
/* Not any of the know types; but the list keeps growing. */
memset
(
serial_number
,
0
,
30
);
usb_string
(
udev
,
udev
->
descriptor
.
iSerialNumber
,
serial_number
,
29
);
Trace
(
TRACE_PROBE
,
"Device serial number is %s
\n
"
,
serial_number
);
if
(
udev
->
descriptor
.
bNumConfigurations
>
1
)
Info
(
"Warning: more than 1 configuration available.
\n
"
);
/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
pdev
=
kmalloc
(
sizeof
(
struct
pwc_device
),
GFP_KERNEL
);
if
(
pdev
==
NULL
)
{
Err
(
"Oops, could not allocate memory for pwc_device.
\n
"
);
return
-
ENOMEM
;
}
memset
(
pdev
,
0
,
sizeof
(
struct
pwc_device
));
pdev
->
type
=
type_id
;
pdev
->
vsize
=
default_size
;
pdev
->
vframes
=
default_fps
;
strcpy
(
pdev
->
serial
,
serial_number
);
pdev
->
features
=
features
;
if
(
vendor_id
==
0x046D
&&
product_id
==
0x08B5
)
{
/* Logitech QuickCam Orbit
The ranges have been determined experimentally; they may differ from cam to cam.
Also, the exact ranges left-right and up-down are different for my cam
*/
pdev
->
angle_range
.
pan_min
=
-
7000
;
pdev
->
angle_range
.
pan_max
=
7000
;
pdev
->
angle_range
.
tilt_min
=
-
3000
;
pdev
->
angle_range
.
tilt_max
=
2500
;
}
init_MUTEX
(
&
pdev
->
modlock
);
pdev
->
ptrlock
=
SPIN_LOCK_UNLOCKED
;
pdev
->
udev
=
udev
;
init_waitqueue_head
(
&
pdev
->
frameq
);
pdev
->
vcompression
=
pwc_preferred_compression
;
/* Allocate video_device structure */
pdev
->
vdev
=
video_device_alloc
();
if
(
pdev
->
vdev
==
0
)
{
Err
(
"Err, cannot allocate video_device struture. Failing probe."
);
kfree
(
pdev
);
return
-
ENOMEM
;
}
memcpy
(
pdev
->
vdev
,
&
pwc_template
,
sizeof
(
pwc_template
));
strcpy
(
pdev
->
vdev
->
name
,
name
);
pdev
->
vdev
->
owner
=
THIS_MODULE
;
video_set_drvdata
(
pdev
->
vdev
,
pdev
);
pdev
->
release
=
udev
->
descriptor
.
bcdDevice
;
Trace
(
TRACE_PROBE
,
"Release: %04x
\n
"
,
pdev
->
release
);
/* Now search device_hint[] table for a match, so we can hint a node number. */
for
(
hint
=
0
;
hint
<
MAX_DEV_HINTS
;
hint
++
)
{
if
(((
device_hint
[
hint
].
type
==
-
1
)
||
(
device_hint
[
hint
].
type
==
pdev
->
type
))
&&
(
device_hint
[
hint
].
pdev
==
NULL
))
{
/* so far, so good... try serial number */
if
((
device_hint
[
hint
].
serial_number
[
0
]
==
'*'
)
||
!
strcmp
(
device_hint
[
hint
].
serial_number
,
serial_number
))
{
/* match! */
video_nr
=
device_hint
[
hint
].
device_node
;
Trace
(
TRACE_PROBE
,
"Found hint, will try to register as /dev/video%d
\n
"
,
video_nr
);
break
;
}
}
}
pdev
->
vdev
->
release
=
video_device_release
;
i
=
video_register_device
(
pdev
->
vdev
,
VFL_TYPE_GRABBER
,
video_nr
);
if
(
i
<
0
)
{
Err
(
"Failed to register as video device (%d).
\n
"
,
i
);
video_device_release
(
pdev
->
vdev
);
/* Drip... drip... drip... */
kfree
(
pdev
);
/* Oops, no memory leaks please */
return
-
EIO
;
}
else
{
Info
(
"Registered as /dev/video%d.
\n
"
,
pdev
->
vdev
->
minor
&
0x3F
);
}
/* occupy slot */
if
(
hint
<
MAX_DEV_HINTS
)
device_hint
[
hint
].
pdev
=
pdev
;
Trace
(
TRACE_PROBE
,
"probe() function returning struct at 0x%p.
\n
"
,
pdev
);
usb_set_intfdata
(
intf
,
pdev
);
return
0
;
}
/* The user janked out the cable... */
static
void
usb_pwc_disconnect
(
struct
usb_interface
*
intf
)
{
struct
pwc_device
*
pdev
;
int
hint
;
lock_kernel
();
pdev
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
if
(
pdev
==
NULL
)
{
Err
(
"pwc_disconnect() Called without private pointer.
\n
"
);
goto
disconnect_out
;
}
if
(
pdev
->
udev
==
NULL
)
{
Err
(
"pwc_disconnect() already called for %p
\n
"
,
pdev
);
goto
disconnect_out
;
}
if
(
pdev
->
udev
!=
interface_to_usbdev
(
intf
))
{
Err
(
"pwc_disconnect() Woops: pointer mismatch udev/pdev.
\n
"
);
goto
disconnect_out
;
}
#ifdef PWC_MAGIC
if
(
pdev
->
magic
!=
PWC_MAGIC
)
{
Err
(
"pwc_disconnect() Magic number failed. Consult your scrolls and try again.
\n
"
);
goto
disconnect_out
;
}
#endif
/* We got unplugged; this is signalled by an EPIPE error code */
if
(
pdev
->
vopen
)
{
Info
(
"Disconnected while webcam is in use!
\n
"
);
pdev
->
error_status
=
EPIPE
;
}
/* Alert waiting processes */
wake_up_interruptible
(
&
pdev
->
frameq
);
/* Wait until device is closed */
while
(
pdev
->
vopen
)
schedule
();
/* Device is now closed, so we can safely unregister it */
Trace
(
TRACE_PROBE
,
"Unregistering video device in disconnect().
\n
"
);
video_unregister_device
(
pdev
->
vdev
);
/* Free memory (don't set pdev to 0 just yet) */
kfree
(
pdev
);
disconnect_out:
/* search device_hint[] table if we occupy a slot, by any chance */
for
(
hint
=
0
;
hint
<
MAX_DEV_HINTS
;
hint
++
)
if
(
device_hint
[
hint
].
pdev
==
pdev
)
device_hint
[
hint
].
pdev
=
NULL
;
unlock_kernel
();
}
/* *grunt* We have to do atoi ourselves :-( */
static
int
pwc_atoi
(
const
char
*
s
)
{
int
k
=
0
;
k
=
0
;
while
(
*
s
!=
'\0'
&&
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
k
=
10
*
k
+
(
*
s
-
'0'
);
s
++
;
}
return
k
;
}
/*
* Initialization code & module stuff
*/
static
char
*
size
=
NULL
;
static
int
fps
=
0
;
static
int
fbufs
=
0
;
static
int
mbufs
=
0
;
static
int
trace
=
-
1
;
static
int
compression
=
-
1
;
static
int
leds
[
2
]
=
{
-
1
,
-
1
};
static
char
*
dev_hint
[
MAX_DEV_HINTS
]
=
{
};
MODULE_PARM
(
size
,
"s"
);
MODULE_PARM_DESC
(
size
,
"Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"
);
MODULE_PARM
(
fps
,
"i"
);
MODULE_PARM_DESC
(
fps
,
"Initial frames per second. Varies with model, useful range 5-30"
);
MODULE_PARM
(
fbufs
,
"i"
);
MODULE_PARM_DESC
(
fbufs
,
"Number of internal frame buffers to reserve"
);
MODULE_PARM
(
mbufs
,
"i"
);
MODULE_PARM_DESC
(
mbufs
,
"Number of external (mmap()ed) image buffers"
);
MODULE_PARM
(
trace
,
"i"
);
MODULE_PARM_DESC
(
trace
,
"For debugging purposes"
);
MODULE_PARM
(
power_save
,
"i"
);
MODULE_PARM_DESC
(
power_save
,
"Turn power save feature in camera on or off"
);
MODULE_PARM
(
compression
,
"i"
);
MODULE_PARM_DESC
(
compression
,
"Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"
);
MODULE_PARM
(
leds
,
"2i"
);
MODULE_PARM_DESC
(
leds
,
"LED on,off time in milliseconds"
);
MODULE_PARM
(
dev_hint
,
"0-20s"
);
MODULE_PARM_DESC
(
dev_hint
,
"Device node hints"
);
MODULE_DESCRIPTION
(
"Philips & OEM USB webcam driver"
);
MODULE_AUTHOR
(
"Luc Saillard <luc@saillard.org>"
);
MODULE_LICENSE
(
"GPL"
);
static
int
__init
usb_pwc_init
(
void
)
{
int
i
,
sz
;
char
*
sizenames
[
PSZ_MAX
]
=
{
"sqcif"
,
"qsif"
,
"qcif"
,
"sif"
,
"cif"
,
"vga"
};
Info
(
"Philips webcam module version "
PWC_VERSION
" loaded.
\n
"
);
Info
(
"Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.
\n
"
);
Info
(
"Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,
\n
"
);
Info
(
"the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.
\n
"
);
if
(
fps
)
{
if
(
fps
<
4
||
fps
>
30
)
{
Err
(
"Framerate out of bounds (4-30).
\n
"
);
return
-
EINVAL
;
}
default_fps
=
fps
;
Info
(
"Default framerate set to %d.
\n
"
,
default_fps
);
}
if
(
size
)
{
/* string; try matching with array */
for
(
sz
=
0
;
sz
<
PSZ_MAX
;
sz
++
)
{
if
(
!
strcmp
(
sizenames
[
sz
],
size
))
{
/* Found! */
default_size
=
sz
;
break
;
}
}
if
(
sz
==
PSZ_MAX
)
{
Err
(
"Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].
\n
"
);
return
-
EINVAL
;
}
Info
(
"Default image size set to %s [%dx%d].
\n
"
,
sizenames
[
default_size
],
pwc_image_sizes
[
default_size
].
x
,
pwc_image_sizes
[
default_size
].
y
);
}
if
(
mbufs
)
{
if
(
mbufs
<
1
||
mbufs
>
MAX_IMAGES
)
{
Err
(
"Illegal number of mmap() buffers; use a number between 1 and %d.
\n
"
,
MAX_IMAGES
);
return
-
EINVAL
;
}
default_mbufs
=
mbufs
;
Info
(
"Number of image buffers set to %d.
\n
"
,
default_mbufs
);
}
if
(
fbufs
)
{
if
(
fbufs
<
2
||
fbufs
>
MAX_FRAMES
)
{
Err
(
"Illegal number of frame buffers; use a number between 2 and %d.
\n
"
,
MAX_FRAMES
);
return
-
EINVAL
;
}
default_fbufs
=
fbufs
;
Info
(
"Number of frame buffers set to %d.
\n
"
,
default_fbufs
);
}
if
(
trace
>=
0
)
{
Info
(
"Trace options: 0x%04x
\n
"
,
trace
);
pwc_trace
=
trace
;
}
if
(
compression
>=
0
)
{
if
(
compression
>
3
)
{
Err
(
"Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).
\n
"
);
return
-
EINVAL
;
}
pwc_preferred_compression
=
compression
;
Info
(
"Preferred compression set to %d.
\n
"
,
pwc_preferred_compression
);
}
if
(
power_save
)
Info
(
"Enabling power save on open/close.
\n
"
);
if
(
leds
[
0
]
>=
0
)
led_on
=
leds
[
0
];
if
(
leds
[
1
]
>=
0
)
led_off
=
leds
[
1
];
/* Big device node whoopla. Basicly, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
& serial number. The format is [type[.serialnumber]:]node.
Any camera that isn't matched by these rules gets the next
available free device node.
*/
for
(
i
=
0
;
i
<
MAX_DEV_HINTS
;
i
++
)
{
char
*
s
,
*
colon
,
*
dot
;
/* This loop also initializes the array */
device_hint
[
i
].
pdev
=
NULL
;
s
=
dev_hint
[
i
];
if
(
s
!=
NULL
&&
*
s
!=
'\0'
)
{
device_hint
[
i
].
type
=
-
1
;
/* wildcard */
strcpy
(
device_hint
[
i
].
serial_number
,
"*"
);
/* parse string: chop at ':' & '/' */
colon
=
dot
=
s
;
while
(
*
colon
!=
'\0'
&&
*
colon
!=
':'
)
colon
++
;
while
(
*
dot
!=
'\0'
&&
*
dot
!=
'.'
)
dot
++
;
/* Few sanity checks */
if
(
*
dot
!=
'\0'
&&
dot
>
colon
)
{
Err
(
"Malformed camera hint: the colon must be after the dot.
\n
"
);
return
-
EINVAL
;
}
if
(
*
colon
==
'\0'
)
{
/* No colon */
if
(
*
dot
!=
'\0'
)
{
Err
(
"Malformed camera hint: no colon + device node given.
\n
"
);
return
-
EINVAL
;
}
else
{
/* No type or serial number specified, just a number. */
device_hint
[
i
].
device_node
=
pwc_atoi
(
s
);
}
}
else
{
/* There's a colon, so we have at least a type and a device node */
device_hint
[
i
].
type
=
pwc_atoi
(
s
);
device_hint
[
i
].
device_node
=
pwc_atoi
(
colon
+
1
);
if
(
*
dot
!=
'\0'
)
{
/* There's a serial number as well */
int
k
;
dot
++
;
k
=
0
;
while
(
*
dot
!=
':'
&&
k
<
29
)
{
device_hint
[
i
].
serial_number
[
k
++
]
=
*
dot
;
dot
++
;
}
device_hint
[
i
].
serial_number
[
k
]
=
'\0'
;
}
}
#if PWC_DEBUG
Debug
(
"device_hint[%d]:
\n
"
,
i
);
Debug
(
" type : %d
\n
"
,
device_hint
[
i
].
type
);
Debug
(
" serial# : %s
\n
"
,
device_hint
[
i
].
serial_number
);
Debug
(
" node : %d
\n
"
,
device_hint
[
i
].
device_node
);
#endif
}
else
device_hint
[
i
].
type
=
0
;
/* not filled */
}
/* ..for MAX_DEV_HINTS */
Trace
(
TRACE_PROBE
,
"Registering driver at address 0x%p.
\n
"
,
&
pwc_driver
);
return
usb_register
(
&
pwc_driver
);
}
static
void
__exit
usb_pwc_exit
(
void
)
{
Trace
(
TRACE_MODULE
,
"Deregistering driver.
\n
"
);
usb_deregister
(
&
pwc_driver
);
Info
(
"Philips webcam module removed.
\n
"
);
}
module_init
(
usb_pwc_init
);
module_exit
(
usb_pwc_exit
);
drivers/usb/media/pwc/pwc-ioctl.h
0 → 100644
View file @
ef4333ae
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
/* (C) 2001-2004 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This is pwc-ioctl.h belonging to PWC 8.12.1
It contains structures and defines to communicate from user space
directly to the driver.
*/
/*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2003/12/13 Nemosft Unv. Some modifications to make interfacing to
PWCX easier
*/
/* These are private ioctl() commands, specific for the Philips webcams.
They contain functions not found in other webcams, and settings not
specified in the Video4Linux API.
The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix
PWC Philps WebCam
G optional: Get
S optional: Set
... the function
*/
/* Enumeration of image sizes */
#define PSZ_SQCIF 0x00
#define PSZ_QSIF 0x01
#define PSZ_QCIF 0x02
#define PSZ_SIF 0x03
#define PSZ_CIF 0x04
#define PSZ_VGA 0x05
#define PSZ_MAX 6
/* The frame rate is encoded in the video_window.flags parameter using
the upper 16 bits, since some flags are defined nowadays. The following
defines provide a mask and shift to filter out this value.
In 'Snapshot' mode the camera freezes its automatic exposure and colour
balance controls.
*/
#define PWC_FPS_SHIFT 16
#define PWC_FPS_MASK 0x00FF0000
#define PWC_FPS_FRMASK 0x003F0000
#define PWC_FPS_SNAPSHOT 0x00400000
/* structure for transfering x & y coordinates */
struct
pwc_coord
{
int
x
,
y
;
/* guess what */
int
size
;
/* size, or offset */
};
/* Used with VIDIOCPWCPROBE */
struct
pwc_probe
{
char
name
[
32
];
int
type
;
};
struct
pwc_serial
{
char
serial
[
30
];
/* String with serial number. Contains terminating 0 */
};
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
#define PWC_WB_FL 2
#define PWC_WB_MANUAL 3
#define PWC_WB_AUTO 4
/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
'read_red' and 'read_blue' are read-only.
*/
struct
pwc_whitebalance
{
int
mode
;
int
manual_red
,
manual_blue
;
/* R/W */
int
read_red
,
read_blue
;
/* R/O */
};
/*
'control_speed' and 'control_delay' are used in automatic whitebalance mode,
and tell the camera how fast it should react to changes in lighting, and
with how much delay. Valid values are 0..65535.
*/
struct
pwc_wb_speed
{
int
control_speed
;
int
control_delay
;
};
/* Used with VIDIOCPWC[SG]LED */
struct
pwc_leds
{
int
led_on
;
/* Led on-time; range = 0..25000 */
int
led_off
;
/* Led off-time; range = 0..25000 */
};
/* Image size (used with GREALSIZE) */
struct
pwc_imagesize
{
int
width
;
int
height
;
};
/* Defines and structures for Motorized Pan & Tilt */
#define PWC_MPT_PAN 0x01
#define PWC_MPT_TILT 0x02
#define PWC_MPT_TIMEOUT 0x04
/* for status */
/* Set angles; when absolute != 0, the angle is absolute and the
driver calculates the relative offset for you. This can only
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
absolute angles.
*/
struct
pwc_mpt_angles
{
int
absolute
;
/* write-only */
int
pan
;
/* degrees * 100 */
int
tilt
;
/* degress * 100 */
};
/* Range of angles of the camera, both horizontally and vertically.
*/
struct
pwc_mpt_range
{
int
pan_min
,
pan_max
;
/* degrees * 100 */
int
tilt_min
,
tilt_max
;
};
struct
pwc_mpt_status
{
int
status
;
int
time_pan
;
int
time_tilt
;
};
/* This is used for out-of-kernel decompression. With it, you can get
all the necessary information to initialize and use the decompressor
routines in standalone applications.
*/
struct
pwc_video_command
{
int
type
;
/* camera type (645, 675, 730, etc.) */
int
release
;
/* release number */
int
size
;
/* one of PSZ_* */
int
alternate
;
int
command_len
;
/* length of USB video command */
unsigned
char
command_buf
[
13
];
/* Actual USB video command */
int
bandlength
;
/* >0 = compressed */
int
frame_size
;
/* Size of one (un)compressed frame */
};
/* Flags for PWCX subroutines. Not all modules honour all flags. */
#define PWCX_FLAG_PLANAR 0x0001
#define PWCX_FLAG_BAYER 0x0008
/* IOCTL definitions */
/* Restore user settings */
#define VIDIOCPWCRUSER _IO('v', 192)
/* Save user settings */
#define VIDIOCPWCSUSER _IO('v', 193)
/* Restore factory settings */
#define VIDIOCPWCFACTORY _IO('v', 194)
/* You can manipulate the compression factor. A compression preference of 0
means use uncompressed modes when available; 1 is low compression, 2 is
medium and 3 is high compression preferred. Of course, the higher the
compression, the lower the bandwidth used but more chance of artefacts
in the image. The driver automatically chooses a higher compression when
the preferred mode is not available.
*/
/* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
/* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
/* Retrieve serial number of camera */
#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
/* This is a probe function; since so many devices are supported, it
becomes difficult to include all the names in programs that want to
check for the enhanced Philips stuff. So in stead, try this PROBE;
it returns a structure with the original name, and the corresponding
Philips type.
To use, fill the structure with zeroes, call PROBE and if that succeeds,
compare the name with that returned from VIDIOCGCAP; they should be the
same. If so, you can be assured it is a Philips (OEM) cam and the type
is valid.
*/
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCGAGC _IOR('v', 200, int)
/* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
/* Color compensation (Auto White Balance) */
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
/* Auto WB speed */
#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
/* LEDs on/off/blink; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
/* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
/* Backlight compensation; 0 = off, otherwise on */
#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
/* Flickerless mode; = 0 off, otherwise on */
#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
/* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
/* Motorized pan & tilt functions */
#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
/* Get the USB set-video command; needed for initializing libpwcx */
#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
struct
pwc_table_init_buffer
{
int
len
;
char
*
buffer
;
};
#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)
#endif
drivers/usb/media/pwc/pwc-kiara.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This tables contains entries for the 730/740/750 (Kiara) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#include "pwc-kiara.h"
#include "pwc-uncompress.h"
const
struct
Kiara_table_entry
Kiara_table
[
PSZ_MAX
][
6
][
4
]
=
{
/* SQCIF */
{
/* 5 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 10 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 15 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 20 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 25 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 30 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
},
/* QSIF */
{
/* 5 fps */
{
{
1
,
146
,
0
,
{
0x1D
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0x00
,
0x80
}},
{
1
,
146
,
0
,
{
0x1D
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0x00
,
0x80
}},
{
1
,
146
,
0
,
{
0x1D
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0x00
,
0x80
}},
{
1
,
146
,
0
,
{
0x1D
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0x00
,
0x80
}},
},
/* 10 fps */
{
{
2
,
291
,
0
,
{
0x1C
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x23
,
0x01
,
0x80
}},
{
1
,
192
,
630
,
{
0x14
,
0xF4
,
0x30
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xC0
,
0x00
,
0x80
}},
{
1
,
192
,
630
,
{
0x14
,
0xF4
,
0x30
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xC0
,
0x00
,
0x80
}},
{
1
,
192
,
630
,
{
0x14
,
0xF4
,
0x30
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xC0
,
0x00
,
0x80
}},
},
/* 15 fps */
{
{
3
,
437
,
0
,
{
0x1B
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0xB5
,
0x01
,
0x80
}},
{
2
,
292
,
640
,
{
0x13
,
0xF4
,
0x30
,
0x13
,
0xF7
,
0x13
,
0x2F
,
0x13
,
0x20
,
0x24
,
0x01
,
0x80
}},
{
2
,
292
,
640
,
{
0x13
,
0xF4
,
0x30
,
0x13
,
0xF7
,
0x13
,
0x2F
,
0x13
,
0x20
,
0x24
,
0x01
,
0x80
}},
{
1
,
192
,
420
,
{
0x13
,
0xF4
,
0x30
,
0x0D
,
0x1B
,
0x0C
,
0x53
,
0x1E
,
0x18
,
0xC0
,
0x00
,
0x80
}},
},
/* 20 fps */
{
{
4
,
589
,
0
,
{
0x1A
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x4D
,
0x02
,
0x80
}},
{
3
,
448
,
730
,
{
0x12
,
0xF4
,
0x30
,
0x16
,
0xC9
,
0x16
,
0x01
,
0x0E
,
0x18
,
0xC0
,
0x01
,
0x80
}},
{
2
,
292
,
476
,
{
0x12
,
0xF4
,
0x30
,
0x0E
,
0xD8
,
0x0E
,
0x10
,
0x19
,
0x18
,
0x24
,
0x01
,
0x80
}},
{
1
,
192
,
312
,
{
0x12
,
0xF4
,
0x50
,
0x09
,
0xB3
,
0x08
,
0xEB
,
0x1E
,
0x18
,
0xC0
,
0x00
,
0x80
}},
},
/* 25 fps */
{
{
5
,
703
,
0
,
{
0x19
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0xBF
,
0x02
,
0x80
}},
{
3
,
447
,
610
,
{
0x11
,
0xF4
,
0x30
,
0x13
,
0x0B
,
0x12
,
0x43
,
0x14
,
0x28
,
0xBF
,
0x01
,
0x80
}},
{
2
,
292
,
398
,
{
0x11
,
0xF4
,
0x50
,
0x0C
,
0x6C
,
0x0B
,
0xA4
,
0x1E
,
0x28
,
0x24
,
0x01
,
0x80
}},
{
1
,
193
,
262
,
{
0x11
,
0xF4
,
0x50
,
0x08
,
0x23
,
0x07
,
0x5B
,
0x1E
,
0x28
,
0xC1
,
0x00
,
0x80
}},
},
/* 30 fps */
{
{
8
,
874
,
0
,
{
0x18
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x6A
,
0x03
,
0x80
}},
{
5
,
704
,
730
,
{
0x10
,
0xF4
,
0x30
,
0x16
,
0xC9
,
0x16
,
0x01
,
0x0E
,
0x28
,
0xC0
,
0x02
,
0x80
}},
{
3
,
448
,
492
,
{
0x10
,
0xF4
,
0x30
,
0x0F
,
0x5D
,
0x0E
,
0x95
,
0x15
,
0x28
,
0xC0
,
0x01
,
0x80
}},
{
2
,
292
,
320
,
{
0x10
,
0xF4
,
0x50
,
0x09
,
0xFB
,
0x09
,
0x33
,
0x1E
,
0x28
,
0x24
,
0x01
,
0x80
}},
},
},
/* QCIF */
{
/* 5 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 10 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 15 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 20 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 25 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 30 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
},
/* SIF */
{
/* 5 fps */
{
{
4
,
582
,
0
,
{
0x0D
,
0xF4
,
0x30
,
0x00
,
0x00
,
0x00
,
0x00
,
0x04
,
0x00
,
0x46
,
0x02
,
0x80
}},
{
3
,
387
,
1276
,
{
0x05
,
0xF4
,
0x30
,
0x27
,
0xD8
,
0x26
,
0x48
,
0x03
,
0x10
,
0x83
,
0x01
,
0x80
}},
{
2
,
291
,
960
,
{
0x05
,
0xF4
,
0x30
,
0x1D
,
0xF2
,
0x1C
,
0x62
,
0x04
,
0x10
,
0x23
,
0x01
,
0x80
}},
{
1
,
191
,
630
,
{
0x05
,
0xF4
,
0x50
,
0x13
,
0xA9
,
0x12
,
0x19
,
0x05
,
0x18
,
0xBF
,
0x00
,
0x80
}},
},
/* 10 fps */
{
{
0
,
},
{
6
,
775
,
1278
,
{
0x04
,
0xF4
,
0x30
,
0x27
,
0xE8
,
0x26
,
0x58
,
0x05
,
0x30
,
0x07
,
0x03
,
0x80
}},
{
3
,
447
,
736
,
{
0x04
,
0xF4
,
0x30
,
0x16
,
0xFB
,
0x15
,
0x6B
,
0x05
,
0x28
,
0xBF
,
0x01
,
0x80
}},
{
2
,
292
,
480
,
{
0x04
,
0xF4
,
0x70
,
0x0E
,
0xF9
,
0x0D
,
0x69
,
0x09
,
0x28
,
0x24
,
0x01
,
0x80
}},
},
/* 15 fps */
{
{
0
,
},
{
9
,
955
,
1050
,
{
0x03
,
0xF4
,
0x30
,
0x20
,
0xCF
,
0x1F
,
0x3F
,
0x06
,
0x48
,
0xBB
,
0x03
,
0x80
}},
{
4
,
592
,
650
,
{
0x03
,
0xF4
,
0x30
,
0x14
,
0x44
,
0x12
,
0xB4
,
0x08
,
0x30
,
0x50
,
0x02
,
0x80
}},
{
3
,
448
,
492
,
{
0x03
,
0xF4
,
0x50
,
0x0F
,
0x52
,
0x0D
,
0xC2
,
0x09
,
0x38
,
0xC0
,
0x01
,
0x80
}},
},
/* 20 fps */
{
{
0
,
},
{
9
,
958
,
782
,
{
0x02
,
0xF4
,
0x30
,
0x18
,
0x6A
,
0x16
,
0xDA
,
0x0B
,
0x58
,
0xBE
,
0x03
,
0x80
}},
{
5
,
703
,
574
,
{
0x02
,
0xF4
,
0x50
,
0x11
,
0xE7
,
0x10
,
0x57
,
0x0B
,
0x40
,
0xBF
,
0x02
,
0x80
}},
{
3
,
446
,
364
,
{
0x02
,
0xF4
,
0x90
,
0x0B
,
0x5C
,
0x09
,
0xCC
,
0x0E
,
0x38
,
0xBE
,
0x01
,
0x80
}},
},
/* 25 fps */
{
{
0
,
},
{
9
,
958
,
654
,
{
0x01
,
0xF4
,
0x30
,
0x14
,
0x66
,
0x12
,
0xD6
,
0x0B
,
0x50
,
0xBE
,
0x03
,
0x80
}},
{
6
,
776
,
530
,
{
0x01
,
0xF4
,
0x50
,
0x10
,
0x8C
,
0x0E
,
0xFC
,
0x0C
,
0x48
,
0x08
,
0x03
,
0x80
}},
{
4
,
592
,
404
,
{
0x01
,
0xF4
,
0x70
,
0x0C
,
0x96
,
0x0B
,
0x06
,
0x0B
,
0x48
,
0x50
,
0x02
,
0x80
}},
},
/* 30 fps */
{
{
0
,
},
{
9
,
957
,
526
,
{
0x00
,
0xF4
,
0x50
,
0x10
,
0x68
,
0x0E
,
0xD8
,
0x0D
,
0x58
,
0xBD
,
0x03
,
0x80
}},
{
6
,
775
,
426
,
{
0x00
,
0xF4
,
0x70
,
0x0D
,
0x48
,
0x0B
,
0xB8
,
0x0F
,
0x50
,
0x07
,
0x03
,
0x80
}},
{
4
,
590
,
324
,
{
0x00
,
0x7A
,
0x88
,
0x0A
,
0x1C
,
0x08
,
0xB4
,
0x0E
,
0x50
,
0x4E
,
0x02
,
0x80
}},
},
},
/* CIF */
{
/* 5 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 10 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 15 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 20 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 25 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 30 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
},
/* VGA */
{
/* 5 fps */
{
{
0
,
},
{
6
,
773
,
1272
,
{
0x25
,
0xF4
,
0x30
,
0x27
,
0xB6
,
0x24
,
0x96
,
0x02
,
0x30
,
0x05
,
0x03
,
0x80
}},
{
4
,
592
,
976
,
{
0x25
,
0xF4
,
0x50
,
0x1E
,
0x78
,
0x1B
,
0x58
,
0x03
,
0x30
,
0x50
,
0x02
,
0x80
}},
{
3
,
448
,
738
,
{
0x25
,
0xF4
,
0x90
,
0x17
,
0x0C
,
0x13
,
0xEC
,
0x04
,
0x30
,
0xC0
,
0x01
,
0x80
}},
},
/* 10 fps */
{
{
0
,
},
{
9
,
956
,
788
,
{
0x24
,
0xF4
,
0x70
,
0x18
,
0x9C
,
0x15
,
0x7C
,
0x03
,
0x48
,
0xBC
,
0x03
,
0x80
}},
{
6
,
776
,
640
,
{
0x24
,
0xF4
,
0xB0
,
0x13
,
0xFC
,
0x11
,
0x2C
,
0x04
,
0x48
,
0x08
,
0x03
,
0x80
}},
{
4
,
592
,
488
,
{
0x24
,
0x7A
,
0xE8
,
0x0F
,
0x3C
,
0x0C
,
0x6C
,
0x06
,
0x48
,
0x50
,
0x02
,
0x80
}},
},
/* 15 fps */
{
{
0
,
},
{
9
,
957
,
526
,
{
0x23
,
0x7A
,
0xE8
,
0x10
,
0x68
,
0x0D
,
0x98
,
0x06
,
0x58
,
0xBD
,
0x03
,
0x80
}},
{
9
,
957
,
526
,
{
0x23
,
0x7A
,
0xE8
,
0x10
,
0x68
,
0x0D
,
0x98
,
0x06
,
0x58
,
0xBD
,
0x03
,
0x80
}},
{
8
,
895
,
492
,
{
0x23
,
0x7A
,
0xE8
,
0x0F
,
0x5D
,
0x0C
,
0x8D
,
0x06
,
0x58
,
0x7F
,
0x03
,
0x80
}},
},
/* 20 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 25 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 30 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
},
};
/*
* Rom table for kiara chips
*
* 32 roms tables (one for each resolution ?)
* 2 tables per roms (one for each passes) (Y, and U&V)
* 128 bytes per passes
*/
const
unsigned
int
KiaraRomTable
[
8
][
2
][
16
][
8
]
=
{
{
/* version 0 */
{
/* version 0, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009292
,
0x00009292
,
0x00009493
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 0, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000001
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009252
,
0x00009292
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009292
,
0x00009292
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00009292
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x00009493
,
0x000126dc
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x000136e4
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 1 */
{
/* version 1, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009252
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00009252
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 1, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000009
,
0x00000049
,
0x00000009
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000049
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009292
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 2 */
{
/* version 2, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009493
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000124db
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 2, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x0000a49b
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 3 */
{
/* version 3, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000136e4
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 3, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 4 */
{
/* version 4, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x00009493
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 4, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00000249
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009252
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009252
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009493
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 5 */
{
/* version 5, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001c924
,
0x0002496d
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 5, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009252
,
0x00009252
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000126dc
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 6 */
{
/* version 6, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000126db
,
0x0001c924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 6, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009252
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000126dc
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 7 */
{
/* version 7, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b725
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001c96e
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x000136e4
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000136db
,
0x00024924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 7, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x00009492
,
0x00009292
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000136db
,
0x0001b724
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x0001c924
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
}
};
drivers/usb/media/pwc/pwc-kiara.h
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Entries for the Kiara (730/740/750) camera */
#ifndef PWC_KIARA_H
#define PWC_KIARA_H
#include "pwc-ioctl.h"
struct
Kiara_table_entry
{
char
alternate
;
/* USB alternate interface */
unsigned
short
packetsize
;
/* Normal packet size */
unsigned
short
bandlength
;
/* Bandlength when decompressing */
unsigned
char
mode
[
12
];
/* precomputed mode settings for cam */
};
const
extern
struct
Kiara_table_entry
Kiara_table
[
PSZ_MAX
][
6
][
4
];
const
extern
unsigned
int
KiaraRomTable
[
8
][
2
][
16
][
8
];
#endif
drivers/usb/media/pwc/pwc-misc.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/slab.h>
#include "pwc.h"
struct
pwc_coord
pwc_image_sizes
[
PSZ_MAX
]
=
{
{
128
,
96
,
0
},
{
160
,
120
,
0
},
{
176
,
144
,
0
},
{
320
,
240
,
0
},
{
352
,
288
,
0
},
{
640
,
480
,
0
},
};
/* x,y -> PSZ_ */
int
pwc_decode_size
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
)
{
int
i
,
find
;
/* Make sure we don't go beyond our max size.
NB: we have different limits for RAW and normal modes. In case
you don't have the decompressor loaded or use RAW mode,
the maximum viewable size is smaller.
*/
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
{
if
(
width
>
pdev
->
abs_max
.
x
||
height
>
pdev
->
abs_max
.
y
)
{
Debug
(
"VIDEO_PALETTE_RAW: going beyond abs_max.
\n
"
);
return
-
1
;
}
}
else
{
if
(
width
>
pdev
->
view_max
.
x
||
height
>
pdev
->
view_max
.
y
)
{
Debug
(
"VIDEO_PALETTE_ not RAW: going beyond view_max.
\n
"
);
return
-
1
;
}
}
/* Find the largest size supported by the camera that fits into the
requested size.
*/
find
=
-
1
;
for
(
i
=
0
;
i
<
PSZ_MAX
;
i
++
)
{
if
(
pdev
->
image_mask
&
(
1
<<
i
))
{
if
(
pwc_image_sizes
[
i
].
x
<=
width
&&
pwc_image_sizes
[
i
].
y
<=
height
)
find
=
i
;
}
}
return
find
;
}
/* initialize variables depending on type and decompressor*/
void
pwc_construct
(
struct
pwc_device
*
pdev
)
{
switch
(
pdev
->
type
)
{
case
645
:
case
646
:
pdev
->
view_min
.
x
=
128
;
pdev
->
view_min
.
y
=
96
;
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
y
=
288
;
pdev
->
abs_max
.
x
=
352
;
pdev
->
abs_max
.
y
=
288
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_CIF
;
pdev
->
vcinterface
=
2
;
pdev
->
vendpoint
=
4
;
pdev
->
frame_header_size
=
0
;
pdev
->
frame_trailer_size
=
0
;
break
;
case
675
:
case
680
:
case
690
:
pdev
->
view_min
.
x
=
128
;
pdev
->
view_min
.
y
=
96
;
/* Anthill bug #38: PWC always reports max size, even without PWCX */
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
y
=
480
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QSIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_CIF
|
1
<<
PSZ_VGA
;
pdev
->
abs_max
.
x
=
640
;
pdev
->
abs_max
.
y
=
480
;
pdev
->
vcinterface
=
3
;
pdev
->
vendpoint
=
4
;
pdev
->
frame_header_size
=
0
;
pdev
->
frame_trailer_size
=
0
;
break
;
case
720
:
case
730
:
case
740
:
case
750
:
pdev
->
view_min
.
x
=
160
;
pdev
->
view_min
.
y
=
120
;
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
y
=
480
;
pdev
->
image_mask
=
1
<<
PSZ_QSIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_VGA
;
pdev
->
abs_max
.
x
=
640
;
pdev
->
abs_max
.
y
=
480
;
pdev
->
vcinterface
=
3
;
pdev
->
vendpoint
=
5
;
pdev
->
frame_header_size
=
TOUCAM_HEADER_SIZE
;
pdev
->
frame_trailer_size
=
TOUCAM_TRAILER_SIZE
;
break
;
}
Debug
(
"type = %d
\n
"
,
pdev
->
type
);
pdev
->
vpalette
=
VIDEO_PALETTE_YUV420P
;
/* default */
pdev
->
view_min
.
size
=
pdev
->
view_min
.
x
*
pdev
->
view_min
.
y
;
pdev
->
view_max
.
size
=
pdev
->
view_max
.
x
*
pdev
->
view_max
.
y
;
/* length of image, in YUV format; always allocate enough memory. */
pdev
->
len_per_image
=
(
pdev
->
abs_max
.
x
*
pdev
->
abs_max
.
y
*
3
)
/
2
;
}
drivers/usb/media/pwc/pwc-nala.h
0 → 100644
View file @
ef4333ae
/* SQCIF */
{
{
0
,
0
,
{
0x04
,
0x01
,
0x03
}},
{
8
,
0
,
{
0x05
,
0x01
,
0x03
}},
{
7
,
0
,
{
0x08
,
0x01
,
0x03
}},
{
7
,
0
,
{
0x0A
,
0x01
,
0x03
}},
{
6
,
0
,
{
0x0C
,
0x01
,
0x03
}},
{
5
,
0
,
{
0x0F
,
0x01
,
0x03
}},
{
4
,
0
,
{
0x14
,
0x01
,
0x03
}},
{
3
,
0
,
{
0x18
,
0x01
,
0x03
}},
},
/* QSIF */
{
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
},
/* QCIF */
{
{
0
,
0
,
{
0x04
,
0x01
,
0x02
}},
{
8
,
0
,
{
0x05
,
0x01
,
0x02
}},
{
7
,
0
,
{
0x08
,
0x01
,
0x02
}},
{
6
,
0
,
{
0x0A
,
0x01
,
0x02
}},
{
5
,
0
,
{
0x0C
,
0x01
,
0x02
}},
{
4
,
0
,
{
0x0F
,
0x01
,
0x02
}},
{
1
,
0
,
{
0x14
,
0x01
,
0x02
}},
{
1
,
0
,
{
0x18
,
0x01
,
0x02
}},
},
/* SIF */
{
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
},
/* CIF */
{
{
4
,
0
,
{
0x04
,
0x01
,
0x01
}},
{
7
,
1
,
{
0x05
,
0x03
,
0x01
}},
{
6
,
1
,
{
0x08
,
0x03
,
0x01
}},
{
4
,
1
,
{
0x0A
,
0x03
,
0x01
}},
{
3
,
1
,
{
0x0C
,
0x03
,
0x01
}},
{
2
,
1
,
{
0x0F
,
0x03
,
0x01
}},
{
0
},
{
0
},
},
/* VGA */
{
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
{
0
},
},
drivers/usb/media/pwc/pwc-timon.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This tables contains entries for the 675/680/690 (Timon) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#include "pwc-timon.h"
const
struct
Timon_table_entry
Timon_table
[
PSZ_MAX
][
6
][
4
]
=
{
/* SQCIF */
{
/* 5 fps */
{
{
1
,
140
,
0
,
{
0x05
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x8C
,
0xFC
,
0x80
,
0x02
}},
{
1
,
140
,
0
,
{
0x05
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x8C
,
0xFC
,
0x80
,
0x02
}},
{
1
,
140
,
0
,
{
0x05
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x8C
,
0xFC
,
0x80
,
0x02
}},
{
1
,
140
,
0
,
{
0x05
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x8C
,
0xFC
,
0x80
,
0x02
}},
},
/* 10 fps */
{
{
2
,
280
,
0
,
{
0x04
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x18
,
0xA9
,
0x80
,
0x02
}},
{
2
,
280
,
0
,
{
0x04
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x18
,
0xA9
,
0x80
,
0x02
}},
{
2
,
280
,
0
,
{
0x04
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x18
,
0xA9
,
0x80
,
0x02
}},
{
2
,
280
,
0
,
{
0x04
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x18
,
0xA9
,
0x80
,
0x02
}},
},
/* 15 fps */
{
{
3
,
410
,
0
,
{
0x03
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x9A
,
0x71
,
0x80
,
0x02
}},
{
3
,
410
,
0
,
{
0x03
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x9A
,
0x71
,
0x80
,
0x02
}},
{
3
,
410
,
0
,
{
0x03
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x9A
,
0x71
,
0x80
,
0x02
}},
{
3
,
410
,
0
,
{
0x03
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x9A
,
0x71
,
0x80
,
0x02
}},
},
/* 20 fps */
{
{
4
,
559
,
0
,
{
0x02
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x2F
,
0x56
,
0x80
,
0x02
}},
{
4
,
559
,
0
,
{
0x02
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x2F
,
0x56
,
0x80
,
0x02
}},
{
4
,
559
,
0
,
{
0x02
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x2F
,
0x56
,
0x80
,
0x02
}},
{
4
,
559
,
0
,
{
0x02
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x2F
,
0x56
,
0x80
,
0x02
}},
},
/* 25 fps */
{
{
5
,
659
,
0
,
{
0x01
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x93
,
0x46
,
0x80
,
0x02
}},
{
5
,
659
,
0
,
{
0x01
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x93
,
0x46
,
0x80
,
0x02
}},
{
5
,
659
,
0
,
{
0x01
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x93
,
0x46
,
0x80
,
0x02
}},
{
5
,
659
,
0
,
{
0x01
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x93
,
0x46
,
0x80
,
0x02
}},
},
/* 30 fps */
{
{
7
,
838
,
0
,
{
0x00
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x46
,
0x3B
,
0x80
,
0x02
}},
{
7
,
838
,
0
,
{
0x00
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x46
,
0x3B
,
0x80
,
0x02
}},
{
7
,
838
,
0
,
{
0x00
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x46
,
0x3B
,
0x80
,
0x02
}},
{
7
,
838
,
0
,
{
0x00
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x13
,
0x00
,
0x46
,
0x3B
,
0x80
,
0x02
}},
},
},
/* QSIF */
{
/* 5 fps */
{
{
1
,
146
,
0
,
{
0x2D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0xFC
,
0xC0
,
0x02
}},
{
1
,
146
,
0
,
{
0x2D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0xFC
,
0xC0
,
0x02
}},
{
1
,
146
,
0
,
{
0x2D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0xFC
,
0xC0
,
0x02
}},
{
1
,
146
,
0
,
{
0x2D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x92
,
0xFC
,
0xC0
,
0x02
}},
},
/* 10 fps */
{
{
2
,
291
,
0
,
{
0x2C
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
191
,
630
,
{
0x2C
,
0xF4
,
0x05
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xBF
,
0xF4
,
0xC0
,
0x02
}},
{
1
,
191
,
630
,
{
0x2C
,
0xF4
,
0x05
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xBF
,
0xF4
,
0xC0
,
0x02
}},
{
1
,
191
,
630
,
{
0x2C
,
0xF4
,
0x05
,
0x13
,
0xA9
,
0x12
,
0xE1
,
0x17
,
0x08
,
0xBF
,
0xF4
,
0xC0
,
0x02
}},
},
/* 15 fps */
{
{
3
,
437
,
0
,
{
0x2B
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0xB5
,
0x6D
,
0xC0
,
0x02
}},
{
2
,
291
,
640
,
{
0x2B
,
0xF4
,
0x05
,
0x13
,
0xF7
,
0x13
,
0x2F
,
0x13
,
0x08
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
{
2
,
291
,
640
,
{
0x2B
,
0xF4
,
0x05
,
0x13
,
0xF7
,
0x13
,
0x2F
,
0x13
,
0x08
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
191
,
420
,
{
0x2B
,
0xF4
,
0x0D
,
0x0D
,
0x1B
,
0x0C
,
0x53
,
0x1E
,
0x08
,
0xBF
,
0xF4
,
0xC0
,
0x02
}},
},
/* 20 fps */
{
{
4
,
588
,
0
,
{
0x2A
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x4C
,
0x52
,
0xC0
,
0x02
}},
{
3
,
447
,
730
,
{
0x2A
,
0xF4
,
0x05
,
0x16
,
0xC9
,
0x16
,
0x01
,
0x0E
,
0x18
,
0xBF
,
0x69
,
0xC0
,
0x02
}},
{
2
,
292
,
476
,
{
0x2A
,
0xF4
,
0x0D
,
0x0E
,
0xD8
,
0x0E
,
0x10
,
0x19
,
0x18
,
0x24
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
192
,
312
,
{
0x2A
,
0xF4
,
0x1D
,
0x09
,
0xB3
,
0x08
,
0xEB
,
0x1E
,
0x18
,
0xC0
,
0xF4
,
0xC0
,
0x02
}},
},
/* 25 fps */
{
{
5
,
703
,
0
,
{
0x29
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0xBF
,
0x42
,
0xC0
,
0x02
}},
{
3
,
447
,
610
,
{
0x29
,
0xF4
,
0x05
,
0x13
,
0x0B
,
0x12
,
0x43
,
0x14
,
0x18
,
0xBF
,
0x69
,
0xC0
,
0x02
}},
{
2
,
292
,
398
,
{
0x29
,
0xF4
,
0x0D
,
0x0C
,
0x6C
,
0x0B
,
0xA4
,
0x1E
,
0x18
,
0x24
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
192
,
262
,
{
0x29
,
0xF4
,
0x25
,
0x08
,
0x23
,
0x07
,
0x5B
,
0x1E
,
0x18
,
0xC0
,
0xF4
,
0xC0
,
0x02
}},
},
/* 30 fps */
{
{
8
,
873
,
0
,
{
0x28
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x18
,
0x00
,
0x69
,
0x37
,
0xC0
,
0x02
}},
{
5
,
704
,
774
,
{
0x28
,
0xF4
,
0x05
,
0x18
,
0x21
,
0x17
,
0x59
,
0x0F
,
0x18
,
0xC0
,
0x42
,
0xC0
,
0x02
}},
{
3
,
448
,
492
,
{
0x28
,
0xF4
,
0x05
,
0x0F
,
0x5D
,
0x0E
,
0x95
,
0x15
,
0x18
,
0xC0
,
0x69
,
0xC0
,
0x02
}},
{
2
,
291
,
320
,
{
0x28
,
0xF4
,
0x1D
,
0x09
,
0xFB
,
0x09
,
0x33
,
0x1E
,
0x18
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
},
},
/* QCIF */
{
/* 5 fps */
{
{
1
,
193
,
0
,
{
0x0D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0xC1
,
0xF4
,
0xC0
,
0x02
}},
{
1
,
193
,
0
,
{
0x0D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0xC1
,
0xF4
,
0xC0
,
0x02
}},
{
1
,
193
,
0
,
{
0x0D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0xC1
,
0xF4
,
0xC0
,
0x02
}},
{
1
,
193
,
0
,
{
0x0D
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0xC1
,
0xF4
,
0xC0
,
0x02
}},
},
/* 10 fps */
{
{
3
,
385
,
0
,
{
0x0C
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0x81
,
0x79
,
0xC0
,
0x02
}},
{
2
,
291
,
800
,
{
0x0C
,
0xF4
,
0x05
,
0x18
,
0xF4
,
0x18
,
0x18
,
0x11
,
0x08
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
{
2
,
291
,
800
,
{
0x0C
,
0xF4
,
0x05
,
0x18
,
0xF4
,
0x18
,
0x18
,
0x11
,
0x08
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
194
,
532
,
{
0x0C
,
0xF4
,
0x05
,
0x10
,
0x9A
,
0x0F
,
0xBE
,
0x1B
,
0x08
,
0xC2
,
0xF0
,
0xC0
,
0x02
}},
},
/* 15 fps */
{
{
4
,
577
,
0
,
{
0x0B
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0x41
,
0x52
,
0xC0
,
0x02
}},
{
3
,
447
,
818
,
{
0x0B
,
0xF4
,
0x05
,
0x19
,
0x89
,
0x18
,
0xAD
,
0x0F
,
0x10
,
0xBF
,
0x69
,
0xC0
,
0x02
}},
{
2
,
292
,
534
,
{
0x0B
,
0xF4
,
0x05
,
0x10
,
0xA3
,
0x0F
,
0xC7
,
0x19
,
0x10
,
0x24
,
0xA1
,
0xC0
,
0x02
}},
{
1
,
195
,
356
,
{
0x0B
,
0xF4
,
0x15
,
0x0B
,
0x11
,
0x0A
,
0x35
,
0x1E
,
0x10
,
0xC3
,
0xF0
,
0xC0
,
0x02
}},
},
/* 20 fps */
{
{
6
,
776
,
0
,
{
0x0A
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0x08
,
0x3F
,
0xC0
,
0x02
}},
{
4
,
591
,
804
,
{
0x0A
,
0xF4
,
0x05
,
0x19
,
0x1E
,
0x18
,
0x42
,
0x0F
,
0x18
,
0x4F
,
0x4E
,
0xC0
,
0x02
}},
{
3
,
447
,
608
,
{
0x0A
,
0xF4
,
0x05
,
0x12
,
0xFD
,
0x12
,
0x21
,
0x15
,
0x18
,
0xBF
,
0x69
,
0xC0
,
0x02
}},
{
2
,
291
,
396
,
{
0x0A
,
0xF4
,
0x15
,
0x0C
,
0x5E
,
0x0B
,
0x82
,
0x1E
,
0x18
,
0x23
,
0xA1
,
0xC0
,
0x02
}},
},
/* 25 fps */
{
{
9
,
928
,
0
,
{
0x09
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x12
,
0x00
,
0xA0
,
0x33
,
0xC0
,
0x02
}},
{
5
,
703
,
800
,
{
0x09
,
0xF4
,
0x05
,
0x18
,
0xF4
,
0x18
,
0x18
,
0x10
,
0x18
,
0xBF
,
0x42
,
0xC0
,
0x02
}},
{
3
,
447
,
508
,
{
0x09
,
0xF4
,
0x0D
,
0x0F
,
0xD2
,
0x0E
,
0xF6
,
0x1B
,
0x18
,
0xBF
,
0x69
,
0xC0
,
0x02
}},
{
2
,
292
,
332
,
{
0x09
,
0xF4
,
0x1D
,
0x0A
,
0x5A
,
0x09
,
0x7E
,
0x1E
,
0x18
,
0x24
,
0xA1
,
0xC0
,
0x02
}},
},
/* 30 fps */
{
{
0
,
},
{
9
,
956
,
876
,
{
0x08
,
0xF4
,
0x05
,
0x1B
,
0x58
,
0x1A
,
0x7C
,
0x0E
,
0x20
,
0xBC
,
0x33
,
0x10
,
0x02
}},
{
4
,
592
,
542
,
{
0x08
,
0xF4
,
0x05
,
0x10
,
0xE4
,
0x10
,
0x08
,
0x17
,
0x20
,
0x50
,
0x4E
,
0x10
,
0x02
}},
{
2
,
291
,
266
,
{
0x08
,
0xF4
,
0x25
,
0x08
,
0x48
,
0x07
,
0x6C
,
0x1E
,
0x20
,
0x23
,
0xA1
,
0x10
,
0x02
}},
},
},
/* SIF */
{
/* 5 fps */
{
{
4
,
582
,
0
,
{
0x35
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x04
,
0x00
,
0x46
,
0x52
,
0x60
,
0x02
}},
{
3
,
387
,
1276
,
{
0x35
,
0xF4
,
0x05
,
0x27
,
0xD8
,
0x26
,
0x48
,
0x03
,
0x10
,
0x83
,
0x79
,
0x60
,
0x02
}},
{
2
,
291
,
960
,
{
0x35
,
0xF4
,
0x0D
,
0x1D
,
0xF2
,
0x1C
,
0x62
,
0x04
,
0x10
,
0x23
,
0xA1
,
0x60
,
0x02
}},
{
1
,
191
,
630
,
{
0x35
,
0xF4
,
0x1D
,
0x13
,
0xA9
,
0x12
,
0x19
,
0x05
,
0x08
,
0xBF
,
0xF4
,
0x60
,
0x02
}},
},
/* 10 fps */
{
{
0
,
},
{
6
,
775
,
1278
,
{
0x34
,
0xF4
,
0x05
,
0x27
,
0xE8
,
0x26
,
0x58
,
0x05
,
0x30
,
0x07
,
0x3F
,
0x10
,
0x02
}},
{
3
,
447
,
736
,
{
0x34
,
0xF4
,
0x15
,
0x16
,
0xFB
,
0x15
,
0x6B
,
0x05
,
0x18
,
0xBF
,
0x69
,
0x10
,
0x02
}},
{
2
,
291
,
480
,
{
0x34
,
0xF4
,
0x2D
,
0x0E
,
0xF9
,
0x0D
,
0x69
,
0x09
,
0x18
,
0x23
,
0xA1
,
0x10
,
0x02
}},
},
/* 15 fps */
{
{
0
,
},
{
9
,
955
,
1050
,
{
0x33
,
0xF4
,
0x05
,
0x20
,
0xCF
,
0x1F
,
0x3F
,
0x06
,
0x48
,
0xBB
,
0x33
,
0x10
,
0x02
}},
{
4
,
591
,
650
,
{
0x33
,
0xF4
,
0x15
,
0x14
,
0x44
,
0x12
,
0xB4
,
0x08
,
0x30
,
0x4F
,
0x4E
,
0x10
,
0x02
}},
{
3
,
448
,
492
,
{
0x33
,
0xF4
,
0x25
,
0x0F
,
0x52
,
0x0D
,
0xC2
,
0x09
,
0x28
,
0xC0
,
0x69
,
0x10
,
0x02
}},
},
/* 20 fps */
{
{
0
,
},
{
9
,
958
,
782
,
{
0x32
,
0xF4
,
0x0D
,
0x18
,
0x6A
,
0x16
,
0xDA
,
0x0B
,
0x58
,
0xBE
,
0x33
,
0xD0
,
0x02
}},
{
5
,
703
,
574
,
{
0x32
,
0xF4
,
0x1D
,
0x11
,
0xE7
,
0x10
,
0x57
,
0x0B
,
0x40
,
0xBF
,
0x42
,
0xD0
,
0x02
}},
{
3
,
446
,
364
,
{
0x32
,
0xF4
,
0x3D
,
0x0B
,
0x5C
,
0x09
,
0xCC
,
0x0E
,
0x30
,
0xBE
,
0x69
,
0xD0
,
0x02
}},
},
/* 25 fps */
{
{
0
,
},
{
9
,
958
,
654
,
{
0x31
,
0xF4
,
0x15
,
0x14
,
0x66
,
0x12
,
0xD6
,
0x0B
,
0x50
,
0xBE
,
0x33
,
0x90
,
0x02
}},
{
6
,
776
,
530
,
{
0x31
,
0xF4
,
0x25
,
0x10
,
0x8C
,
0x0E
,
0xFC
,
0x0C
,
0x48
,
0x08
,
0x3F
,
0x90
,
0x02
}},
{
4
,
592
,
404
,
{
0x31
,
0xF4
,
0x35
,
0x0C
,
0x96
,
0x0B
,
0x06
,
0x0B
,
0x38
,
0x50
,
0x4E
,
0x90
,
0x02
}},
},
/* 30 fps */
{
{
0
,
},
{
9
,
957
,
526
,
{
0x30
,
0xF4
,
0x25
,
0x10
,
0x68
,
0x0E
,
0xD8
,
0x0D
,
0x58
,
0xBD
,
0x33
,
0x60
,
0x02
}},
{
6
,
775
,
426
,
{
0x30
,
0xF4
,
0x35
,
0x0D
,
0x48
,
0x0B
,
0xB8
,
0x0F
,
0x50
,
0x07
,
0x3F
,
0x60
,
0x02
}},
{
4
,
590
,
324
,
{
0x30
,
0x7A
,
0x4B
,
0x0A
,
0x1C
,
0x08
,
0xB4
,
0x0E
,
0x40
,
0x4E
,
0x52
,
0x60
,
0x02
}},
},
},
/* CIF */
{
/* 5 fps */
{
{
6
,
771
,
0
,
{
0x15
,
0xF4
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
,
0x03
,
0x00
,
0x03
,
0x3F
,
0x80
,
0x02
}},
{
4
,
465
,
1278
,
{
0x15
,
0xF4
,
0x05
,
0x27
,
0xEE
,
0x26
,
0x36
,
0x03
,
0x18
,
0xD1
,
0x65
,
0x80
,
0x02
}},
{
2
,
291
,
800
,
{
0x15
,
0xF4
,
0x15
,
0x18
,
0xF4
,
0x17
,
0x3C
,
0x05
,
0x18
,
0x23
,
0xA1
,
0x80
,
0x02
}},
{
1
,
193
,
528
,
{
0x15
,
0xF4
,
0x2D
,
0x10
,
0x7E
,
0x0E
,
0xC6
,
0x0A
,
0x18
,
0xC1
,
0xF4
,
0x80
,
0x02
}},
},
/* 10 fps */
{
{
0
,
},
{
9
,
932
,
1278
,
{
0x14
,
0xF4
,
0x05
,
0x27
,
0xEE
,
0x26
,
0x36
,
0x04
,
0x30
,
0xA4
,
0x33
,
0x10
,
0x02
}},
{
4
,
591
,
812
,
{
0x14
,
0xF4
,
0x15
,
0x19
,
0x56
,
0x17
,
0x9E
,
0x06
,
0x28
,
0x4F
,
0x4E
,
0x10
,
0x02
}},
{
2
,
291
,
400
,
{
0x14
,
0xF4
,
0x3D
,
0x0C
,
0x7A
,
0x0A
,
0xC2
,
0x0E
,
0x28
,
0x23
,
0xA1
,
0x10
,
0x02
}},
},
/* 15 fps */
{
{
0
,
},
{
9
,
956
,
876
,
{
0x13
,
0xF4
,
0x0D
,
0x1B
,
0x58
,
0x19
,
0xA0
,
0x05
,
0x38
,
0xBC
,
0x33
,
0x60
,
0x02
}},
{
5
,
703
,
644
,
{
0x13
,
0xF4
,
0x1D
,
0x14
,
0x1C
,
0x12
,
0x64
,
0x08
,
0x38
,
0xBF
,
0x42
,
0x60
,
0x02
}},
{
3
,
448
,
410
,
{
0x13
,
0xF4
,
0x3D
,
0x0C
,
0xC4
,
0x0B
,
0x0C
,
0x0E
,
0x38
,
0xC0
,
0x69
,
0x60
,
0x02
}},
},
/* 20 fps */
{
{
0
,
},
{
9
,
956
,
650
,
{
0x12
,
0xF4
,
0x1D
,
0x14
,
0x4A
,
0x12
,
0x92
,
0x09
,
0x48
,
0xBC
,
0x33
,
0x10
,
0x03
}},
{
6
,
776
,
528
,
{
0x12
,
0xF4
,
0x2D
,
0x10
,
0x7E
,
0x0E
,
0xC6
,
0x0A
,
0x40
,
0x08
,
0x3F
,
0x10
,
0x03
}},
{
4
,
591
,
402
,
{
0x12
,
0xF4
,
0x3D
,
0x0C
,
0x8F
,
0x0A
,
0xD7
,
0x0E
,
0x40
,
0x4F
,
0x4E
,
0x10
,
0x03
}},
},
/* 25 fps */
{
{
0
,
},
{
9
,
956
,
544
,
{
0x11
,
0xF4
,
0x25
,
0x10
,
0xF4
,
0x0F
,
0x3C
,
0x0A
,
0x48
,
0xBC
,
0x33
,
0xC0
,
0x02
}},
{
7
,
840
,
478
,
{
0x11
,
0xF4
,
0x2D
,
0x0E
,
0xEB
,
0x0D
,
0x33
,
0x0B
,
0x48
,
0x48
,
0x3B
,
0xC0
,
0x02
}},
{
5
,
703
,
400
,
{
0x11
,
0xF4
,
0x3D
,
0x0C
,
0x7A
,
0x0A
,
0xC2
,
0x0E
,
0x48
,
0xBF
,
0x42
,
0xC0
,
0x02
}},
},
/* 30 fps */
{
{
0
,
},
{
9
,
956
,
438
,
{
0x10
,
0xF4
,
0x35
,
0x0D
,
0xAC
,
0x0B
,
0xF4
,
0x0D
,
0x50
,
0xBC
,
0x33
,
0x10
,
0x02
}},
{
7
,
838
,
384
,
{
0x10
,
0xF4
,
0x45
,
0x0B
,
0xFD
,
0x0A
,
0x45
,
0x0F
,
0x50
,
0x46
,
0x3B
,
0x10
,
0x02
}},
{
6
,
773
,
354
,
{
0x10
,
0x7A
,
0x4B
,
0x0B
,
0x0C
,
0x09
,
0x80
,
0x10
,
0x50
,
0x05
,
0x3F
,
0x10
,
0x02
}},
},
},
/* VGA */
{
/* 5 fps */
{
{
0
,
},
{
6
,
773
,
1272
,
{
0x1D
,
0xF4
,
0x15
,
0x27
,
0xB6
,
0x24
,
0x96
,
0x02
,
0x30
,
0x05
,
0x3F
,
0x10
,
0x02
}},
{
4
,
592
,
976
,
{
0x1D
,
0xF4
,
0x25
,
0x1E
,
0x78
,
0x1B
,
0x58
,
0x03
,
0x30
,
0x50
,
0x4E
,
0x10
,
0x02
}},
{
3
,
448
,
738
,
{
0x1D
,
0xF4
,
0x3D
,
0x17
,
0x0C
,
0x13
,
0xEC
,
0x04
,
0x30
,
0xC0
,
0x69
,
0x10
,
0x02
}},
},
/* 10 fps */
{
{
0
,
},
{
9
,
956
,
788
,
{
0x1C
,
0xF4
,
0x35
,
0x18
,
0x9C
,
0x15
,
0x7C
,
0x03
,
0x48
,
0xBC
,
0x33
,
0x10
,
0x02
}},
{
6
,
776
,
640
,
{
0x1C
,
0x7A
,
0x53
,
0x13
,
0xFC
,
0x11
,
0x2C
,
0x04
,
0x48
,
0x08
,
0x3F
,
0x10
,
0x02
}},
{
4
,
592
,
488
,
{
0x1C
,
0x7A
,
0x6B
,
0x0F
,
0x3C
,
0x0C
,
0x6C
,
0x06
,
0x48
,
0x50
,
0x4E
,
0x10
,
0x02
}},
},
/* 15 fps */
{
{
0
,
},
{
9
,
957
,
526
,
{
0x1B
,
0x7A
,
0x63
,
0x10
,
0x68
,
0x0D
,
0x98
,
0x06
,
0x58
,
0xBD
,
0x33
,
0x80
,
0x02
}},
{
9
,
957
,
526
,
{
0x1B
,
0x7A
,
0x63
,
0x10
,
0x68
,
0x0D
,
0x98
,
0x06
,
0x58
,
0xBD
,
0x33
,
0x80
,
0x02
}},
{
8
,
895
,
492
,
{
0x1B
,
0x7A
,
0x6B
,
0x0F
,
0x5D
,
0x0C
,
0x8D
,
0x06
,
0x58
,
0x7F
,
0x37
,
0x80
,
0x02
}},
},
/* 20 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 25 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
/* 30 fps */
{
{
0
,
},
{
0
,
},
{
0
,
},
{
0
,
},
},
},
};
/*
* 16 versions:
* 2 tables (one for Y, and one for U&V)
* 16 levels of details per tables
* 8 blocs
*/
const
unsigned
int
TimonRomTable
[
16
][
2
][
16
][
8
]
=
{
{
/* version 0 */
{
/* version 0, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000001
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 0, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000001
,
0x00000001
,
0x00000009
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000001
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000001
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 1 */
{
/* version 1, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000001
,
0x00000001
,
0x00000001
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 1, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000001
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000001
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000049
,
0x00000249
,
0x00000009
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00000049
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009252
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 2 */
{
/* version 2, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009252
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00009252
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 2, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000009
,
0x00000049
,
0x00000009
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000049
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009292
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 3 */
{
/* version 3, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00009292
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009292
,
0x0000a49b
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x0001b725
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 3, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000001
,
0x00000000
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00000001
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009252
,
0x00009292
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 4 */
{
/* version 4, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009493
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000124db
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 4, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x0000a49b
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 5 */
{
/* version 5, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00001252
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x0000124a
,
0x00009292
,
0x00009292
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000126dc
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 5, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x00009493
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x000124db
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009493
,
0x000124db
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x000124db
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 6 */
{
/* version 6, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000136e4
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 6, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 7 */
{
/* version 7, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001c96e
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x0002496d
,
0x00025bb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 7, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000136e4
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000126db
,
0x0001b724
,
0x0001b925
,
0x0001b725
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 8 */
{
/* version 8, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009292
,
0x00009493
,
0x0000a49b
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b725
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000126dc
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x00024b76
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x00024b76
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x000136e4
,
0x0001c92d
,
0x00024b76
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000136db
,
0x0001b724
,
0x00024b6d
,
0x0002ddb6
,
0x0002efff
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 8, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000126dc
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b725
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x0001b925
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x0002496d
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 9 */
{
/* version 9, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x0000124a
,
0x00009252
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x00009493
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 9, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000049
,
0x00000009
,
0x00000009
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000049
,
0x00000009
,
0x00000009
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00000249
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009252
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009252
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009493
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000124db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 10 */
{
/* version 10, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x00009493
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x000124db
,
0x000124db
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x0000a49b
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000126dc
,
0x0001b925
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x000136e4
,
0x0002496d
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 10, passes 1 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000049
,
0x00000049
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00000249
,
0x00000049
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x00009252
,
0x0000024a
,
0x00000049
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009493
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009252
,
0x00009492
,
0x00009493
,
0x00001252
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009493
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x00009492
,
0x00009493
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009493
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009252
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 11 */
{
/* version 11, passes 0 */
{
0x00000000
,
0x00000000
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009492
,
0x0000a49b
,
0x0000a49b
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001c924
,
0x0002496d
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 11, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00000249
,
0x00000249
,
0x00000249
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009252
,
0x00009252
,
0x0000024a
,
0x0000024a
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000126dc
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 12 */
{
/* version 12, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x0000a493
,
0x0000a49b
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001b925
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000126db
,
0x0001c924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 12, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009292
,
0x00009492
,
0x00009252
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000124db
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000126dc
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x000136e4
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000126db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 13 */
{
/* version 13, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x00009252
,
0x00009292
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000126dc
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x000136e4
,
0x0001b725
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x0000a49b
,
0x000136e4
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001c96e
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x000136e4
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000136db
,
0x00024924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 13, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x00009492
,
0x00009292
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x0000a49b
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000124db
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000136db
,
0x0001b724
,
0x000124db
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000126dc
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x0001c924
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 14 */
{
/* version 14, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000924a
,
0x00009292
,
0x00009493
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00001249
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x000126dc
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x000136e4
,
0x0001b725
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x0001b92d
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001c92d
,
0x0001c96e
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x0001c92d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b924
,
0x0002496d
,
0x00024b76
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x00024924
,
0x0002db6d
,
0x00036db6
,
0x0002efff
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 14, passes 1 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00001249
,
0x0000124a
,
0x0000124a
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x00009493
,
0x0000a493
,
0x00009292
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x0000a49b
,
0x00001252
,
0x00001252
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000136e4
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000136e4
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x000136e4
,
0x00009493
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x0000a49b
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000124db
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b724
,
0x000136e4
,
0x000126dc
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x0001c924
,
0x0001b724
,
0x000136e4
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
},
{
/* version 15 */
{
/* version 15, passes 0 */
{
0x00000000
,
0x00000000
,
0x00001249
,
0x00009493
,
0x0000a493
,
0x0000a49b
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0001249b
,
0x000126dc
,
0x000136e4
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x000126dc
,
0x0001b724
,
0x0001b725
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0001b92d
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x000136e4
,
0x0001b925
,
0x0001c96e
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000124db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b724
,
0x0001c92d
,
0x0001c96e
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000126db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b924
,
0x0001c92d
,
0x00024b76
,
0x0001c92d
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001b924
,
0x0002496d
,
0x00024b76
,
0x0002496e
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0002496d
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x00024b6d
,
0x00025bb6
,
0x00024b77
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000136db
,
0x0001c924
,
0x00024b6d
,
0x0002ddb6
,
0x00025bbf
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x00024924
,
0x0002db6d
,
0x00036db6
,
0x0002efff
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
},
{
/* version 15, passes 1 */
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000924a
,
0x00009292
,
0x00009292
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x0000a49b
,
0x0000a493
,
0x000124db
,
0x00009292
,
0x00009292
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000124db
,
0x0001b724
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000126dc
,
0x0001b724
,
0x00009493
,
0x00009493
},
{
0x00000000
,
0x00000000
,
0x0000924a
,
0x000124db
,
0x000136e4
,
0x0001b724
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009292
,
0x000136db
,
0x0001b724
,
0x0001b724
,
0x0000a49b
,
0x0000a49b
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001c924
,
0x0001b724
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x00009492
,
0x000136db
,
0x0001c924
,
0x0001b724
,
0x000124db
,
0x000124db
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b724
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b925
,
0x000126dc
,
0x000126dc
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b925
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b925
,
0x000136e4
,
0x000136e4
},
{
0x00000000
,
0x00000000
,
0x0000a492
,
0x000136db
,
0x0001c924
,
0x0001b925
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x000136db
,
0x0001c924
,
0x0001b925
,
0x0001b725
,
0x0001b724
},
{
0x00000000
,
0x00000000
,
0x00012492
,
0x0001b6db
,
0x00024924
,
0x0002496d
,
0x0001b92d
,
0x0001b925
},
{
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
,
0x00000000
}
}
}
};
drivers/usb/media/pwc/pwc-timon.h
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This tables contains entries for the 675/680/690 (Timon) camera, with
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
*/
#ifndef PWC_TIMON_H
#define PWC_TIMON_H
#include "pwc-ioctl.h"
struct
Timon_table_entry
{
char
alternate
;
/* USB alternate interface */
unsigned
short
packetsize
;
/* Normal packet size */
unsigned
short
bandlength
;
/* Bandlength when decompressing */
unsigned
char
mode
[
13
];
/* precomputed mode settings for cam */
};
const
extern
struct
Timon_table_entry
Timon_table
[
PSZ_MAX
][
6
][
4
];
const
extern
unsigned
int
TimonRomTable
[
16
][
2
][
16
][
8
];
#endif
drivers/usb/media/pwc/pwc-uncompress.c
0 → 100644
View file @
ef4333ae
/* Linux driver for Philips webcam
Decompression frontend.
(C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <asm/current.h>
#include <asm/types.h>
#include "pwc.h"
#include "pwc-uncompress.h"
#include "pwc-dec1.h"
#include "pwc-dec23.h"
int
pwc_decompress
(
struct
pwc_device
*
pdev
)
{
struct
pwc_frame_buf
*
fbuf
;
int
n
,
line
,
col
,
stride
;
void
*
yuv
,
*
image
;
u16
*
src
;
u16
*
dsty
,
*
dstu
,
*
dstv
;
if
(
pdev
==
NULL
)
return
-
EFAULT
;
#if defined(__KERNEL__) && defined(PWC_MAGIC)
if
(
pdev
->
magic
!=
PWC_MAGIC
)
{
Err
(
"pwc_decompress(): magic failed.
\n
"
);
return
-
EFAULT
;
}
#endif
fbuf
=
pdev
->
read_frame
;
if
(
fbuf
==
NULL
)
return
-
EFAULT
;
image
=
pdev
->
image_ptr
[
pdev
->
fill_image
];
if
(
!
image
)
return
-
EFAULT
;
yuv
=
fbuf
->
data
+
pdev
->
frame_header_size
;
/* Skip header */
/* Raw format; that's easy... */
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
{
memcpy
(
image
,
yuv
,
pdev
->
frame_size
);
return
0
;
}
if
(
pdev
->
vbandlength
==
0
)
{
/* Uncompressed mode. We copy the data into the output buffer,
using the viewport size (which may be larger than the image
size). Unfortunately we have to do a bit of byte stuffing
to get the desired output format/size.
*/
/*
* We do some byte shuffling here to go from the
* native format to YUV420P.
*/
src
=
(
u16
*
)
yuv
;
n
=
pdev
->
view
.
x
*
pdev
->
view
.
y
;
/* offset in Y plane */
stride
=
pdev
->
view
.
x
*
pdev
->
offset
.
y
+
pdev
->
offset
.
x
;
dsty
=
(
u16
*
)(
image
+
stride
);
/* offsets in U/V planes */
stride
=
pdev
->
view
.
x
*
pdev
->
offset
.
y
/
4
+
pdev
->
offset
.
x
/
2
;
dstu
=
(
u16
*
)(
image
+
n
+
stride
);
dstv
=
(
u16
*
)(
image
+
n
+
n
/
4
+
stride
);
/* increment after each line */
stride
=
(
pdev
->
view
.
x
-
pdev
->
image
.
x
)
/
2
;
/* u16 is 2 bytes */
for
(
line
=
0
;
line
<
pdev
->
image
.
y
;
line
++
)
{
for
(
col
=
0
;
col
<
pdev
->
image
.
x
;
col
+=
4
)
{
*
dsty
++
=
*
src
++
;
*
dsty
++
=
*
src
++
;
if
(
line
&
1
)
*
dstv
++
=
*
src
++
;
else
*
dstu
++
=
*
src
++
;
}
dsty
+=
stride
;
if
(
line
&
1
)
dstv
+=
(
stride
>>
1
);
else
dstu
+=
(
stride
>>
1
);
}
}
else
{
/* Compressed; the decompressor routines will write the data
in planar format immediately.
*/
int
flags
;
flags
=
PWCX_FLAG_PLANAR
;
if
(
pdev
->
vsize
==
PSZ_VGA
&&
pdev
->
vframes
==
5
&&
pdev
->
vsnapshot
)
{
printk
(
KERN_ERR
"pwc: Mode Bayer is not supported for now
\n
"
);
flags
|=
PWCX_FLAG_BAYER
;
return
-
ENXIO
;
/* No such device or address: missing decompressor */
}
switch
(
pdev
->
type
)
{
case
675
:
case
680
:
case
690
:
case
720
:
case
730
:
case
740
:
case
750
:
pwc_dec23_decompress
(
&
pdev
->
image
,
&
pdev
->
view
,
&
pdev
->
offset
,
yuv
,
image
,
flags
,
pdev
->
decompress_data
,
pdev
->
vbandlength
);
break
;
case
645
:
case
646
:
/* TODO & FIXME */
return
-
ENXIO
;
/* No such device or address: missing decompressor */
break
;
}
}
return
0
;
}
drivers/usb/media/pwc/pwc-uncompress.h
0 → 100644
View file @
ef4333ae
/* (C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file is the bridge between the kernel module and the plugin; it
describes the structures and datatypes used in both modules. Any
significant change should be reflected by increasing the
pwc_decompressor_version major number.
*/
#ifndef PWC_UNCOMPRESS_H
#define PWC_UNCOMPRESS_H
#include <linux/config.h>
#include "pwc-ioctl.h"
/* from pwc-dec.h */
#define PWCX_FLAG_PLANAR 0x0001
/* */
#endif
drivers/usb/media/pwc/pwc.h
0 → 100644
View file @
ef4333ae
/* (C) 1999-2003 Nemosoft Unv.
(C) 2004 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PWC_H
#define PWC_H
#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/spinlock.h>
#include <linux/videodev.h>
#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <asm/semaphore.h>
#include <asm/errno.h>
#include "pwc-uncompress.h"
#include "pwc-ioctl.h"
/* Defines and structures for the Philips webcam */
/* Used for checking memory corruption/pointer validation */
#define PWC_MAGIC 0x89DC10ABUL
#undef PWC_MAGIC
/* Turn some debugging options on/off */
#define PWC_DEBUG 0
/* Trace certain actions in the driver */
#define TRACE_MODULE 0x0001
#define TRACE_PROBE 0x0002
#define TRACE_OPEN 0x0004
#define TRACE_READ 0x0008
#define TRACE_MEMORY 0x0010
#define TRACE_FLOW 0x0020
#define TRACE_SIZE 0x0040
#define TRACE_PWCX 0x0080
#define TRACE_SEQUENCE 0x1000
#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
#define Info(A...) printk(KERN_INFO PWC_NAME " " A)
#define Err(A...) printk(KERN_ERR PWC_NAME " " A)
/* Defines for ToUCam cameras */
#define TOUCAM_HEADER_SIZE 8
#define TOUCAM_TRAILER_SIZE 4
#define FEATURE_MOTOR_PANTILT 0x0001
/* Version block */
#define PWC_MAJOR 9
#define PWC_MINOR 0
#define PWC_VERSION "9.0.2-unofficial"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
#define PWC_INT_PIPE 0
/* Ignore errors in the first N frames, to allow for startup delays */
#define FRAME_LOWMARK 5
/* Size and number of buffers for the ISO pipe. */
#define MAX_ISO_BUFS 2
#define ISO_FRAMES_PER_DESC 10
#define ISO_MAX_FRAME_SIZE 960
#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
/* Frame buffers: contains compressed or uncompressed video data. */
#define MAX_FRAMES 5
/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
/* Absolute maximum number of buffers available for mmap() */
#define MAX_IMAGES 10
/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
struct
pwc_iso_buf
{
void
*
data
;
int
length
;
int
read
;
struct
urb
*
urb
;
};
/* intermediate buffers with raw data from the USB cam */
struct
pwc_frame_buf
{
void
*
data
;
volatile
int
filled
;
/* number of bytes filled */
struct
pwc_frame_buf
*
next
;
/* list */
#if PWC_DEBUG
int
sequence
;
/* Sequence number */
#endif
};
struct
pwc_device
{
struct
video_device
*
vdev
;
#ifdef PWC_MAGIC
int
magic
;
#endif
/* Pointer to our usb_device */
struct
usb_device
*
udev
;
int
type
;
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int
release
;
/* release number */
int
features
;
/* feature bits */
char
serial
[
30
];
/* serial number (string) */
int
error_status
;
/* set when something goes wrong with the cam (unplugged, USB errors) */
int
usb_init
;
/* set when the cam has been initialized over USB */
/*** Video data ***/
int
vopen
;
/* flag */
int
vendpoint
;
/* video isoc endpoint */
int
vcinterface
;
/* video control interface */
int
valternate
;
/* alternate interface needed */
int
vframes
,
vsize
;
/* frames-per-second & size (see PSZ_*) */
int
vpalette
;
/* palette: 420P, RAW or RGBBAYER */
int
vframe_count
;
/* received frames */
int
vframes_dumped
;
/* counter for dumped frames */
int
vframes_error
;
/* frames received in error */
int
vmax_packet_size
;
/* USB maxpacket size */
int
vlast_packet_size
;
/* for frame synchronisation */
int
visoc_errors
;
/* number of contiguous ISOC errors */
int
vcompression
;
/* desired compression factor */
int
vbandlength
;
/* compressed band length; 0 is uncompressed */
char
vsnapshot
;
/* snapshot mode */
char
vsync
;
/* used by isoc handler */
char
vmirror
;
/* for ToUCaM series */
int
cmd_len
;
unsigned
char
cmd_buf
[
13
];
/* The image acquisition requires 3 to 4 steps:
1. data is gathered in short packets from the USB controller
2. data is synchronized and packed into a frame buffer
3a. in case data is compressed, decompress it directly into image buffer
3b. in case data is uncompressed, copy into image buffer with viewport
4. data is transferred to the user process
Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
We have in effect a back-to-back-double-buffer system.
*/
/* 1: isoc */
struct
pwc_iso_buf
sbuf
[
MAX_ISO_BUFS
];
char
iso_init
;
/* 2: frame */
struct
pwc_frame_buf
*
fbuf
;
/* all frames */
struct
pwc_frame_buf
*
empty_frames
,
*
empty_frames_tail
;
/* all empty frames */
struct
pwc_frame_buf
*
full_frames
,
*
full_frames_tail
;
/* all filled frames */
struct
pwc_frame_buf
*
fill_frame
;
/* frame currently being filled */
struct
pwc_frame_buf
*
read_frame
;
/* frame currently read by user process */
int
frame_header_size
,
frame_trailer_size
;
int
frame_size
;
int
frame_total_size
;
/* including header & trailer */
int
drop_frames
;
#if PWC_DEBUG
int
sequence
;
/* Debugging aid */
#endif
/* 3: decompression */
struct
pwc_decompressor
*
decompressor
;
/* function block with decompression routines */
void
*
decompress_data
;
/* private data for decompression engine */
/* 4: image */
/* We have an 'image' and a 'view', where 'image' is the fixed-size image
as delivered by the camera, and 'view' is the size requested by the
program. The camera image is centered in this viewport, laced with
a gray or black border. view_min <= image <= view <= view_max;
*/
int
image_mask
;
/* bitmask of supported sizes */
struct
pwc_coord
view_min
,
view_max
;
/* minimum and maximum viewable sizes */
struct
pwc_coord
abs_max
;
/* maximum supported size with compression */
struct
pwc_coord
image
,
view
;
/* image and viewport size */
struct
pwc_coord
offset
;
/* offset within the viewport */
void
*
image_data
;
/* total buffer, which is subdivided into ... */
void
*
image_ptr
[
MAX_IMAGES
];
/* ...several images... */
int
fill_image
;
/* ...which are rotated. */
int
len_per_image
;
/* length per image */
int
image_read_pos
;
/* In case we read data in pieces, keep track of were we are in the imagebuffer */
int
image_used
[
MAX_IMAGES
];
/* For MCAPTURE and SYNC */
struct
semaphore
modlock
;
/* to prevent races in video_open(), etc */
spinlock_t
ptrlock
;
/* for manipulating the buffer pointers */
/*** motorized pan/tilt feature */
struct
pwc_mpt_range
angle_range
;
int
pan_angle
;
/* in degrees * 100 */
int
tilt_angle
;
/* absolute angle; 0,0 is home position */
/*** Misc. data ***/
wait_queue_head_t
frameq
;
/* When waiting for a frame to finish... */
#if PWC_INT_PIPE
void
*
usb_int_handler
;
/* for the interrupt endpoint */
#endif
};
#ifdef __cplusplus
extern
"C"
{
#endif
/* Global variables */
extern
int
pwc_trace
;
extern
int
pwc_preferred_compression
;
/** functions in pwc-if.c */
int
pwc_try_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
new_fps
,
int
new_compression
,
int
new_snapshot
);
/** Functions in pwc-misc.c */
/* sizes in pixels */
extern
struct
pwc_coord
pwc_image_sizes
[
PSZ_MAX
];
int
pwc_decode_size
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
);
void
pwc_construct
(
struct
pwc_device
*
pdev
);
/** Functions in pwc-ctrl.c */
/* Request a certain video mode. Returns < 0 if not possible */
extern
int
pwc_set_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
frames
,
int
compression
,
int
snapshot
);
/* Calculate the number of bytes per image (not frame) */
extern
void
pwc_set_image_buffer_size
(
struct
pwc_device
*
pdev
);
/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
extern
int
pwc_get_brightness
(
struct
pwc_device
*
pdev
);
extern
int
pwc_set_brightness
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_get_contrast
(
struct
pwc_device
*
pdev
);
extern
int
pwc_set_contrast
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_get_gamma
(
struct
pwc_device
*
pdev
);
extern
int
pwc_set_gamma
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_get_saturation
(
struct
pwc_device
*
pdev
);
extern
int
pwc_set_saturation
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_set_leds
(
struct
pwc_device
*
pdev
,
int
on_value
,
int
off_value
);
extern
int
pwc_get_leds
(
struct
pwc_device
*
pdev
,
int
*
on_value
,
int
*
off_value
);
extern
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
,
int
*
sensor
);
/* Power down or up the camera; not supported by all models */
extern
int
pwc_camera_power
(
struct
pwc_device
*
pdev
,
int
power
);
/* Private ioctl()s; see pwc-ioctl.h */
extern
int
pwc_ioctl
(
struct
pwc_device
*
pdev
,
unsigned
int
cmd
,
void
*
arg
);
/** pwc-uncompress.c */
/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
extern
int
pwc_decompress
(
struct
pwc_device
*
pdev
);
#ifdef __cplusplus
}
#endif
#endif
include/linux/pci_ids.h
View file @
ef4333ae
...
@@ -352,10 +352,21 @@
...
@@ -352,10 +352,21 @@
#define PCI_DEVICE_ID_ATI_RS300_133 0x5831
#define PCI_DEVICE_ID_ATI_RS300_133 0x5831
#define PCI_DEVICE_ID_ATI_RS300_166 0x5832
#define PCI_DEVICE_ID_ATI_RS300_166 0x5832
#define PCI_DEVICE_ID_ATI_RS300_200 0x5833
#define PCI_DEVICE_ID_ATI_RS300_200 0x5833
#define PCI_DEVICE_ID_ATI_RS350_100 0x7830
#define PCI_DEVICE_ID_ATI_RS350_133 0x7831
#define PCI_DEVICE_ID_ATI_RS350_166 0x7832
#define PCI_DEVICE_ID_ATI_RS350_200 0x7833
#define PCI_DEVICE_ID_ATI_RS400_100 0x5a30
#define PCI_DEVICE_ID_ATI_RS400_133 0x5a31
#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32
#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33
#define PCI_DEVICE_ID_ATI_RS480 0x5950
/* ATI IXP Chipset */
/* ATI IXP Chipset */
#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349
#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349
#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369
#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369
#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e
#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376
#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376
#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_DEVICE_ID_VLSI_82C592 0x0005
#define PCI_DEVICE_ID_VLSI_82C592 0x0005
...
@@ -1501,6 +1512,9 @@
...
@@ -1501,6 +1512,9 @@
#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040
#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040
#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
#define PCI_DEVICE_ID_ARTOP_8060 0x8060
#define PCI_DEVICE_ID_ARTOP_8060 0x8060
#define PCI_DEVICE_ID_ARTOP_AEC67160 0x8080
#define PCI_DEVICE_ID_ARTOP_AEC67160_2 0x8081
#define PCI_DEVICE_ID_ARTOP_AEC67162 0x808a
#define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
...
@@ -1613,6 +1627,10 @@
...
@@ -1613,6 +1627,10 @@
#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320
#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320
#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321
#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321
/* Allied Telesyn */
#define PCI_VENDOR_ID_AT 0x1259
#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703
#define PCI_VENDOR_ID_ESSENTIAL 0x120f
#define PCI_VENDOR_ID_ESSENTIAL 0x120f
#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001
#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001
...
...
include/linux/stallion.h
View file @
ef4333ae
...
@@ -126,7 +126,7 @@ typedef struct stlbrd {
...
@@ -126,7 +126,7 @@ typedef struct stlbrd {
int
nrbnks
;
int
nrbnks
;
int
irq
;
int
irq
;
int
irqtype
;
int
irqtype
;
void
(
*
isr
)(
struct
stlbrd
*
brdp
);
int
(
*
isr
)(
struct
stlbrd
*
brdp
);
unsigned
int
ioaddr1
;
unsigned
int
ioaddr1
;
unsigned
int
ioaddr2
;
unsigned
int
ioaddr2
;
unsigned
int
iosize1
;
unsigned
int
iosize1
;
...
...
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