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
cc6120c6
Commit
cc6120c6
authored
Sep 12, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
parents
7b799bc8
f5e09b7c
Changes
43
Show whitespace changes
Inline
Side-by-side
Showing
43 changed files
with
5277 additions
and
348 deletions
+5277
-348
Documentation/input/appletouch.txt
Documentation/input/appletouch.txt
+84
-0
Documentation/usb/proc_usb_info.txt
Documentation/usb/proc_usb_info.txt
+8
-5
drivers/usb/class/audio.c
drivers/usb/class/audio.c
+8
-4
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+1
-2
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+6
-5
drivers/usb/gadget/inode.c
drivers/usb/gadget/inode.c
+1
-0
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+24
-4
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-hub.c
+16
-11
drivers/usb/host/ehci.h
drivers/usb/host/ehci.h
+1
-0
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-dbg.c
+4
-5
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hcd.c
+8
-6
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-hub.c
+11
-11
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-pxa27x.c
+10
-38
drivers/usb/host/ohci.h
drivers/usb/host/ohci.h
+1
-0
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+22
-40
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hcd.h
+3
-8
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-hub.c
+6
-5
drivers/usb/host/uhci-q.c
drivers/usb/host/uhci-q.c
+1
-1
drivers/usb/input/Kconfig
drivers/usb/input/Kconfig
+20
-0
drivers/usb/input/Makefile
drivers/usb/input/Makefile
+1
-0
drivers/usb/input/appletouch.c
drivers/usb/input/appletouch.c
+469
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+0
-2
drivers/usb/misc/sisusbvga/Kconfig
drivers/usb/misc/sisusbvga/Kconfig
+37
-5
drivers/usb/misc/sisusbvga/Makefile
drivers/usb/misc/sisusbvga/Makefile
+3
-1
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/sisusbvga/sisusb.c
+426
-37
drivers/usb/misc/sisusbvga/sisusb.h
drivers/usb/misc/sisusbvga/sisusb.h
+61
-12
drivers/usb/misc/sisusbvga/sisusb_con.c
drivers/usb/misc/sisusbvga/sisusb_con.c
+1658
-0
drivers/usb/misc/sisusbvga/sisusb_init.c
drivers/usb/misc/sisusbvga/sisusb_init.c
+1047
-0
drivers/usb/misc/sisusbvga/sisusb_init.h
drivers/usb/misc/sisusbvga/sisusb_init.h
+830
-0
drivers/usb/misc/sisusbvga/sisusb_struct.h
drivers/usb/misc/sisusbvga/sisusb_struct.h
+169
-0
drivers/usb/misc/uss720.c
drivers/usb/misc/uss720.c
+270
-123
drivers/usb/mon/mon_text.c
drivers/usb/mon/mon_text.c
+1
-1
drivers/usb/serial/cp2101.c
drivers/usb/serial/cp2101.c
+4
-1
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/cypress_m8.c
+1
-2
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+1
-1
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.c
+2
-2
drivers/usb/serial/pl2303.h
drivers/usb/serial/pl2303.h
+4
-0
drivers/usb/storage/scsiglue.c
drivers/usb/storage/scsiglue.c
+9
-11
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+35
-0
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+8
-3
drivers/video/console/Kconfig
drivers/video/console/Kconfig
+1
-1
drivers/video/console/Makefile
drivers/video/console/Makefile
+4
-0
include/linux/usbdevice_fs.h
include/linux/usbdevice_fs.h
+1
-1
No files found.
Documentation/input/appletouch.txt
0 → 100644
View file @
cc6120c6
Apple Touchpad Driver (appletouch)
----------------------------------
Copyright (C) 2005 Stelian Pop <stelian@popies.net>
appletouch is a Linux kernel driver for the USB touchpad found on post
February 2005 Apple Alu Powerbooks.
This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
been improved in some areas:
* appletouch is a full kernel driver, no userspace program is necessary
* appletouch can be interfaced with the synaptics X11 driver, in order
to have touchpad acceleration, scrolling, etc.
Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
Frank Arnold for further improvements, and Alex Harper for some additional
information about the inner workings of the touchpad sensors.
Usage:
------
In order to use the touchpad in the basic mode, compile the driver and load
the module. A new input device will be detected and you will be able to read
the mouse data from /dev/input/mice (using gpm, or X11).
In X11, you can configure the touchpad to use the synaptics X11 driver, which
will give additional functionalities, like acceleration, scrolling, 2 finger
tap for middle button mouse emulation, 3 finger tap for right button mouse
emulation, etc. In order to do this, make sure you're using a recent version of
the synaptics driver (tested with 0.14.2, available from [2]), and configure a
new input device in your X11 configuration file (take a look below for an
example). For additional configuration, see the synaptics driver documentation.
Section "InputDevice"
Identifier "Synaptics Touchpad"
Driver "synaptics"
Option "SendCoreEvents" "true"
Option "Device" "/dev/input/mice"
Option "Protocol" "auto-dev"
Option "LeftEdge" "0"
Option "RightEdge" "850"
Option "TopEdge" "0"
Option "BottomEdge" "645"
Option "MinSpeed" "0.4"
Option "MaxSpeed" "1"
Option "AccelFactor" "0.02"
Option "FingerLow" "0"
Option "FingerHigh" "30"
Option "MaxTapMove" "20"
Option "MaxTapTime" "100"
Option "HorizScrollDelta" "0"
Option "VertScrollDelta" "30"
Option "SHMConfig" "on"
EndSection
Section "ServerLayout"
...
InputDevice "Mouse"
InputDevice "Synaptics Touchpad"
...
EndSection
Fuzz problems:
--------------
The touchpad sensors are very sensitive to heat, and will generate a lot of
noise when the temperature changes. This is especially true when you power-on
the laptop for the first time.
The appletouch driver tries to handle this noise and auto adapt itself, but it
is not perfect. If finger movements are not recognized anymore, try reloading
the driver.
You can activate debugging using the 'debug' module parameter. A value of 0
deactivates any debugging, 1 activates tracing of invalid samples, 2 activates
full tracing (each sample is being traced):
modprobe appletouch debug=1
or
echo "1" > /sys/module/appletouch/parameters/debug
Links:
------
[1]: http://johannes.sipsolutions.net/PowerBook/touchpad/
[2]: http://web.telia.com/~u89404340/touchpad/index.html
Documentation/usb/proc_usb_info.txt
View file @
cc6120c6
...
...
@@ -297,18 +297,21 @@ S: SerialNumber=dce0
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0451 ProdID=1446 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b4 ProdID=0001 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0565 ProdID=0001 Rev= 1.08
...
...
drivers/usb/class/audio.c
View file @
cc6120c6
...
...
@@ -631,8 +631,10 @@ static void usbin_stop(struct usb_audiodev *as)
i
=
u
->
flags
;
spin_unlock_irqrestore
(
&
as
->
lock
,
flags
);
while
(
i
&
(
FLG_URB0RUNNING
|
FLG_URB1RUNNING
|
FLG_SYNC0RUNNING
|
FLG_SYNC1RUNNING
))
{
set_current_state
(
notkilled
?
TASK_INTERRUPTIBLE
:
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
if
(
notkilled
)
schedule_timeout_interruptible
(
1
);
else
schedule_timeout_uninterruptible
(
1
);
spin_lock_irqsave
(
&
as
->
lock
,
flags
);
i
=
u
->
flags
;
spin_unlock_irqrestore
(
&
as
->
lock
,
flags
);
...
...
@@ -1102,8 +1104,10 @@ static void usbout_stop(struct usb_audiodev *as)
i
=
u
->
flags
;
spin_unlock_irqrestore
(
&
as
->
lock
,
flags
);
while
(
i
&
(
FLG_URB0RUNNING
|
FLG_URB1RUNNING
|
FLG_SYNC0RUNNING
|
FLG_SYNC1RUNNING
))
{
set_current_state
(
notkilled
?
TASK_INTERRUPTIBLE
:
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
if
(
notkilled
)
schedule_timeout_interruptible
(
1
);
else
schedule_timeout_uninterruptible
(
1
);
spin_lock_irqsave
(
&
as
->
lock
,
flags
);
i
=
u
->
flags
;
spin_unlock_irqrestore
(
&
as
->
lock
,
flags
);
...
...
drivers/usb/core/hcd.c
View file @
cc6120c6
...
...
@@ -1606,7 +1606,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
return
IRQ_NONE
;
hcd
->
saw_irq
=
1
;
if
(
hcd
->
state
!=
start
&&
hcd
->
state
==
HC_STATE_HALT
)
if
(
hcd
->
state
==
HC_STATE_HALT
)
usb_hc_died
(
hcd
);
return
IRQ_HANDLED
;
}
...
...
@@ -1630,7 +1630,6 @@ void usb_hc_died (struct usb_hcd *hcd)
spin_lock_irqsave
(
&
hcd_root_hub_lock
,
flags
);
if
(
hcd
->
rh_registered
)
{
hcd
->
poll_rh
=
0
;
del_timer
(
&
hcd
->
rh_timer
);
/* make khubd clean up old urbs and devices */
usb_set_device_state
(
hcd
->
self
.
root_hub
,
...
...
drivers/usb/core/hub.c
View file @
cc6120c6
...
...
@@ -435,6 +435,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
static
void
hub_power_on
(
struct
usb_hub
*
hub
)
{
int
port1
;
unsigned
pgood_delay
=
hub
->
descriptor
->
bPwrOn2PwrGood
*
2
;
/* if hub supports power switching, enable power on each port */
if
((
hub
->
descriptor
->
wHubCharacteristics
&
HUB_CHAR_LPSM
)
<
2
)
{
...
...
@@ -444,8 +445,8 @@ static void hub_power_on(struct usb_hub *hub)
USB_PORT_FEAT_POWER
);
}
/* Wait
for power to be enabled
*/
msleep
(
hub
->
descriptor
->
bPwrOn2PwrGood
*
2
);
/* Wait
at least 100 msec for power to become stable
*/
msleep
(
max
(
pgood_delay
,
(
unsigned
)
100
)
);
}
static
void
hub_quiesce
(
struct
usb_hub
*
hub
)
...
...
@@ -1460,7 +1461,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
port1
,
status
);
else
{
status
=
hub_port_wait_reset
(
hub
,
port1
,
udev
,
delay
);
if
(
status
)
if
(
status
&&
status
!=
-
ENOTCONN
)
dev_dbg
(
hub
->
intfdev
,
"port_wait_reset: err = %d
\n
"
,
status
);
...
...
@@ -1469,8 +1470,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
/* return on disconnect or reset */
switch
(
status
)
{
case
0
:
/* TRSTRCY = 10 ms */
msleep
(
10
);
/* TRSTRCY = 10 ms
; plus some extra
*/
msleep
(
10
+
40
);
/* FALL THROUGH */
case
-
ENOTCONN
:
case
-
ENODEV
:
...
...
drivers/usb/gadget/inode.c
View file @
cc6120c6
...
...
@@ -483,6 +483,7 @@ ep_release (struct inode *inode, struct file *fd)
data
->
state
=
STATE_EP_DISABLED
;
data
->
desc
.
bDescriptorType
=
0
;
data
->
hs_desc
.
bDescriptorType
=
0
;
usb_ep_disable
(
data
->
ep
);
}
put_ep
(
data
);
return
0
;
...
...
drivers/usb/host/ehci-hcd.c
View file @
cc6120c6
...
...
@@ -400,6 +400,23 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
return
-
EIO
;
}
break
;
case
PCI_VENDOR_ID_NVIDIA
:
/* NVidia reports that certain chips don't handle
* QH, ITD, or SITD addresses above 2GB. (But TD,
* data buffer, and periodic schedule are normal.)
*/
switch
(
pdev
->
device
)
{
case
0x003c
:
/* MCP04 */
case
0x005b
:
/* CK804 */
case
0x00d8
:
/* CK8 */
case
0x00e8
:
/* CK8S */
if
(
pci_set_consistent_dma_mask
(
pdev
,
DMA_31BIT_MASK
)
<
0
)
ehci_warn
(
ehci
,
"can't enable NVidia "
"workaround for >2GB RAM
\n
"
);
break
;
}
break
;
}
/* optional debug port, normally in the first BAR */
...
...
@@ -759,12 +776,16 @@ static int ehci_resume (struct usb_hcd *hcd)
if
(
time_before
(
jiffies
,
ehci
->
next_statechange
))
msleep
(
100
);
/* If any port is suspended, we know we can/must resume the HC. */
/* If any port is suspended (or owned by the companion),
* we know we can/must resume the HC (and mustn't reset it).
*/
for
(
port
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
port
>
0
;
)
{
u32
status
;
port
--
;
status
=
readl
(
&
ehci
->
regs
->
port_status
[
port
]);
if
(
status
&
PORT_SUSPEND
)
{
if
(
!
(
status
&
PORT_POWER
))
continue
;
if
(
status
&
(
PORT_SUSPEND
|
PORT_OWNER
))
{
down
(
&
hcd
->
self
.
root_hub
->
serialize
);
retval
=
ehci_hub_resume
(
hcd
);
up
(
&
hcd
->
self
.
root_hub
->
serialize
);
...
...
@@ -1126,8 +1147,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
case
QH_STATE_UNLINK
:
/* wait for hw to finish? */
idle_timeout:
spin_unlock_irqrestore
(
&
ehci
->
lock
,
flags
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
schedule_timeout_uninterruptible
(
1
);
goto
rescan
;
case
QH_STATE_IDLE
:
/* fully unlinked */
if
(
list_empty
(
&
qh
->
qtd_list
))
{
...
...
drivers/usb/host/ehci-hub.c
View file @
cc6120c6
...
...
@@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* suspend any active/unsuspended ports, maybe allow wakeup */
while
(
port
--
)
{
u32
__iomem
*
reg
=
&
ehci
->
regs
->
port_status
[
port
];
u32
t1
=
readl
(
reg
);
u32
t1
=
readl
(
reg
)
&
~
PORT_RWC_BITS
;
u32
t2
=
t1
;
if
((
t1
&
PORT_PE
)
&&
!
(
t1
&
PORT_OWNER
))
...
...
@@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
i
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
while
(
i
--
)
{
temp
=
readl
(
&
ehci
->
regs
->
port_status
[
i
]);
temp
&=
~
(
PORT_WKOC_E
|
PORT_WKDISC_E
|
PORT_WKCONN_E
);
temp
&=
~
(
PORT_RWC_BITS
|
PORT_WKOC_E
|
PORT_WKDISC_E
|
PORT_WKCONN_E
);
if
(
temp
&
PORT_SUSPEND
)
{
ehci
->
reset_done
[
i
]
=
jiffies
+
msecs_to_jiffies
(
20
);
temp
|=
PORT_RESUME
;
...
...
@@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
temp
=
readl
(
&
ehci
->
regs
->
port_status
[
i
]);
if
((
temp
&
PORT_SUSPEND
)
==
0
)
continue
;
temp
&=
~
PORT_RESUME
;
temp
&=
~
(
PORT_RWC_BITS
|
PORT_RESUME
)
;
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
ehci_vdbg
(
ehci
,
"resumed port %d
\n
"
,
i
+
1
);
}
...
...
@@ -191,6 +192,7 @@ static int check_reset_complete (
// what happens if HCS_N_CC(params) == 0 ?
port_status
|=
PORT_OWNER
;
port_status
&=
~
PORT_RWC_BITS
;
writel
(
port_status
,
&
ehci
->
regs
->
port_status
[
index
]);
}
else
...
...
@@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
if
(
temp
&
PORT_OWNER
)
{
/* don't report this in GetPortStatus */
if
(
temp
&
PORT_CSC
)
{
temp
&=
~
PORT_CSC
;
temp
&=
~
PORT_RWC_BITS
;
temp
|=
PORT_CSC
;
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
}
continue
;
...
...
@@ -343,7 +346,7 @@ static int ehci_hub_control (
&
ehci
->
regs
->
port_status
[
wIndex
]);
break
;
case
USB_PORT_FEAT_C_ENABLE
:
writel
(
temp
|
PORT_PEC
,
writel
((
temp
&
~
PORT_RWC_BITS
)
|
PORT_PEC
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
break
;
case
USB_PORT_FEAT_SUSPEND
:
...
...
@@ -353,7 +356,8 @@ static int ehci_hub_control (
if
((
temp
&
PORT_PE
)
==
0
)
goto
error
;
/* resume signaling for 20 msec */
writel
((
temp
&
~
PORT_WAKE_BITS
)
|
PORT_RESUME
,
temp
&=
~
(
PORT_RWC_BITS
|
PORT_WAKE_BITS
);
writel
(
temp
|
PORT_RESUME
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
ehci
->
reset_done
[
wIndex
]
=
jiffies
+
msecs_to_jiffies
(
20
);
...
...
@@ -364,15 +368,15 @@ static int ehci_hub_control (
break
;
case
USB_PORT_FEAT_POWER
:
if
(
HCS_PPC
(
ehci
->
hcs_params
))
writel
(
temp
&
~
PORT_POWER
,
writel
(
temp
&
~
(
PORT_RWC_BITS
|
PORT_POWER
)
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
break
;
case
USB_PORT_FEAT_C_CONNECTION
:
writel
(
temp
|
PORT_CSC
,
writel
((
temp
&
~
PORT_RWC_BITS
)
|
PORT_CSC
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
break
;
case
USB_PORT_FEAT_C_OVER_CURRENT
:
writel
(
temp
|
PORT_OCC
,
writel
((
temp
&
~
PORT_RWC_BITS
)
|
PORT_OCC
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
break
;
case
USB_PORT_FEAT_C_RESET
:
...
...
@@ -416,7 +420,7 @@ static int ehci_hub_control (
/* stop resume signaling */
temp
=
readl
(
&
ehci
->
regs
->
port_status
[
wIndex
]);
writel
(
temp
&
~
PORT_RESUME
,
writel
(
temp
&
~
(
PORT_RWC_BITS
|
PORT_RESUME
)
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
retval
=
handshake
(
&
ehci
->
regs
->
port_status
[
wIndex
],
...
...
@@ -437,7 +441,7 @@ static int ehci_hub_control (
ehci
->
reset_done
[
wIndex
]
=
0
;
/* force reset to complete */
writel
(
temp
&
~
PORT_RESET
,
writel
(
temp
&
~
(
PORT_RWC_BITS
|
PORT_RESET
)
,
&
ehci
->
regs
->
port_status
[
wIndex
]);
/* REVISIT: some hardware needs 550+ usec to clear
* this bit; seems too long to spin routinely...
...
...
@@ -500,6 +504,7 @@ static int ehci_hub_control (
if
(
temp
&
PORT_OWNER
)
break
;
temp
&=
~
PORT_RWC_BITS
;
switch
(
wValue
)
{
case
USB_PORT_FEAT_SUSPEND
:
if
((
temp
&
PORT_PE
)
==
0
...
...
drivers/usb/host/ehci.h
View file @
cc6120c6
...
...
@@ -263,6 +263,7 @@ struct ehci_regs {
#define PORT_PE (1<<2)
/* port enable */
#define PORT_CSC (1<<1)
/* connect status change */
#define PORT_CONNECT (1<<0)
/* device connected */
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
}
__attribute__
((
packed
));
/* Appendix C, Debug port ... intended for use with special "debug devices"
...
...
drivers/usb/host/ohci-dbg.c
View file @
cc6120c6
...
...
@@ -228,23 +228,22 @@ ohci_dump_roothub (
char
**
next
,
unsigned
*
size
)
{
u32
temp
,
ndp
,
i
;
u32
temp
,
i
;
temp
=
roothub_a
(
controller
);
if
(
temp
==
~
(
u32
)
0
)
return
;
ndp
=
(
temp
&
RH_A_NDP
);
if
(
verbose
)
{
ohci_dbg_sw
(
controller
,
next
,
size
,
"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d
\n
"
,
temp
,
"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d
(%d)
\n
"
,
temp
,
((
temp
&
RH_A_POTPGT
)
>>
24
)
&
0xff
,
(
temp
&
RH_A_NOCP
)
?
" NOCP"
:
""
,
(
temp
&
RH_A_OCPM
)
?
" OCPM"
:
""
,
(
temp
&
RH_A_DT
)
?
" DT"
:
""
,
(
temp
&
RH_A_NPS
)
?
" NPS"
:
""
,
(
temp
&
RH_A_PSM
)
?
" PSM"
:
""
,
ndp
(
temp
&
RH_A_NDP
),
controller
->
num_ports
);
temp
=
roothub_b
(
controller
);
ohci_dbg_sw
(
controller
,
next
,
size
,
...
...
@@ -266,7 +265,7 @@ ohci_dump_roothub (
);
}
for
(
i
=
0
;
i
<
ndp
;
i
++
)
{
for
(
i
=
0
;
i
<
controller
->
num_ports
;
i
++
)
{
temp
=
roothub_portstatus
(
controller
,
i
);
dbg_port_sw
(
controller
,
i
,
temp
,
next
,
size
);
}
...
...
drivers/usb/host/ohci-hcd.c
View file @
cc6120c6
...
...
@@ -382,8 +382,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
goto
sanitize
;
}
spin_unlock_irqrestore
(
&
ohci
->
lock
,
flags
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
1
);
schedule_timeout_uninterruptible
(
1
);
goto
rescan
;
case
ED_IDLE
:
/* fully unlinked */
if
(
list_empty
(
&
ed
->
td_list
))
{
...
...
@@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
// flush the writes
(
void
)
ohci_readl
(
ohci
,
&
ohci
->
regs
->
control
);
/* Read the number of ports unless overridden */
if
(
ohci
->
num_ports
==
0
)
ohci
->
num_ports
=
roothub_a
(
ohci
)
&
RH_A_NDP
;
if
(
ohci
->
hcca
)
return
0
;
...
...
@@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
msleep
(
temp
);
temp
=
roothub_a
(
ohci
);
if
(
!
(
temp
&
RH_A_NPS
))
{
unsigned
ports
=
temp
&
RH_A_NDP
;
/* power down each port */
for
(
temp
=
0
;
temp
<
ports
;
temp
++
)
for
(
temp
=
0
;
temp
<
ohci
->
num_
ports
;
temp
++
)
ohci_writel
(
ohci
,
RH_PS_LSDA
,
&
ohci
->
regs
->
roothub
.
portstatus
[
temp
]);
}
...
...
@@ -720,6 +721,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if
(
ints
&
OHCI_INTR_RD
)
{
ohci_vdbg
(
ohci
,
"resume detect
\n
"
);
ohci_writel
(
ohci
,
OHCI_INTR_RD
,
&
regs
->
intrstatus
);
if
(
hcd
->
state
!=
HC_STATE_QUIESCING
)
schedule_work
(
&
ohci
->
rh_resume
);
}
...
...
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* and that if we try to turn them back on the root hub
* will respond to CSC processing.
*/
i
=
roothub_a
(
ohci
)
&
RH_A_NDP
;
i
=
ohci
->
num_ports
;
while
(
i
--
)
ohci_writel
(
ohci
,
RH_PS_PSS
,
&
ohci
->
regs
->
roothub
.
portstatus
[
temp
]);
...
...
drivers/usb/host/ohci-hub.c
View file @
cc6120c6
...
...
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if
(
status
!=
-
EINPROGRESS
)
return
status
;
temp
=
roothub_a
(
ohci
)
&
RH_A_NDP
;
temp
=
ohci
->
num_ports
;
enables
=
0
;
while
(
temp
--
)
{
u32
stat
=
ohci_readl
(
ohci
,
...
...
@@ -304,7 +304,7 @@ static int
ohci_hub_status_data
(
struct
usb_hcd
*
hcd
,
char
*
buf
)
{
struct
ohci_hcd
*
ohci
=
hcd_to_ohci
(
hcd
);
int
ports
,
i
,
changed
=
0
,
length
=
1
;
int
i
,
changed
=
0
,
length
=
1
;
int
can_suspend
=
hcd
->
can_wakeup
;
unsigned
long
flags
;
...
...
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
goto
done
;
}
ports
=
roothub_a
(
ohci
)
&
RH_A_NDP
;
if
(
ports
>
MAX_ROOT_PORTS
)
{
ohci_err
(
ohci
,
"bogus NDP=%d, rereads as NDP=%d
\n
"
,
ports
,
/* undocumented erratum seen on at least rev D */
if
((
ohci
->
flags
&
OHCI_QUIRK_AMD756
)
&&
(
roothub_a
(
ohci
)
&
RH_A_NDP
)
>
MAX_ROOT_PORTS
)
{
ohci_warn
(
ohci
,
"bogus NDP, rereads as NDP=%d
\n
"
,
ohci_readl
(
ohci
,
&
ohci
->
regs
->
roothub
.
a
)
&
RH_A_NDP
);
/* retry later; "should not happen" */
goto
done
;
...
...
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
buf
[
0
]
=
changed
=
1
;
else
buf
[
0
]
=
0
;
if
(
ports
>
7
)
{
if
(
ohci
->
num_
ports
>
7
)
{
buf
[
1
]
=
0
;
length
++
;
}
/* look at each port */
for
(
i
=
0
;
i
<
ports
;
i
++
)
{
for
(
i
=
0
;
i
<
ohci
->
num_
ports
;
i
++
)
{
u32
status
=
roothub_portstatus
(
ohci
,
i
);
if
(
status
&
(
RH_PS_CSC
|
RH_PS_PESC
|
RH_PS_PSSC
...
...
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
struct
usb_hub_descriptor
*
desc
)
{
u32
rh
=
roothub_a
(
ohci
);
int
ports
=
rh
&
RH_A_NDP
;
u16
temp
;
desc
->
bDescriptorType
=
0x29
;
desc
->
bPwrOn2PwrGood
=
(
rh
&
RH_A_POTPGT
)
>>
24
;
desc
->
bHubContrCurrent
=
0
;
desc
->
bNbrPorts
=
ports
;
temp
=
1
+
(
ports
/
8
);
desc
->
bNbrPorts
=
ohci
->
num_
ports
;
temp
=
1
+
(
ohci
->
num_
ports
/
8
);
desc
->
bDescLength
=
7
+
2
*
temp
;
temp
=
0
;
...
...
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
rh
=
roothub_b
(
ohci
);
memset
(
desc
->
bitmap
,
0xff
,
sizeof
(
desc
->
bitmap
));
desc
->
bitmap
[
0
]
=
rh
&
RH_B_DR
;
if
(
ports
>
7
)
{
if
(
ohci
->
num_
ports
>
7
)
{
desc
->
bitmap
[
1
]
=
(
rh
&
RH_B_DR
)
>>
8
;
desc
->
bitmap
[
2
]
=
0xff
;
}
else
...
...
drivers/usb/host/ohci-pxa27x.c
View file @
cc6120c6
...
...
@@ -75,33 +75,6 @@ static int pxa27x_ohci_select_pmm( int mode )
return
0
;
}
/*
If you select PMM_PERPORT_MODE, you should set the port power
*/
static
int
pxa27x_ohci_set_port_power
(
int
port
)
{
if
(
(
pxa27x_ohci_pmm_state
==
PMM_PERPORT_MODE
)
&&
(
port
>
0
)
&&
(
port
<
PXA_UHC_MAX_PORTNUM
)
)
{
UHCRHPS
(
port
)
|=
0x100
;
return
0
;
}
return
-
1
;
}
/*
If you select PMM_PERPORT_MODE, you should set the port power
*/
static
int
pxa27x_ohci_clear_port_power
(
int
port
)
{
if
(
(
pxa27x_ohci_pmm_state
==
PMM_PERPORT_MODE
)
&&
(
port
>
0
)
&&
(
port
<
PXA_UHC_MAX_PORTNUM
)
)
{
UHCRHPS
(
port
)
|=
0x200
;
return
0
;
}
return
-
1
;
}
extern
int
usb_disabled
(
void
);
/*-------------------------------------------------------------------------*/
...
...
@@ -130,11 +103,17 @@ static void pxa27x_start_hc(struct platform_device *dev)
Polarity Low to active low. Supply power to USB ports. */
UHCHR
=
(
UHCHR
|
UHCHR_PCPL
|
UHCHR_PSPL
)
&
~
(
UHCHR_SSEP1
|
UHCHR_SSEP2
|
UHCHR_SSEP3
|
UHCHR_SSE
);
pxa27x_ohci_pmm_state
=
PMM_PERPORT_MODE
;
}
UHCHR
&=
~
UHCHR_SSE
;
UHCHIE
=
(
UHCHIE_UPRIE
|
UHCHIE_RWIE
);
/* Clear any OTG Pin Hold */
if
(
PSSR
&
PSSR_OTGPH
)
PSSR
|=
PSSR_OTGPH
;
}
static
void
pxa27x_stop_hc
(
struct
platform_device
*
dev
)
...
...
@@ -198,17 +177,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
pxa27x_start_hc
(
dev
);
/* Select Power Management Mode */
pxa27x_ohci_select_pmm
(
PMM_PERPORT_MODE
);
/* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
if
(
pxa27x_ohci_set_port_power
(
1
)
<
0
)
printk
(
KERN_ERR
"Setting port 1 power failed.
\n
"
);
if
(
pxa27x_ohci_clear_port_power
(
2
)
<
0
)
printk
(
KERN_ERR
"Setting port 2 power failed.
\n
"
);
if
(
pxa27x_ohci_clear_port_power
(
3
)
<
0
)
printk
(
KERN_ERR
"Setting port 3 power failed.
\n
"
);
pxa27x_ohci_select_pmm
(
pxa27x_ohci_pmm_state
);
ohci_hcd_init
(
hcd_to_ohci
(
hcd
));
...
...
@@ -258,6 +227,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
ohci_dbg
(
ohci
,
"ohci_pxa27x_start, ohci:%p"
,
ohci
);
/* The value of NDP in roothub_a is incorrect on this hardware */
ohci
->
num_ports
=
3
;
if
((
ret
=
ohci_init
(
ohci
))
<
0
)
return
ret
;
...
...
drivers/usb/host/ohci.h
View file @
cc6120c6
...
...
@@ -383,6 +383,7 @@ struct ohci_hcd {
/*
* driver state
*/
int
num_ports
;
int
load
[
NUM_INTS
];
u32
hc_control
;
/* copy of hc control reg */
unsigned
long
next_statechange
;
/* suspend/resume */
...
...
drivers/usb/host/uhci-hcd.c
View file @
cc6120c6
...
...
@@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
static
inline
void
restart_timer
(
struct
uhci_hcd
*
uhci
)
{
mod_timer
(
&
uhci
->
stall_timer
,
jiffies
+
msecs_to_jiffies
(
100
));
}
#include "uhci-hub.c"
#include "uhci-debug.c"
#include "uhci-q.c"
#include "uhci-hub.c"
/*
* Make sure the controller is completely inactive, unable to
...
...
@@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci)
{
reset_hc
(
uhci
);
uhci
->
hc_inaccessible
=
1
;
del_timer
(
&
uhci
->
stall_timer
);
}
/*
...
...
@@ -287,8 +281,11 @@ __acquires(uhci->lock)
/* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode, still configured.
*/
int_enable
=
(
resume_detect_interrupts_are_broken
(
uhci
)
?
0
:
USBINTR_RESUME
);
uhci
->
working_RD
=
1
;
int_enable
=
USBINTR_RESUME
;
if
(
resume_detect_interrupts_are_broken
(
uhci
))
{
uhci
->
working_RD
=
int_enable
=
0
;
}
outw
(
int_enable
,
uhci
->
io_addr
+
USBINTR
);
outw
(
USBCMD_EGSM
|
USBCMD_CF
,
uhci
->
io_addr
+
USBCMD
);
mb
();
...
...
@@ -315,7 +312,6 @@ __acquires(uhci->lock)
uhci
->
rh_state
=
new_state
;
uhci
->
is_stopped
=
UHCI_IS_STOPPED
;
del_timer
(
&
uhci
->
stall_timer
);
uhci_to_hcd
(
uhci
)
->
poll_rh
=
!
int_enable
;
uhci_scan_schedule
(
uhci
,
NULL
);
...
...
@@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci)
mb
();
uhci
->
rh_state
=
UHCI_RH_RUNNING
;
uhci_to_hcd
(
uhci
)
->
poll_rh
=
1
;
restart_timer
(
uhci
);
}
static
void
wakeup_rh
(
struct
uhci_hcd
*
uhci
)
...
...
@@ -374,20 +369,6 @@ __acquires(uhci->lock)
mod_timer
(
&
uhci_to_hcd
(
uhci
)
->
rh_timer
,
jiffies
);
}
static
void
stall_callback
(
unsigned
long
_uhci
)
{
struct
uhci_hcd
*
uhci
=
(
struct
uhci_hcd
*
)
_uhci
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
lock
,
flags
);
uhci_scan_schedule
(
uhci
,
NULL
);
check_fsbr
(
uhci
);
if
(
!
uhci
->
is_stopped
)
restart_timer
(
uhci
);
spin_unlock_irqrestore
(
&
uhci
->
lock
,
flags
);
}
static
irqreturn_t
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
...
...
@@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
"host controller halted, "
"very bad!
\n
"
);
hc_died
(
uhci
);
spin_unlock_irqrestore
(
&
uhci
->
lock
,
flags
);
return
IRQ_HANDLED
;
/* Force a callback in case there are
* pending unlinks */
mod_timer
(
&
hcd
->
rh_timer
,
jiffies
);
}
spin_unlock_irqrestore
(
&
uhci
->
lock
,
flags
);
}
...
...
@@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if
(
status
&
USBSTS_RD
)
usb_hcd_poll_rh_status
(
hcd
);
else
{
spin_lock_irqsave
(
&
uhci
->
lock
,
flags
);
uhci_scan_schedule
(
uhci
,
regs
);
spin_unlock_irqrestore
(
&
uhci
->
lock
,
flags
);
}
return
IRQ_HANDLED
;
}
...
...
@@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd)
init_waitqueue_head
(
&
uhci
->
waitqh
);
init_timer
(
&
uhci
->
stall_timer
);
uhci
->
stall_timer
.
function
=
stall_callback
;
uhci
->
stall_timer
.
data
=
(
unsigned
long
)
uhci
;
uhci
->
fl
=
dma_alloc_coherent
(
uhci_dev
(
uhci
),
sizeof
(
*
uhci
->
fl
),
&
dma_handle
,
0
);
if
(
!
uhci
->
fl
)
{
...
...
@@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
spin_lock_irq
(
&
uhci
->
lock
);
if
(
!
uhci
->
hc_inaccessible
)
reset_hc
(
uhci
);
uhci_scan_schedule
(
uhci
,
NULL
);
spin_unlock_irq
(
&
uhci
->
lock
);
del_timer_sync
(
&
uhci
->
stall_timer
);
release_uhci
(
uhci
);
}
...
...
@@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
*/
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
0
);
uhci
->
hc_inaccessible
=
1
;
hcd
->
poll_rh
=
0
;
/* FIXME: Enable non-PME# remote wakeup? */
done:
spin_unlock_irq
(
&
uhci
->
lock
);
if
(
rc
==
0
)
del_timer_sync
(
&
hcd
->
rh_timer
);
return
rc
;
}
...
...
@@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd)
spin_unlock_irq
(
&
uhci
->
lock
);
if
(
hcd
->
poll_rh
)
if
(
!
uhci
->
working_RD
)
{
/* Suspended root hub needs to be polled */
hcd
->
poll_rh
=
1
;
usb_hcd_poll_rh_status
(
hcd
);
}
return
0
;
}
#endif
...
...
drivers/usb/host/uhci-hcd.h
View file @
cc6120c6
...
...
@@ -345,9 +345,6 @@ enum uhci_rh_state {
/*
* This describes the full uhci information.
*
* Note how the "proper" USB information is just
* a subset of what the full implementation needs.
*/
struct
uhci_hcd
{
...
...
@@ -360,8 +357,6 @@ struct uhci_hcd {
struct
dma_pool
*
qh_pool
;
struct
dma_pool
*
td_pool
;
struct
usb_bus
*
bus
;
struct
uhci_td
*
term_td
;
/* Terminating TD, see UHCI bug */
struct
uhci_qh
*
skelqh
[
UHCI_NUM_SKELQH
];
/* Skeleton QH's */
...
...
@@ -380,6 +375,8 @@ struct uhci_hcd {
unsigned
int
scan_in_progress
:
1
;
/* Schedule scan is running */
unsigned
int
need_rescan
:
1
;
/* Redo the schedule scan */
unsigned
int
hc_inaccessible
:
1
;
/* HC is suspended or dead */
unsigned
int
working_RD
:
1
;
/* Suspended root hub doesn't
need to be polled */
/* Support for port suspend/resume/reset */
unsigned
long
port_c_suspend
;
/* Bit-arrays of ports */
...
...
@@ -405,9 +402,7 @@ struct uhci_hcd {
/* List of URB's awaiting completion callback */
struct
list_head
complete_list
;
/* P: uhci->lock */
int
rh_numports
;
struct
timer_list
stall_timer
;
int
rh_numports
;
/* Number of root-hub ports */
wait_queue_head_t
waitqh
;
/* endpoint_disable waiters */
};
...
...
drivers/usb/host/uhci-hub.c
View file @
cc6120c6
...
...
@@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
long
flags
;
int
status
;
int
status
=
0
;
spin_lock_irqsave
(
&
uhci
->
lock
,
flags
);
if
(
uhci
->
hc_inaccessible
)
{
status
=
0
;
goto
done
;
}
uhci_scan_schedule
(
uhci
,
NULL
);
if
(
uhci
->
hc_inaccessible
)
goto
done
;
check_fsbr
(
uhci
);
uhci_check_ports
(
uhci
);
status
=
get_hub_status_data
(
uhci
,
buf
);
switch
(
uhci
->
rh_state
)
{
...
...
drivers/usb/host/uhci-q.c
View file @
cc6120c6
...
...
@@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
static
inline
void
uhci_set_next_interrupt
(
struct
uhci_hcd
*
uhci
)
{
if
(
uhci
->
is_stopped
)
mod_timer
(
&
uhci
->
stall
_timer
,
jiffies
);
mod_timer
(
&
uhci
_to_hcd
(
uhci
)
->
rh
_timer
,
jiffies
);
uhci
->
term_td
->
status
|=
cpu_to_le32
(
TD_CTRL_IOC
);
}
...
...
drivers/usb/input/Kconfig
View file @
cc6120c6
...
...
@@ -286,3 +286,23 @@ config USB_KEYSPAN_REMOTE
To compile this driver as a module, choose M here: the module will
be called keyspan_remote.
config USB_APPLETOUCH
tristate "Apple USB Touchpad support"
depends on USB && INPUT
---help---
Say Y here if you want to use an Apple USB Touchpad.
These are the touchpads that can be found on post-February 2005
Apple Powerbooks (prior models have a Synaptics touchpad connected
to the ADB bus).
This driver provides a basic mouse driver but can be interfaced
with the synaptics X11 driver to provide acceleration and
scrolling in X11.
For further information, see
<file:Documentation/input/appletouch.txt>.
To compile this driver as a module, choose M here: the
module will be called appletouch.
drivers/usb/input/Makefile
View file @
cc6120c6
...
...
@@ -41,3 +41,4 @@ obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_ACECAD)
+=
acecad.o
obj-$(CONFIG_USB_YEALINK)
+=
yealink.o
obj-$(CONFIG_USB_XPAD)
+=
xpad.o
obj-$(CONFIG_USB_APPLETOUCH)
+=
appletouch.o
drivers/usb/input/appletouch.c
0 → 100644
View file @
cc6120c6
/*
* Apple USB Touchpad (for post-February 2005 PowerBooks) driver
*
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
*
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/input.h>
#include <linux/usb_input.h>
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID 0x05AC
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
.idVendor = APPLE_VENDOR_ID, \
.idProduct = (prod), \
.bInterfaceClass = 0x03, \
.bInterfaceProtocol = 0x02
/* table of devices that work with this driver */
static
struct
usb_device_id
atp_table
[]
=
{
{
ATP_DEVICE
(
0x020E
)
},
{
ATP_DEVICE
(
0x020F
)
},
{
ATP_DEVICE
(
0x030A
)
},
{
ATP_DEVICE
(
0x030B
)
},
{
}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
usb
,
atp_table
);
/* size of a USB urb transfer */
#define ATP_DATASIZE 81
/*
* number of sensors. Note that only 16 instead of 26 X (horizontal)
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y
* (vertical) sensors.
*/
#define ATP_XSENSORS 26
#define ATP_YSENSORS 16
/* amount of fuzz this touchpad generates */
#define ATP_FUZZ 16
/* maximum pressure this driver will report */
#define ATP_PRESSURE 300
/*
* multiplication factor for the X and Y coordinates.
* We try to keep the touchpad aspect ratio while still doing only simple
* arithmetics.
* The factors below give coordinates like:
* 0 <= x < 960 on 12" and 15" Powerbooks
* 0 <= x < 1600 on 17" Powerbooks
* 0 <= y < 646
*/
#define ATP_XFACT 64
#define ATP_YFACT 43
/*
* Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
* ignored.
*/
#define ATP_THRESHOLD 5
/* Structure to hold all of our device specific stuff */
struct
atp
{
struct
usb_device
*
udev
;
/* usb device */
struct
urb
*
urb
;
/* usb request block */
signed
char
*
data
;
/* transferred data */
int
open
;
/* non-zero if opened */
struct
input_dev
input
;
/* input dev */
int
valid
;
/* are the sensors valid ? */
int
x_old
;
/* last reported x/y, */
int
y_old
;
/* used for smoothing */
/* current value of the sensors */
signed
char
xy_cur
[
ATP_XSENSORS
+
ATP_YSENSORS
];
/* last value of the sensors */
signed
char
xy_old
[
ATP_XSENSORS
+
ATP_YSENSORS
];
/* accumulated sensors */
int
xy_acc
[
ATP_XSENSORS
+
ATP_YSENSORS
];
};
#define dbg_dump(msg, tab) \
if (debug > 1) { \
int i; \
printk("appletouch: %s %lld", msg, (long long)jiffies); \
for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) \
printk(" %02x", tab[i]); \
printk("\n"); \
}
#define dprintk(format, a...) \
do { \
if (debug) printk(format, ##a); \
} while (0)
MODULE_AUTHOR
(
"Johannes Berg, Stelian Pop, Frank Arnold"
);
MODULE_DESCRIPTION
(
"Apple PowerBooks USB touchpad driver"
);
MODULE_LICENSE
(
"GPL"
);
static
int
debug
=
1
;
module_param
(
debug
,
int
,
0644
);
MODULE_PARM_DESC
(
debug
,
"Activate debugging output"
);
static
int
atp_calculate_abs
(
int
*
xy_sensors
,
int
nb_sensors
,
int
fact
,
int
*
z
,
int
*
fingers
)
{
int
i
;
/* values to calculate mean */
int
pcum
=
0
,
psum
=
0
;
*
fingers
=
0
;
for
(
i
=
0
;
i
<
nb_sensors
;
i
++
)
{
if
(
xy_sensors
[
i
]
<
ATP_THRESHOLD
)
continue
;
if
((
i
-
1
<
0
)
||
(
xy_sensors
[
i
-
1
]
<
ATP_THRESHOLD
))
(
*
fingers
)
++
;
pcum
+=
xy_sensors
[
i
]
*
i
;
psum
+=
xy_sensors
[
i
];
}
if
(
psum
>
0
)
{
*
z
=
psum
;
return
pcum
*
fact
/
psum
;
}
return
0
;
}
static
inline
void
atp_report_fingers
(
struct
input_dev
*
input
,
int
fingers
)
{
input_report_key
(
input
,
BTN_TOOL_FINGER
,
fingers
==
1
);
input_report_key
(
input
,
BTN_TOOL_DOUBLETAP
,
fingers
==
2
);
input_report_key
(
input
,
BTN_TOOL_TRIPLETAP
,
fingers
>
2
);
}
static
void
atp_complete
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
int
x
,
y
,
x_z
,
y_z
,
x_f
,
y_f
;
int
retval
,
i
;
struct
atp
*
dev
=
urb
->
context
;
switch
(
urb
->
status
)
{
case
0
:
/* success */
break
;
case
-
ECONNRESET
:
case
-
ENOENT
:
case
-
ESHUTDOWN
:
/* This urb is terminated, clean up */
dbg
(
"%s - urb shutting down with status: %d"
,
__FUNCTION__
,
urb
->
status
);
return
;
default:
dbg
(
"%s - nonzero urb status received: %d"
,
__FUNCTION__
,
urb
->
status
);
goto
exit
;
}
/* drop incomplete datasets */
if
(
dev
->
urb
->
actual_length
!=
ATP_DATASIZE
)
{
dprintk
(
"appletouch: incomplete data package.
\n
"
);
goto
exit
;
}
/* reorder the sensors values */
for
(
i
=
0
;
i
<
8
;
i
++
)
{
/* X values */
dev
->
xy_cur
[
i
]
=
dev
->
data
[
5
*
i
+
2
];
dev
->
xy_cur
[
i
+
8
]
=
dev
->
data
[
5
*
i
+
4
];
dev
->
xy_cur
[
i
+
16
]
=
dev
->
data
[
5
*
i
+
42
];
if
(
i
<
2
)
dev
->
xy_cur
[
i
+
24
]
=
dev
->
data
[
5
*
i
+
44
];
/* Y values */
dev
->
xy_cur
[
i
+
26
]
=
dev
->
data
[
5
*
i
+
1
];
dev
->
xy_cur
[
i
+
34
]
=
dev
->
data
[
5
*
i
+
3
];
}
dbg_dump
(
"sample"
,
dev
->
xy_cur
);
if
(
!
dev
->
valid
)
{
/* first sample */
dev
->
valid
=
1
;
dev
->
x_old
=
dev
->
y_old
=
-
1
;
memcpy
(
dev
->
xy_old
,
dev
->
xy_cur
,
sizeof
(
dev
->
xy_old
));
/* 17" Powerbooks have 10 extra X sensors */
for
(
i
=
16
;
i
<
ATP_XSENSORS
;
i
++
)
if
(
dev
->
xy_cur
[
i
])
{
printk
(
"appletouch: 17
\"
model detected.
\n
"
);
input_set_abs_params
(
&
dev
->
input
,
ABS_X
,
0
,
(
ATP_XSENSORS
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
break
;
}
goto
exit
;
}
for
(
i
=
0
;
i
<
ATP_XSENSORS
+
ATP_YSENSORS
;
i
++
)
{
/* accumulate the change */
signed
char
change
=
dev
->
xy_old
[
i
]
-
dev
->
xy_cur
[
i
];
dev
->
xy_acc
[
i
]
-=
change
;
/* prevent down drifting */
if
(
dev
->
xy_acc
[
i
]
<
0
)
dev
->
xy_acc
[
i
]
=
0
;
}
memcpy
(
dev
->
xy_old
,
dev
->
xy_cur
,
sizeof
(
dev
->
xy_old
));
dbg_dump
(
"accumulator"
,
dev
->
xy_acc
);
x
=
atp_calculate_abs
(
dev
->
xy_acc
,
ATP_XSENSORS
,
ATP_XFACT
,
&
x_z
,
&
x_f
);
y
=
atp_calculate_abs
(
dev
->
xy_acc
+
ATP_XSENSORS
,
ATP_YSENSORS
,
ATP_YFACT
,
&
y_z
,
&
y_f
);
if
(
x
&&
y
)
{
if
(
dev
->
x_old
!=
-
1
)
{
x
=
(
dev
->
x_old
*
3
+
x
)
>>
2
;
y
=
(
dev
->
y_old
*
3
+
y
)
>>
2
;
dev
->
x_old
=
x
;
dev
->
y_old
=
y
;
if
(
debug
>
1
)
printk
(
"appletouch: X: %3d Y: %3d "
"Xz: %3d Yz: %3d
\n
"
,
x
,
y
,
x_z
,
y_z
);
input_report_key
(
&
dev
->
input
,
BTN_TOUCH
,
1
);
input_report_abs
(
&
dev
->
input
,
ABS_X
,
x
);
input_report_abs
(
&
dev
->
input
,
ABS_Y
,
y
);
input_report_abs
(
&
dev
->
input
,
ABS_PRESSURE
,
min
(
ATP_PRESSURE
,
x_z
+
y_z
));
atp_report_fingers
(
&
dev
->
input
,
max
(
x_f
,
y_f
));
}
dev
->
x_old
=
x
;
dev
->
y_old
=
y
;
}
else
if
(
!
x
&&
!
y
)
{
dev
->
x_old
=
dev
->
y_old
=
-
1
;
input_report_key
(
&
dev
->
input
,
BTN_TOUCH
,
0
);
input_report_abs
(
&
dev
->
input
,
ABS_PRESSURE
,
0
);
atp_report_fingers
(
&
dev
->
input
,
0
);
/* reset the accumulator on release */
memset
(
dev
->
xy_acc
,
0
,
sizeof
(
dev
->
xy_acc
));
}
input_report_key
(
&
dev
->
input
,
BTN_LEFT
,
!!
dev
->
data
[
80
]);
input_sync
(
&
dev
->
input
);
exit:
retval
=
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
);
if
(
retval
)
{
err
(
"%s - usb_submit_urb failed with result %d"
,
__FUNCTION__
,
retval
);
}
}
static
int
atp_open
(
struct
input_dev
*
input
)
{
struct
atp
*
dev
=
input
->
private
;
if
(
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
))
return
-
EIO
;
dev
->
open
=
1
;
return
0
;
}
static
void
atp_close
(
struct
input_dev
*
input
)
{
struct
atp
*
dev
=
input
->
private
;
usb_kill_urb
(
dev
->
urb
);
dev
->
open
=
0
;
}
static
int
atp_probe
(
struct
usb_interface
*
iface
,
const
struct
usb_device_id
*
id
)
{
struct
atp
*
dev
=
NULL
;
struct
usb_host_interface
*
iface_desc
;
struct
usb_endpoint_descriptor
*
endpoint
;
int
int_in_endpointAddr
=
0
;
int
i
,
retval
=
-
ENOMEM
;
/* allocate memory for our device state and initialize it */
dev
=
kmalloc
(
sizeof
(
struct
atp
),
GFP_KERNEL
);
if
(
dev
==
NULL
)
{
err
(
"Out of memory"
);
goto
err_kmalloc
;
}
memset
(
dev
,
0
,
sizeof
(
struct
atp
));
dev
->
udev
=
interface_to_usbdev
(
iface
);
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
iface_desc
=
iface
->
cur_altsetting
;
for
(
i
=
0
;
i
<
iface_desc
->
desc
.
bNumEndpoints
;
i
++
)
{
endpoint
=
&
iface_desc
->
endpoint
[
i
].
desc
;
if
(
!
int_in_endpointAddr
&&
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
)
&&
((
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_INT
))
{
/* we found an interrupt in endpoint */
int_in_endpointAddr
=
endpoint
->
bEndpointAddress
;
break
;
}
}
if
(
!
int_in_endpointAddr
)
{
retval
=
-
EIO
;
err
(
"Could not find int-in endpoint"
);
goto
err_endpoint
;
}
/* save our data pointer in this interface device */
usb_set_intfdata
(
iface
,
dev
);
dev
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
dev
->
urb
)
{
retval
=
-
ENOMEM
;
goto
err_usballoc
;
}
dev
->
data
=
usb_buffer_alloc
(
dev
->
udev
,
ATP_DATASIZE
,
GFP_KERNEL
,
&
dev
->
urb
->
transfer_dma
);
if
(
!
dev
->
data
)
{
retval
=
-
ENOMEM
;
goto
err_usbbufalloc
;
}
usb_fill_int_urb
(
dev
->
urb
,
dev
->
udev
,
usb_rcvintpipe
(
dev
->
udev
,
int_in_endpointAddr
),
dev
->
data
,
ATP_DATASIZE
,
atp_complete
,
dev
,
1
);
init_input_dev
(
&
dev
->
input
);
dev
->
input
.
name
=
"appletouch"
;
dev
->
input
.
dev
=
&
iface
->
dev
;
dev
->
input
.
private
=
dev
;
dev
->
input
.
open
=
atp_open
;
dev
->
input
.
close
=
atp_close
;
usb_to_input_id
(
dev
->
udev
,
&
dev
->
input
.
id
);
set_bit
(
EV_ABS
,
dev
->
input
.
evbit
);
/*
* 12" and 15" Powerbooks only have 16 x sensors,
* 17" models are detected later.
*/
input_set_abs_params
(
&
dev
->
input
,
ABS_X
,
0
,
(
16
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
&
dev
->
input
,
ABS_Y
,
0
,
(
ATP_YSENSORS
-
1
)
*
ATP_YFACT
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
&
dev
->
input
,
ABS_PRESSURE
,
0
,
ATP_PRESSURE
,
0
,
0
);
set_bit
(
EV_KEY
,
dev
->
input
.
evbit
);
set_bit
(
BTN_TOUCH
,
dev
->
input
.
keybit
);
set_bit
(
BTN_TOOL_FINGER
,
dev
->
input
.
keybit
);
set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
input
.
keybit
);
set_bit
(
BTN_TOOL_TRIPLETAP
,
dev
->
input
.
keybit
);
set_bit
(
BTN_LEFT
,
dev
->
input
.
keybit
);
input_register_device
(
&
dev
->
input
);
printk
(
KERN_INFO
"input: appletouch connected
\n
"
);
return
0
;
err_usbbufalloc:
usb_free_urb
(
dev
->
urb
);
err_usballoc:
usb_set_intfdata
(
iface
,
NULL
);
err_endpoint:
kfree
(
dev
);
err_kmalloc:
return
retval
;
}
static
void
atp_disconnect
(
struct
usb_interface
*
iface
)
{
struct
atp
*
dev
=
usb_get_intfdata
(
iface
);
usb_set_intfdata
(
iface
,
NULL
);
if
(
dev
)
{
usb_kill_urb
(
dev
->
urb
);
input_unregister_device
(
&
dev
->
input
);
usb_free_urb
(
dev
->
urb
);
usb_buffer_free
(
dev
->
udev
,
ATP_DATASIZE
,
dev
->
data
,
dev
->
urb
->
transfer_dma
);
kfree
(
dev
);
}
printk
(
KERN_INFO
"input: appletouch disconnected
\n
"
);
}
static
int
atp_suspend
(
struct
usb_interface
*
iface
,
pm_message_t
message
)
{
struct
atp
*
dev
=
usb_get_intfdata
(
iface
);
usb_kill_urb
(
dev
->
urb
);
dev
->
valid
=
0
;
return
0
;
}
static
int
atp_resume
(
struct
usb_interface
*
iface
)
{
struct
atp
*
dev
=
usb_get_intfdata
(
iface
);
if
(
dev
->
open
&&
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
))
return
-
EIO
;
return
0
;
}
static
struct
usb_driver
atp_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"appletouch"
,
.
probe
=
atp_probe
,
.
disconnect
=
atp_disconnect
,
.
suspend
=
atp_suspend
,
.
resume
=
atp_resume
,
.
id_table
=
atp_table
,
};
static
int
__init
atp_init
(
void
)
{
return
usb_register
(
&
atp_driver
);
}
static
void
__exit
atp_exit
(
void
)
{
usb_deregister
(
&
atp_driver
);
}
module_init
(
atp_init
);
module_exit
(
atp_exit
);
drivers/usb/input/hid-core.c
View file @
cc6120c6
...
...
@@ -1446,7 +1446,6 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_BLUETOOTH 0x1000
/*
* Alphabetically sorted blacklist by quirk type.
...
...
@@ -1465,7 +1464,6 @@ static struct hid_blacklist {
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_22
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_23
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_24
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_BLUETOOTH
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_BERKSHIRE
,
USB_DEVICE_ID_BERKSHIRE_PCWD
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_CODEMERCS
,
USB_DEVICE_ID_CODEMERCS_IOW40
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_CODEMERCS
,
USB_DEVICE_ID_CODEMERCS_IOW24
,
HID_QUIRK_IGNORE
},
...
...
drivers/usb/misc/sisusbvga/Kconfig
View file @
cc6120c6
...
...
@@ -9,6 +9,38 @@ config USB_SISUSBVGA
Note that this device requires a USB 2.0 host controller. It will not
work with USB 1.x controllers.
To compile this driver as a module, choose M here: the module will be
called sisusb. If unsure, say N.
To compile this driver as a module, choose M here; the module will be
called sisusbvga. If unsure, say N.
config USB_SISUSBVGA_CON
bool "Text console and mode switching support" if USB_SISUSBVGA
depends on VT
select FONT_8x16
---help---
Say Y here if you want a VGA text console via the USB dongle or
want to support userland applications that utilize the driver's
display mode switching capabilities.
Note that this console supports VGA/EGA text mode only.
By default, the console part of the driver will not kick in when
the driver is initialized. If you want the driver to take over
one or more of the consoles, you need to specify the number of
the first and last consoles (starting at 1) as driver parameters.
For example, if the driver is compiled as a module:
modprobe sisusbvga first=1 last=5
If you use hotplug, add this to your modutils config files with
the "options" keyword, such as eg.
options sisusbvga first=1 last=5
If the driver is compiled into the kernel image, the parameters
must be given in the kernel command like, such as
sisusbvga.first=1 sisusbvga.last=5
drivers/usb/misc/sisusbvga/Makefile
View file @
cc6120c6
...
...
@@ -2,5 +2,7 @@
# Makefile for the sisusb driver (if driver is inside kernel tree).
#
obj-$(CONFIG_USB_SISUSBVGA)
+=
sisusb.o
obj-$(CONFIG_USB_SISUSBVGA)
+=
sisusbvga.o
sisusbvga-objs
:=
sisusb.o sisusb_init.o sisusb_con.o
drivers/usb/misc/sisusbvga/sisusb.c
View file @
cc6120c6
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
* Main part
*
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
...
...
@@ -48,16 +50,60 @@
#include <linux/kref.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include "sisusb.h"
#ifdef INCL_SISUSB_CON
#include <linux/font.h>
#endif
#define SISUSB_DONTSYNC
/* Forward declarations / clean-up routines */
#ifdef INCL_SISUSB_CON
int
sisusb_setreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
data
);
int
sisusb_getreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
*
data
);
int
sisusb_setidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
data
);
int
sisusb_getidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
*
data
);
int
sisusb_setidxregandor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
,
u8
myor
);
int
sisusb_setidxregor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
myor
);
int
sisusb_setidxregand
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
);
int
sisusb_writeb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
data
);
int
sisusb_readb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
*
data
);
int
sisusb_writew
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
data
);
int
sisusb_readw
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
*
data
);
int
sisusb_copy_memory
(
struct
sisusb_usb_data
*
sisusb
,
char
*
src
,
u32
dest
,
int
length
,
size_t
*
bytes_written
);
int
sisusb_reset_text_mode
(
struct
sisusb_usb_data
*
sisusb
,
int
init
);
extern
int
SiSUSBSetMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
);
extern
int
SiSUSBSetVESAMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
VModeNo
);
extern
void
sisusb_init_concode
(
void
);
extern
int
sisusb_console_init
(
struct
sisusb_usb_data
*
sisusb
,
int
first
,
int
last
);
extern
void
sisusb_console_exit
(
struct
sisusb_usb_data
*
sisusb
);
extern
void
sisusb_set_cursor
(
struct
sisusb_usb_data
*
sisusb
,
unsigned
int
location
);
extern
int
sisusbcon_do_font_op
(
struct
sisusb_usb_data
*
sisusb
,
int
set
,
int
slot
,
u8
*
arg
,
int
cmapsz
,
int
ch512
,
int
dorecalc
,
struct
vc_data
*
c
,
int
fh
,
int
uplock
);
static
int
sisusb_first_vc
=
0
;
static
int
sisusb_last_vc
=
0
;
module_param_named
(
first
,
sisusb_first_vc
,
int
,
0
);
module_param_named
(
last
,
sisusb_last_vc
,
int
,
0
);
MODULE_PARM_DESC
(
first
,
"Number of first console to take over (1 - MAX_NR_CONSOLES)"
);
MODULE_PARM_DESC
(
last
,
"Number of last console to take over (1 - MAX_NR_CONSOLES)"
);
#endif
static
struct
usb_driver
sisusb_driver
;
static
DECLARE_MUTEX
(
disconnect_sem
);
DECLARE_MUTEX
(
disconnect_sem
);
static
void
sisusb_free_buffers
(
struct
sisusb_usb_data
*
sisusb
)
...
...
@@ -639,7 +685,10 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
/* The following routines assume being used to transfer byte, word,
* long etc.
* This means that they assume "data" in machine endianness format.
* This means that
* - the write routines expect "data" in machine endianness format.
* The data will be converted to leXX in sisusb_xxx_packet.
* - the read routines can expect read data in machine-endianess.
*/
static
int
sisusb_write_memio_byte
(
struct
sisusb_usb_data
*
sisusb
,
int
type
,
...
...
@@ -839,7 +888,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if
(
get_user
(
swap16
,
(
u16
__user
*
)
userbuffer
))
return
-
EFAULT
;
}
else
swap16
=
(
kernbuffer
[
0
]
<<
8
)
|
kernbuffer
[
1
]
;
swap16
=
*
((
u16
*
)
kernbuffer
)
;
ret
=
sisusb_write_memio_word
(
sisusb
,
SISUSB_TYPE_MEM
,
...
...
@@ -855,14 +904,25 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if
(
userbuffer
)
{
if
(
copy_from_user
(
&
buf
,
userbuffer
,
3
))
return
-
EFAULT
;
#ifdef __BIG_ENDIAN
swap32
=
(
buf
[
0
]
<<
16
)
|
(
buf
[
1
]
<<
8
)
|
buf
[
2
];
#else
swap32
=
(
buf
[
2
]
<<
16
)
|
(
buf
[
1
]
<<
8
)
|
buf
[
0
];
#endif
}
else
#ifdef __BIG_ENDIAN
swap32
=
(
kernbuffer
[
0
]
<<
16
)
|
(
kernbuffer
[
1
]
<<
8
)
|
kernbuffer
[
2
];
#else
swap32
=
(
kernbuffer
[
2
]
<<
16
)
|
(
kernbuffer
[
1
]
<<
8
)
|
kernbuffer
[
0
];
#endif
ret
=
sisusb_write_memio_24bit
(
sisusb
,
SISUSB_TYPE_MEM
,
...
...
@@ -879,10 +939,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
if
(
get_user
(
swap32
,
(
u32
__user
*
)
userbuffer
))
return
-
EFAULT
;
}
else
swap32
=
(
kernbuffer
[
0
]
<<
24
)
|
(
kernbuffer
[
1
]
<<
16
)
|
(
kernbuffer
[
2
]
<<
8
)
|
kernbuffer
[
3
];
swap32
=
*
((
u32
*
)
kernbuffer
);
ret
=
sisusb_write_memio_long
(
sisusb
,
SISUSB_TYPE_MEM
,
...
...
@@ -1005,6 +1062,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
return
ret
?
-
EIO
:
0
;
}
/* Remember: Read data in packet is in machine-endianess! So for
* byte, word, 24bit, long no endian correction is necessary.
*/
static
int
sisusb_read_memio_byte
(
struct
sisusb_usb_data
*
sisusb
,
int
type
,
u32
addr
,
u8
*
data
)
{
...
...
@@ -1191,8 +1252,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
(
u16
__user
*
)
userbuffer
))
return
-
EFAULT
;
}
else
{
kernbuffer
[
0
]
=
swap16
>>
8
;
kernbuffer
[
1
]
=
swap16
&
0xff
;
*
((
u16
*
)
kernbuffer
)
=
swap16
;
}
}
return
ret
;
...
...
@@ -1202,9 +1262,15 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
addr
,
&
swap32
);
if
(
!
ret
)
{
(
*
bytes_read
)
+=
3
;
#ifdef __BIG_ENDIAN
buf
[
0
]
=
(
swap32
>>
16
)
&
0xff
;
buf
[
1
]
=
(
swap32
>>
8
)
&
0xff
;
buf
[
2
]
=
swap32
&
0xff
;
#else
buf
[
2
]
=
(
swap32
>>
16
)
&
0xff
;
buf
[
1
]
=
(
swap32
>>
8
)
&
0xff
;
buf
[
0
]
=
swap32
&
0xff
;
#endif
if
(
userbuffer
)
{
if
(
copy_to_user
(
userbuffer
,
&
buf
[
0
],
3
))
return
-
EFAULT
;
...
...
@@ -1228,10 +1294,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
userbuffer
+=
4
;
}
else
{
kernbuffer
[
0
]
=
(
swap32
>>
24
)
&
0xff
;
kernbuffer
[
1
]
=
(
swap32
>>
16
)
&
0xff
;
kernbuffer
[
2
]
=
(
swap32
>>
8
)
&
0xff
;
kernbuffer
[
3
]
=
swap32
&
0xff
;
*
((
u32
*
)
kernbuffer
)
=
swap32
;
kernbuffer
+=
4
;
}
addr
+=
4
;
...
...
@@ -1289,7 +1352,24 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
/* High level: Gfx (indexed) register access */
static
int
#ifdef INCL_SISUSB_CON
int
sisusb_setreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
data
)
{
return
sisusb_write_memio_byte
(
sisusb
,
SISUSB_TYPE_IO
,
port
,
data
);
}
int
sisusb_getreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
*
data
)
{
return
sisusb_read_memio_byte
(
sisusb
,
SISUSB_TYPE_IO
,
port
,
data
);
}
#endif
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
data
)
{
int
ret
;
...
...
@@ -1298,7 +1378,10 @@ sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
return
ret
;
}
static
int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_getidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
*
data
)
{
int
ret
;
...
...
@@ -1307,7 +1390,10 @@ sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
return
ret
;
}
static
int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregandor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
,
u8
myor
)
{
...
...
@@ -1336,18 +1422,89 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
return
ret
;
}
static
int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
myor
)
{
return
(
sisusb_setidxregandor
(
sisusb
,
port
,
index
,
0xff
,
myor
));
}
static
int
#ifndef INCL_SISUSB_CON
static
#endif
int
sisusb_setidxregand
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
)
{
return
(
sisusb_setidxregandor
(
sisusb
,
port
,
idx
,
myand
,
0x00
));
}
/* Write/read video ram */
#ifdef INCL_SISUSB_CON
int
sisusb_writeb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
data
)
{
return
(
sisusb_write_memio_byte
(
sisusb
,
SISUSB_TYPE_MEM
,
adr
,
data
));
}
int
sisusb_readb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
*
data
)
{
return
(
sisusb_read_memio_byte
(
sisusb
,
SISUSB_TYPE_MEM
,
adr
,
data
));
}
int
sisusb_writew
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
data
)
{
return
(
sisusb_write_memio_word
(
sisusb
,
SISUSB_TYPE_MEM
,
adr
,
data
));
}
int
sisusb_readw
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
*
data
)
{
return
(
sisusb_read_memio_word
(
sisusb
,
SISUSB_TYPE_MEM
,
adr
,
data
));
}
int
sisusb_copy_memory
(
struct
sisusb_usb_data
*
sisusb
,
char
*
src
,
u32
dest
,
int
length
,
size_t
*
bytes_written
)
{
return
(
sisusb_write_mem_bulk
(
sisusb
,
dest
,
src
,
length
,
NULL
,
0
,
bytes_written
));
}
#ifdef SISUSBENDIANTEST
int
sisusb_read_memory
(
struct
sisusb_usb_data
*
sisusb
,
char
*
dest
,
u32
src
,
int
length
,
size_t
*
bytes_written
)
{
return
(
sisusb_read_mem_bulk
(
sisusb
,
src
,
dest
,
length
,
NULL
,
bytes_written
));
}
#endif
#endif
#ifdef SISUSBENDIANTEST
static
void
sisusb_testreadwrite
(
struct
sisusb_usb_data
*
sisusb
)
{
static
char
srcbuffer
[]
=
{
0x11
,
0x22
,
0x33
,
0x44
,
0x55
,
0x66
,
0x77
};
char
destbuffer
[
10
];
size_t
dummy
;
int
i
,
j
;
sisusb_copy_memory
(
sisusb
,
srcbuffer
,
sisusb
->
vrambase
,
7
,
&
dummy
);
for
(
i
=
1
;
i
<=
7
;
i
++
)
{
printk
(
KERN_DEBUG
"sisusb: rwtest %d bytes
\n
"
,
i
);
sisusb_read_memory
(
sisusb
,
destbuffer
,
sisusb
->
vrambase
,
i
,
&
dummy
);
for
(
j
=
0
;
j
<
i
;
j
++
)
{
printk
(
KERN_DEBUG
"sisusb: rwtest read[%d] = %x
\n
"
,
j
,
destbuffer
[
j
]);
}
}
}
#endif
/* access pci config registers (reg numbers 0, 4, 8, etc) */
static
int
...
...
@@ -2270,6 +2427,129 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
return
ret
;
}
#ifdef INCL_SISUSB_CON
/* Set up default text mode:
- Set text mode (0x03)
- Upload default font
- Upload user font (if available)
*/
int
sisusb_reset_text_mode
(
struct
sisusb_usb_data
*
sisusb
,
int
init
)
{
int
ret
=
0
,
slot
=
sisusb
->
font_slot
,
i
;
struct
font_desc
*
myfont
;
u8
*
tempbuf
;
u16
*
tempbufb
;
size_t
written
;
static
char
bootstring
[]
=
"SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."
;
static
char
bootlogo
[]
=
"(o_ //
\\
V_/_"
;
/* sisusb->lock is down */
if
(
!
sisusb
->
SiS_Pr
)
return
1
;
sisusb
->
SiS_Pr
->
IOAddress
=
SISUSB_PCI_IOPORTBASE
+
0x30
;
sisusb
->
SiS_Pr
->
sisusb
=
(
void
*
)
sisusb
;
/* Set mode 0x03 */
SiSUSBSetMode
(
sisusb
->
SiS_Pr
,
0x03
);
if
(
!
(
myfont
=
find_font
(
"VGA8x16"
)))
return
1
;
if
(
!
(
tempbuf
=
vmalloc
(
8192
)))
return
1
;
for
(
i
=
0
;
i
<
256
;
i
++
)
memcpy
(
tempbuf
+
(
i
*
32
),
myfont
->
data
+
(
i
*
16
),
16
);
/* Upload default font */
ret
=
sisusbcon_do_font_op
(
sisusb
,
1
,
0
,
tempbuf
,
8192
,
0
,
1
,
NULL
,
16
,
0
);
vfree
(
tempbuf
);
/* Upload user font (and reset current slot) */
if
(
sisusb
->
font_backup
)
{
ret
|=
sisusbcon_do_font_op
(
sisusb
,
1
,
2
,
sisusb
->
font_backup
,
8192
,
sisusb
->
font_backup_512
,
1
,
NULL
,
sisusb
->
font_backup_height
,
0
);
if
(
slot
!=
2
)
sisusbcon_do_font_op
(
sisusb
,
1
,
0
,
NULL
,
0
,
0
,
1
,
NULL
,
16
,
0
);
}
if
(
init
&&
!
sisusb
->
scrbuf
)
{
if
((
tempbuf
=
vmalloc
(
8192
)))
{
i
=
4096
;
tempbufb
=
(
u16
*
)
tempbuf
;
while
(
i
--
)
*
(
tempbufb
++
)
=
0x0720
;
i
=
0
;
tempbufb
=
(
u16
*
)
tempbuf
;
while
(
bootlogo
[
i
])
{
*
(
tempbufb
++
)
=
0x0700
|
bootlogo
[
i
++
];
if
(
!
(
i
%
4
))
tempbufb
+=
76
;
}
i
=
0
;
tempbufb
=
(
u16
*
)
tempbuf
+
6
;
while
(
bootstring
[
i
])
*
(
tempbufb
++
)
=
0x0700
|
bootstring
[
i
++
];
ret
|=
sisusb_copy_memory
(
sisusb
,
tempbuf
,
sisusb
->
vrambase
,
8192
,
&
written
);
vfree
(
tempbuf
);
}
}
else
if
(
sisusb
->
scrbuf
)
{
ret
|=
sisusb_copy_memory
(
sisusb
,
(
char
*
)
sisusb
->
scrbuf
,
sisusb
->
vrambase
,
sisusb
->
scrbuf_size
,
&
written
);
}
if
(
sisusb
->
sisusb_cursor_size_from
>=
0
&&
sisusb
->
sisusb_cursor_size_to
>=
0
)
{
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0a
,
sisusb
->
sisusb_cursor_size_from
);
sisusb_setidxregandor
(
sisusb
,
SISCR
,
0x0b
,
0xe0
,
sisusb
->
sisusb_cursor_size_to
);
}
else
{
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0a
,
0x2d
);
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0b
,
0x0e
);
sisusb
->
sisusb_cursor_size_to
=
-
1
;
}
slot
=
sisusb
->
sisusb_cursor_loc
;
if
(
slot
<
0
)
slot
=
0
;
sisusb
->
sisusb_cursor_loc
=
-
1
;
sisusb
->
bad_cursor_pos
=
1
;
sisusb_set_cursor
(
sisusb
,
slot
);
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0c
,
(
sisusb
->
cur_start_addr
>>
8
));
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0d
,
(
sisusb
->
cur_start_addr
&
0xff
));
sisusb
->
textmodedestroyed
=
0
;
/* sisusb->lock is down */
return
ret
;
}
#endif
/* fops */
static
int
...
...
@@ -2329,7 +2609,7 @@ sisusb_open(struct inode *inode, struct file *file)
}
}
/*
increment usage count for the device
*/
/*
Increment usage count for our sisusb
*/
kref_get
(
&
sisusb
->
kref
);
sisusb
->
isopen
=
1
;
...
...
@@ -2340,12 +2620,10 @@ sisusb_open(struct inode *inode, struct file *file)
up
(
&
disconnect_sem
);
printk
(
KERN_DEBUG
"sisusbvga[%d]: opened"
,
sisusb
->
minor
);
return
0
;
}
static
void
void
sisusb_delete
(
struct
kref
*
kref
)
{
struct
sisusb_usb_data
*
sisusb
=
to_sisusb_dev
(
kref
);
...
...
@@ -2359,6 +2637,9 @@ sisusb_delete(struct kref *kref)
sisusb
->
sisusb_dev
=
NULL
;
sisusb_free_buffers
(
sisusb
);
sisusb_free_urbs
(
sisusb
);
#ifdef INCL_SISUSB_CON
kfree
(
sisusb
->
SiS_Pr
);
#endif
kfree
(
sisusb
);
}
...
...
@@ -2395,8 +2676,6 @@ sisusb_release(struct inode *inode, struct file *file)
up
(
&
disconnect_sem
);
printk
(
KERN_DEBUG
"sisusbvga[%d]: released"
,
myminor
);
return
0
;
}
...
...
@@ -2733,6 +3012,12 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
int
retval
,
port
,
length
;
u32
address
;
/* All our commands require the device
* to be initialized.
*/
if
(
!
sisusb
->
devinit
)
return
-
ENODEV
;
port
=
y
->
data3
-
SISUSB_PCI_PSEUDO_IOPORTBASE
+
SISUSB_PCI_IOPORTBASE
;
...
...
@@ -2774,6 +3059,10 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
break
;
case
SUCMD_CLRSCR
:
/* Gfx core must be initialized */
if
(
!
sisusb
->
gfxinit
)
return
-
ENODEV
;
length
=
(
y
->
data0
<<
16
)
|
(
y
->
data1
<<
8
)
|
y
->
data2
;
address
=
y
->
data3
-
SISUSB_PCI_PSEUDO_MEMBASE
+
...
...
@@ -2781,11 +3070,61 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
retval
=
sisusb_clear_vram
(
sisusb
,
address
,
length
);
break
;
case
SUCMD_HANDLETEXTMODE
:
retval
=
0
;
#ifdef INCL_SISUSB_CON
/* Gfx core must be initialized, SiS_Pr must exist */
if
(
!
sisusb
->
gfxinit
||
!
sisusb
->
SiS_Pr
)
return
-
ENODEV
;
switch
(
y
->
data0
)
{
case
0
:
retval
=
sisusb_reset_text_mode
(
sisusb
,
0
);
break
;
case
1
:
sisusb
->
textmodedestroyed
=
1
;
break
;
}
#endif
break
;
#ifdef INCL_SISUSB_CON
case
SUCMD_SETMODE
:
/* Gfx core must be initialized, SiS_Pr must exist */
if
(
!
sisusb
->
gfxinit
||
!
sisusb
->
SiS_Pr
)
return
-
ENODEV
;
retval
=
0
;
sisusb
->
SiS_Pr
->
IOAddress
=
SISUSB_PCI_IOPORTBASE
+
0x30
;
sisusb
->
SiS_Pr
->
sisusb
=
(
void
*
)
sisusb
;
if
(
SiSUSBSetMode
(
sisusb
->
SiS_Pr
,
y
->
data3
))
retval
=
-
EINVAL
;
break
;
case
SUCMD_SETVESAMODE
:
/* Gfx core must be initialized, SiS_Pr must exist */
if
(
!
sisusb
->
gfxinit
||
!
sisusb
->
SiS_Pr
)
return
-
ENODEV
;
retval
=
0
;
sisusb
->
SiS_Pr
->
IOAddress
=
SISUSB_PCI_IOPORTBASE
+
0x30
;
sisusb
->
SiS_Pr
->
sisusb
=
(
void
*
)
sisusb
;
if
(
SiSUSBSetVESAMode
(
sisusb
->
SiS_Pr
,
y
->
data3
))
retval
=
-
EINVAL
;
break
;
#endif
default:
retval
=
-
EINVAL
;
}
if
(
retval
>
0
)
if
(
retval
>
0
)
retval
=
-
EIO
;
return
retval
;
...
...
@@ -2835,6 +3174,11 @@ sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
x
.
sisusb_vramsize
=
sisusb
->
vramsize
;
x
.
sisusb_minor
=
sisusb
->
minor
;
x
.
sisusb_fbdevactive
=
0
;
#ifdef INCL_SISUSB_CON
x
.
sisusb_conactive
=
sisusb
->
haveconsole
?
1
:
0
;
#else
x
.
sisusb_conactive
=
0
;
#endif
if
(
copy_to_user
((
void
__user
*
)
arg
,
&
x
,
sizeof
(
x
)))
retval
=
-
EFAULT
;
...
...
@@ -2895,9 +3239,13 @@ static struct file_operations usb_sisusb_fops = {
};
static
struct
usb_class_driver
usb_sisusb_class
=
{
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
.
name
=
"usb/sisusbvga%d"
,
.
fops
=
&
usb_sisusb_fops
,
.
mode
=
S_IFCHR
|
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
,
#else
.
name
=
"sisusbvga%d"
,
#endif
.
fops
=
&
usb_sisusb_fops
,
.
minor_base
=
SISUSB_MINOR
};
...
...
@@ -2994,12 +3342,25 @@ static int sisusb_probe(struct usb_interface *intf,
printk
(
KERN_INFO
"sisusbvga[%d]: Allocated %d output buffers
\n
"
,
sisusb
->
minor
,
sisusb
->
numobufs
);
#ifdef INCL_SISUSB_CON
/* Allocate our SiS_Pr */
if
(
!
(
sisusb
->
SiS_Pr
=
kmalloc
(
sizeof
(
struct
SiS_Private
),
GFP_KERNEL
)))
{
printk
(
KERN_ERR
"sisusbvga[%d]: Failed to allocate SiS_Pr
\n
"
,
sisusb
->
minor
);
}
#endif
/* Do remaining init stuff */
init_waitqueue_head
(
&
sisusb
->
wait_q
);
usb_set_intfdata
(
intf
,
sisusb
);
usb_get_dev
(
sisusb
->
sisusb_dev
);
sisusb
->
present
=
1
;
#ifdef SISUSB_OLD_CONFIG_COMPAT
{
int
ret
;
...
...
@@ -3014,14 +3375,19 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb
->
minor
);
else
sisusb
->
ioctl32registered
=
1
;
}
#endif
sisusb
->
present
=
1
;
if
(
dev
->
speed
==
USB_SPEED_HIGH
)
{
if
(
sisusb_init_gfxdevice
(
sisusb
,
1
))
int
initscreen
=
1
;
#ifdef INCL_SISUSB_CON
if
(
sisusb_first_vc
>
0
&&
sisusb_last_vc
>
0
&&
sisusb_first_vc
<=
sisusb_last_vc
&&
sisusb_last_vc
<=
MAX_NR_CONSOLES
)
initscreen
=
0
;
#endif
if
(
sisusb_init_gfxdevice
(
sisusb
,
initscreen
))
printk
(
KERN_ERR
"sisusbvga[%d]: Failed to early "
"initialize device
\n
"
,
...
...
@@ -3035,6 +3401,16 @@ static int sisusb_probe(struct usb_interface *intf,
sisusb
->
ready
=
1
;
#ifdef SISUSBENDIANTEST
printk
(
KERN_DEBUG
"sisusb: *** RWTEST ***
\n
"
);
sisusb_testreadwrite
(
sisusb
);
printk
(
KERN_DEBUG
"sisusb: *** RWTEST END ***
\n
"
);
#endif
#ifdef INCL_SISUSB_CON
sisusb_console_init
(
sisusb
,
sisusb_first_vc
,
sisusb_last_vc
);
#endif
return
0
;
error_4:
...
...
@@ -3053,13 +3429,20 @@ static void sisusb_disconnect(struct usb_interface *intf)
struct
sisusb_usb_data
*
sisusb
;
int
minor
;
down
(
&
disconnect_sem
);
/* This should *not* happen */
if
(
!
(
sisusb
=
usb_get_intfdata
(
intf
)))
{
up
(
&
disconnect_sem
);
if
(
!
(
sisusb
=
usb_get_intfdata
(
intf
)))
return
;
}
#ifdef INCL_SISUSB_CON
sisusb_console_exit
(
sisusb
);
#endif
/* The above code doesn't need the disconnect
* semaphore to be down; its meaning is to
* protect all other routines from the disconnect
* case, not the other way round.
*/
down
(
&
disconnect_sem
);
down
(
&
sisusb
->
lock
);
...
...
@@ -3123,11 +3506,17 @@ static int __init usb_sisusb_init(void)
{
int
retval
;
#ifdef INCL_SISUSB_CON
sisusb_init_concode
();
#endif
if
(
!
(
retval
=
usb_register
(
&
sisusb_driver
)))
{
printk
(
KERN_INFO
"sisusb: Driver version %d.%d.%d
\n
"
,
SISUSB_VERSION
,
SISUSB_REVISION
,
SISUSB_PATCHLEVEL
);
printk
(
KERN_INFO
"sisusb: Copyright (C) 2005 Thomas Winischhofer
\n
"
);
}
return
retval
;
...
...
@@ -3142,6 +3531,6 @@ module_init(usb_sisusb_init);
module_exit
(
usb_sisusb_exit
);
MODULE_AUTHOR
(
"Thomas Winischhofer <thomas@winischhofer.net>"
);
MODULE_DESCRIPTION
(
"sisusb - Driver for Net2280/SiS315-based USB2VGA dongles"
);
MODULE_DESCRIPTION
(
"sisusb
vga
- Driver for Net2280/SiS315-based USB2VGA dongles"
);
MODULE_LICENSE
(
"GPL"
);
drivers/usb/misc/sisusbvga/sisusb.h
View file @
cc6120c6
...
...
@@ -46,15 +46,36 @@
#endif
#endif
/* For older kernels, support for text consoles is by default
* off. To ensable text console support, change the following:
*/
#if 0
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
#define CONFIG_USB_SISUSBVGA_CON
#endif
#endif
/* Version Information */
#define SISUSB_VERSION 0
#define SISUSB_REVISION 0
#define SISUSB_PATCHLEVEL 7
#define SISUSB_PATCHLEVEL 8
/* Include console and mode switching code? */
#ifdef CONFIG_USB_SISUSBVGA_CON
#define INCL_SISUSB_CON 1
#endif
#ifdef INCL_SISUSB_CON
#include <linux/console.h>
#include <linux/vt_kern.h>
#include "sisusb_struct.h"
#endif
/* USB related */
#define SISUSB_MINOR
133
/* FIXME
*/
#define SISUSB_MINOR
133
/* official
*/
/* Size of the sisusb input/output buffers */
#define SISUSB_IBUF_SIZE 0x01000
...
...
@@ -131,6 +152,26 @@ struct sisusb_usb_data {
unsigned
char
gfxinit
;
/* graphics core initialized? */
unsigned
short
chipid
,
chipvendor
;
unsigned
short
chiprevision
;
#ifdef INCL_SISUSB_CON
struct
SiS_Private
*
SiS_Pr
;
unsigned
long
scrbuf
;
unsigned
int
scrbuf_size
;
int
haveconsole
,
con_first
,
con_last
;
int
havethisconsole
[
MAX_NR_CONSOLES
];
int
textmodedestroyed
;
unsigned
int
sisusb_num_columns
;
/* real number, not vt's idea */
int
cur_start_addr
,
con_rolled_over
;
int
sisusb_cursor_loc
,
bad_cursor_pos
;
int
sisusb_cursor_size_from
;
int
sisusb_cursor_size_to
;
int
current_font_height
,
current_font_512
;
int
font_backup_size
,
font_backup_height
,
font_backup_512
;
char
*
font_backup
;
int
font_slot
;
struct
vc_data
*
sisusb_display_fg
;
int
is_gfx
;
int
con_blanked
;
#endif
};
#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
...
...
@@ -249,7 +290,9 @@ struct sisusb_info {
__u32
sisusb_fbdevactive
;
/* != 0 if framebuffer device active */
__u8
sisusb_reserved
[
32
];
/* for future use */
__u32
sisusb_conactive
;
/* != 0 if console driver active */
__u8
sisusb_reserved
[
28
];
/* for future use */
};
struct
sisusb_command
{
...
...
@@ -270,9 +313,15 @@ struct sisusb_command {
#define SUCMD_CLRSCR 0x07
/* data0:1:2 = length, data3 = address */
#define SUCMD_HANDLETEXTMODE 0x08
/* Reset/destroy text mode */
#define SUCMD_SETMODE 0x09
/* Set a display mode (data3 = SiS mode) */
#define SUCMD_SETVESAMODE 0x0a
/* Set a display mode (data3 = VESA mode) */
#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
#endif
/* SISUSB_H */
drivers/usb/misc/sisusbvga/sisusb_con.c
0 → 100644
View file @
cc6120c6
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
* VGA text mode console part
*
* Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
* terms of the GPL v2.
*
* Otherwise, the following license terms apply:
*
* * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions
* * are met:
* * 1) Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* * 2) Redistributions in binary form must reproduce the above copyright
* * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific psisusbr written permission.
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
* Portions based on vgacon.c which are
* Created 28 Sep 1997 by Geert Uytterhoeven
* Rewritten by Martin Mares <mj@ucw.cz>, July 1998
* based on code Copyright (C) 1991, 1992 Linus Torvalds
* 1995 Jay Estabrook
*
* A note on using in_atomic() in here: We can't handle console
* calls from non-schedulable context due to our USB-dependend
* nature. For now, this driver just ignores any calls if it
* detects this state.
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/spinlock.h>
#include <linux/kref.h>
#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include "sisusb.h"
#ifdef INCL_SISUSB_CON
extern
int
sisusb_setreg
(
struct
sisusb_usb_data
*
,
int
,
u8
);
extern
int
sisusb_getreg
(
struct
sisusb_usb_data
*
,
int
,
u8
*
);
extern
int
sisusb_setidxreg
(
struct
sisusb_usb_data
*
,
int
,
u8
,
u8
);
extern
int
sisusb_getidxreg
(
struct
sisusb_usb_data
*
,
int
,
u8
,
u8
*
);
extern
int
sisusb_setidxregor
(
struct
sisusb_usb_data
*
,
int
,
u8
,
u8
);
extern
int
sisusb_setidxregand
(
struct
sisusb_usb_data
*
,
int
,
u8
,
u8
);
extern
int
sisusb_setidxregandor
(
struct
sisusb_usb_data
*
,
int
,
u8
,
u8
,
u8
);
extern
int
sisusb_writeb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
data
);
extern
int
sisusb_readb
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u8
*
data
);
extern
int
sisusb_writew
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
data
);
extern
int
sisusb_readw
(
struct
sisusb_usb_data
*
sisusb
,
u32
adr
,
u16
*
data
);
extern
int
sisusb_copy_memory
(
struct
sisusb_usb_data
*
sisusb
,
char
*
src
,
u32
dest
,
int
length
,
size_t
*
bytes_written
);
extern
void
sisusb_delete
(
struct
kref
*
kref
);
extern
int
sisusb_reset_text_mode
(
struct
sisusb_usb_data
*
sisusb
,
int
init
);
extern
int
SiSUSBSetMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
);
#define sisusbcon_writew(val, addr) (*(addr) = (val))
#define sisusbcon_readw(addr) (*(addr))
#define sisusbcon_memmovew(d, s, c) memmove(d, s, c)
#define sisusbcon_memcpyw(d, s, c) memcpy(d, s, c)
/* vc_data -> sisusb conversion table */
static
struct
sisusb_usb_data
*
mysisusbs
[
MAX_NR_CONSOLES
];
/* Forward declaration */
static
const
struct
consw
sisusb_con
;
extern
struct
semaphore
disconnect_sem
;
static
inline
void
sisusbcon_memsetw
(
u16
*
s
,
u16
c
,
unsigned
int
count
)
{
count
/=
2
;
while
(
count
--
)
sisusbcon_writew
(
c
,
s
++
);
}
static
inline
void
sisusb_initialize
(
struct
sisusb_usb_data
*
sisusb
)
{
/* Reset cursor and start address */
if
(
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0c
,
0x00
))
return
;
if
(
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0d
,
0x00
))
return
;
if
(
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0e
,
0x00
))
return
;
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0f
,
0x00
);
}
static
inline
void
sisusbcon_set_start_address
(
struct
sisusb_usb_data
*
sisusb
,
struct
vc_data
*
c
)
{
sisusb
->
cur_start_addr
=
(
c
->
vc_visible_origin
-
sisusb
->
scrbuf
)
/
2
;
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0c
,
(
sisusb
->
cur_start_addr
>>
8
));
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0d
,
(
sisusb
->
cur_start_addr
&
0xff
));
}
void
sisusb_set_cursor
(
struct
sisusb_usb_data
*
sisusb
,
unsigned
int
location
)
{
if
(
sisusb
->
sisusb_cursor_loc
==
location
)
return
;
sisusb
->
sisusb_cursor_loc
=
location
;
/* Hardware bug: Text cursor appears twice or not at all
* at some positions. Work around it with the cursor skew
* bits.
*/
if
((
location
&
0x0007
)
==
0x0007
)
{
sisusb
->
bad_cursor_pos
=
1
;
location
--
;
if
(
sisusb_setidxregandor
(
sisusb
,
SISCR
,
0x0b
,
0x1f
,
0x20
))
return
;
}
else
if
(
sisusb
->
bad_cursor_pos
)
{
if
(
sisusb_setidxregand
(
sisusb
,
SISCR
,
0x0b
,
0x1f
))
return
;
sisusb
->
bad_cursor_pos
=
0
;
}
if
(
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0e
,
(
location
>>
8
)))
return
;
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0f
,
(
location
&
0xff
));
}
static
inline
struct
sisusb_usb_data
*
sisusb_get_sisusb
(
unsigned
short
console
)
{
return
mysisusbs
[
console
];
}
static
inline
int
sisusb_sisusb_valid
(
struct
sisusb_usb_data
*
sisusb
)
{
if
(
!
sisusb
->
present
||
!
sisusb
->
ready
||
!
sisusb
->
sisusb_dev
)
return
0
;
return
1
;
}
static
struct
sisusb_usb_data
*
sisusb_get_sisusb_lock_and_check
(
unsigned
short
console
)
{
struct
sisusb_usb_data
*
sisusb
;
/* We can't handle console calls in non-schedulable
* context due to our locks and the USB transport.
* So we simply ignore them. This should only affect
* some calls to printk.
*/
if
(
in_atomic
())
return
NULL
;
if
(
!
(
sisusb
=
sisusb_get_sisusb
(
console
)))
return
NULL
;
down
(
&
sisusb
->
lock
);
if
(
!
sisusb_sisusb_valid
(
sisusb
)
||
!
sisusb
->
havethisconsole
[
console
])
{
up
(
&
sisusb
->
lock
);
return
NULL
;
}
return
sisusb
;
}
static
int
sisusb_is_inactive
(
struct
vc_data
*
c
,
struct
sisusb_usb_data
*
sisusb
)
{
if
(
sisusb
->
is_gfx
||
sisusb
->
textmodedestroyed
||
c
->
vc_mode
!=
KD_TEXT
)
return
1
;
return
0
;
}
/* con_startup console interface routine */
static
const
char
*
sisusbcon_startup
(
void
)
{
return
"SISUSBCON"
;
}
/* con_init console interface routine */
static
void
sisusbcon_init
(
struct
vc_data
*
c
,
int
init
)
{
struct
sisusb_usb_data
*
sisusb
;
int
cols
,
rows
;
/* This is called by take_over_console(),
* ie by us/under our control. It is
* only called after text mode and fonts
* are set up/restored.
*/
down
(
&
disconnect_sem
);
if
(
!
(
sisusb
=
sisusb_get_sisusb
(
c
->
vc_num
)))
{
up
(
&
disconnect_sem
);
return
;
}
down
(
&
sisusb
->
lock
);
if
(
!
sisusb_sisusb_valid
(
sisusb
))
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
return
;
}
c
->
vc_can_do_color
=
1
;
c
->
vc_complement_mask
=
0x7700
;
c
->
vc_hi_font_mask
=
sisusb
->
current_font_512
?
0x0800
:
0
;
sisusb
->
haveconsole
=
1
;
sisusb
->
havethisconsole
[
c
->
vc_num
]
=
1
;
/* We only support 640x400 */
c
->
vc_scan_lines
=
400
;
c
->
vc_font
.
height
=
sisusb
->
current_font_height
;
/* We only support width = 8 */
cols
=
80
;
rows
=
c
->
vc_scan_lines
/
c
->
vc_font
.
height
;
/* Increment usage count for our sisusb.
* Doing so saves us from upping/downing
* the disconnect semaphore; we can't
* lose our sisusb until this is undone
* in con_deinit. For all other console
* interface functions, it suffices to
* use sisusb->lock and do a quick check
* of sisusb for device disconnection.
*/
kref_get
(
&
sisusb
->
kref
);
if
(
!*
c
->
vc_uni_pagedir_loc
)
con_set_default_unimap
(
c
);
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
if
(
init
)
{
c
->
vc_cols
=
cols
;
c
->
vc_rows
=
rows
;
}
else
vc_resize
(
c
,
cols
,
rows
);
}
/* con_deinit console interface routine */
static
void
sisusbcon_deinit
(
struct
vc_data
*
c
)
{
struct
sisusb_usb_data
*
sisusb
;
int
i
;
/* This is called by take_over_console()
* and others, ie not under our control.
*/
down
(
&
disconnect_sem
);
if
(
!
(
sisusb
=
sisusb_get_sisusb
(
c
->
vc_num
)))
{
up
(
&
disconnect_sem
);
return
;
}
down
(
&
sisusb
->
lock
);
/* Clear ourselves in mysisusbs */
mysisusbs
[
c
->
vc_num
]
=
NULL
;
sisusb
->
havethisconsole
[
c
->
vc_num
]
=
0
;
/* Free our font buffer if all consoles are gone */
if
(
sisusb
->
font_backup
)
{
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
{
if
(
sisusb
->
havethisconsole
[
c
->
vc_num
])
break
;
}
if
(
i
==
MAX_NR_CONSOLES
)
{
vfree
(
sisusb
->
font_backup
);
sisusb
->
font_backup
=
NULL
;
}
}
up
(
&
sisusb
->
lock
);
/* decrement the usage count on our sisusb */
kref_put
(
&
sisusb
->
kref
,
sisusb_delete
);
up
(
&
disconnect_sem
);
}
/* interface routine */
static
u8
sisusbcon_build_attr
(
struct
vc_data
*
c
,
u8
color
,
u8
intensity
,
u8
blink
,
u8
underline
,
u8
reverse
)
{
u8
attr
=
color
;
if
(
underline
)
attr
=
(
attr
&
0xf0
)
|
c
->
vc_ulcolor
;
else
if
(
intensity
==
0
)
attr
=
(
attr
&
0xf0
)
|
c
->
vc_halfcolor
;
if
(
reverse
)
attr
=
((
attr
)
&
0x88
)
|
((((
attr
)
>>
4
)
|
((
attr
)
<<
4
))
&
0x77
);
if
(
blink
)
attr
^=
0x80
;
if
(
intensity
==
2
)
attr
^=
0x08
;
return
attr
;
}
/* Interface routine */
static
void
sisusbcon_invert_region
(
struct
vc_data
*
vc
,
u16
*
p
,
int
count
)
{
/* Invert a region. This is called with a pointer
* to the console's internal screen buffer. So we
* simply do the inversion there and rely on
* a call to putc(s) to update the real screen.
*/
while
(
count
--
)
{
u16
a
=
sisusbcon_readw
(
p
);
a
=
((
a
)
&
0x88ff
)
|
(((
a
)
&
0x7000
)
>>
4
)
|
(((
a
)
&
0x0700
)
<<
4
);
sisusbcon_writew
(
a
,
p
++
);
}
}
#define SISUSB_VADDR(x,y) \
((u16 *)c->vc_origin + \
(y) * sisusb->sisusb_num_columns + \
(x))
#define SISUSB_HADDR(x,y) \
((u16 *)(sisusb->vrambase + (c->vc_origin - sisusb->scrbuf)) + \
(y) * sisusb->sisusb_num_columns + \
(x))
/* Interface routine */
static
void
sisusbcon_putc
(
struct
vc_data
*
c
,
int
ch
,
int
y
,
int
x
)
{
struct
sisusb_usb_data
*
sisusb
;
ssize_t
written
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
/* Don't need to put the character into buffer ourselves,
* because the vt does this BEFORE calling us.
*/
#if 0
sisusbcon_writew(ch, SISUSB_VADDR(x, y));
#endif
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
sisusb_copy_memory
(
sisusb
,
(
char
*
)
SISUSB_VADDR
(
x
,
y
),
(
u32
)
SISUSB_HADDR
(
x
,
y
),
2
,
&
written
);
up
(
&
sisusb
->
lock
);
}
/* Interface routine */
static
void
sisusbcon_putcs
(
struct
vc_data
*
c
,
const
unsigned
short
*
s
,
int
count
,
int
y
,
int
x
)
{
struct
sisusb_usb_data
*
sisusb
;
ssize_t
written
;
u16
*
dest
;
int
i
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
/* Need to put the characters into the buffer ourselves,
* because the vt does this AFTER calling us.
*/
dest
=
SISUSB_VADDR
(
x
,
y
);
for
(
i
=
count
;
i
>
0
;
i
--
)
sisusbcon_writew
(
sisusbcon_readw
(
s
++
),
dest
++
);
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
sisusb_copy_memory
(
sisusb
,
(
char
*
)
SISUSB_VADDR
(
x
,
y
),
(
u32
)
SISUSB_HADDR
(
x
,
y
),
count
*
2
,
&
written
);
up
(
&
sisusb
->
lock
);
}
/* Interface routine */
static
void
sisusbcon_clear
(
struct
vc_data
*
c
,
int
y
,
int
x
,
int
height
,
int
width
)
{
struct
sisusb_usb_data
*
sisusb
;
u16
eattr
=
c
->
vc_video_erase_char
;
ssize_t
written
;
int
i
,
length
,
cols
;
u16
*
dest
;
if
(
width
<=
0
||
height
<=
0
)
return
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
/* Need to clear buffer ourselves, because the vt does
* this AFTER calling us.
*/
dest
=
SISUSB_VADDR
(
x
,
y
);
cols
=
sisusb
->
sisusb_num_columns
;
if
(
width
>
cols
)
width
=
cols
;
if
(
x
==
0
&&
width
>=
c
->
vc_cols
)
{
sisusbcon_memsetw
(
dest
,
eattr
,
height
*
cols
*
2
);
}
else
{
for
(
i
=
height
;
i
>
0
;
i
--
,
dest
+=
cols
)
sisusbcon_memsetw
(
dest
,
eattr
,
width
*
2
);
}
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
length
=
((
height
*
cols
)
-
x
-
(
cols
-
width
-
x
))
*
2
;
sisusb_copy_memory
(
sisusb
,
(
unsigned
char
*
)
SISUSB_VADDR
(
x
,
y
),
(
u32
)
SISUSB_HADDR
(
x
,
y
),
length
,
&
written
);
up
(
&
sisusb
->
lock
);
}
/* Interface routine */
static
void
sisusbcon_bmove
(
struct
vc_data
*
c
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
{
struct
sisusb_usb_data
*
sisusb
;
ssize_t
written
;
int
cols
,
length
;
#if 0
u16 *src, *dest;
int i;
#endif
if
(
width
<=
0
||
height
<=
0
)
return
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
cols
=
sisusb
->
sisusb_num_columns
;
/* Don't need to move data outselves, because
* vt does this BEFORE calling us.
* This is only used by vt's insert/deletechar.
*/
#if 0
if (sx == 0 && dx == 0 && width >= c->vc_cols && width <= cols) {
sisusbcon_memmovew(SISUSB_VADDR(0, dy), SISUSB_VADDR(0, sy),
height * width * 2);
} else if (dy < sy || (dy == sy && dx < sx)) {
src = SISUSB_VADDR(sx, sy);
dest = SISUSB_VADDR(dx, dy);
for (i = height; i > 0; i--) {
sisusbcon_memmovew(dest, src, width * 2);
src += cols;
dest += cols;
}
} else {
src = SISUSB_VADDR(sx, sy + height - 1);
dest = SISUSB_VADDR(dx, dy + height - 1);
for (i = height; i > 0; i--) {
sisusbcon_memmovew(dest, src, width * 2);
src -= cols;
dest -= cols;
}
}
#endif
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
length
=
((
height
*
cols
)
-
dx
-
(
cols
-
width
-
dx
))
*
2
;
sisusb_copy_memory
(
sisusb
,
(
unsigned
char
*
)
SISUSB_VADDR
(
dx
,
dy
),
(
u32
)
SISUSB_HADDR
(
dx
,
dy
),
length
,
&
written
);
up
(
&
sisusb
->
lock
);
}
/* interface routine */
static
int
sisusbcon_switch
(
struct
vc_data
*
c
)
{
struct
sisusb_usb_data
*
sisusb
;
ssize_t
written
;
int
length
;
/* Returnvalue 0 means we have fully restored screen,
* and vt doesn't need to call do_update_region().
* Returnvalue != 0 naturally means the opposite.
*/
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
0
;
/* sisusb->lock is down */
/* Don't write to screen if in gfx mode */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
0
;
}
/* That really should not happen. It would mean we are
* being called while the vc is using its private buffer
* as origin.
*/
if
(
c
->
vc_origin
==
(
unsigned
long
)
c
->
vc_screenbuf
)
{
up
(
&
sisusb
->
lock
);
printk
(
KERN_DEBUG
"sisusb: ASSERT ORIGIN != SCREENBUF!
\n
"
);
return
0
;
}
/* Check that we don't copy too much */
length
=
min
((
int
)
c
->
vc_screenbuf_size
,
(
int
)(
sisusb
->
scrbuf
+
sisusb
->
scrbuf_size
-
c
->
vc_origin
));
/* Restore the screen contents */
sisusbcon_memcpyw
((
u16
*
)
c
->
vc_origin
,
(
u16
*
)
c
->
vc_screenbuf
,
length
);
sisusb_copy_memory
(
sisusb
,
(
unsigned
char
*
)
c
->
vc_origin
,
(
u32
)
SISUSB_HADDR
(
0
,
0
),
length
,
&
written
);
up
(
&
sisusb
->
lock
);
return
0
;
}
/* interface routine */
static
void
sisusbcon_save_screen
(
struct
vc_data
*
c
)
{
struct
sisusb_usb_data
*
sisusb
;
int
length
;
/* Save the current screen contents to vc's private
* buffer.
*/
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
/* Check that we don't copy too much */
length
=
min
((
int
)
c
->
vc_screenbuf_size
,
(
int
)(
sisusb
->
scrbuf
+
sisusb
->
scrbuf_size
-
c
->
vc_origin
));
/* Save the screen contents to vc's private buffer */
sisusbcon_memcpyw
((
u16
*
)
c
->
vc_screenbuf
,
(
u16
*
)
c
->
vc_origin
,
length
);
up
(
&
sisusb
->
lock
);
}
/* interface routine */
static
int
sisusbcon_set_palette
(
struct
vc_data
*
c
,
unsigned
char
*
table
)
{
struct
sisusb_usb_data
*
sisusb
;
int
i
,
j
;
/* Return value not used by vt */
if
(
!
CON_IS_VISIBLE
(
c
))
return
-
EINVAL
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
-
EINVAL
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
-
EINVAL
;
}
for
(
i
=
j
=
0
;
i
<
16
;
i
++
)
{
if
(
sisusb_setreg
(
sisusb
,
SISCOLIDX
,
table
[
i
]))
break
;
if
(
sisusb_setreg
(
sisusb
,
SISCOLDATA
,
c
->
vc_palette
[
j
++
]
>>
2
))
break
;
if
(
sisusb_setreg
(
sisusb
,
SISCOLDATA
,
c
->
vc_palette
[
j
++
]
>>
2
))
break
;
if
(
sisusb_setreg
(
sisusb
,
SISCOLDATA
,
c
->
vc_palette
[
j
++
]
>>
2
))
break
;
}
up
(
&
sisusb
->
lock
);
return
0
;
}
/* interface routine */
static
int
sisusbcon_blank
(
struct
vc_data
*
c
,
int
blank
,
int
mode_switch
)
{
struct
sisusb_usb_data
*
sisusb
;
u8
sr1
,
cr17
,
pmreg
,
cr63
;
ssize_t
written
;
int
ret
=
0
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
0
;
/* sisusb->lock is down */
if
(
mode_switch
)
sisusb
->
is_gfx
=
blank
?
1
:
0
;
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
0
;
}
switch
(
blank
)
{
case
1
:
/* Normal blanking: Clear screen */
case
-
1
:
sisusbcon_memsetw
((
u16
*
)
c
->
vc_origin
,
c
->
vc_video_erase_char
,
c
->
vc_screenbuf_size
);
sisusb_copy_memory
(
sisusb
,
(
unsigned
char
*
)
c
->
vc_origin
,
(
u32
)(
sisusb
->
vrambase
+
(
c
->
vc_origin
-
sisusb
->
scrbuf
)),
c
->
vc_screenbuf_size
,
&
written
);
sisusb
->
con_blanked
=
1
;
ret
=
1
;
break
;
default:
/* VESA blanking */
switch
(
blank
)
{
case
0
:
/* Unblank */
sr1
=
0x00
;
cr17
=
0x80
;
pmreg
=
0x00
;
cr63
=
0x00
;
ret
=
1
;
sisusb
->
con_blanked
=
0
;
break
;
case
VESA_VSYNC_SUSPEND
+
1
:
sr1
=
0x20
;
cr17
=
0x80
;
pmreg
=
0x80
;
cr63
=
0x40
;
break
;
case
VESA_HSYNC_SUSPEND
+
1
:
sr1
=
0x20
;
cr17
=
0x80
;
pmreg
=
0x40
;
cr63
=
0x40
;
break
;
case
VESA_POWERDOWN
+
1
:
sr1
=
0x20
;
cr17
=
0x00
;
pmreg
=
0xc0
;
cr63
=
0x40
;
break
;
default:
up
(
&
sisusb
->
lock
);
return
-
EINVAL
;
}
sisusb_setidxregandor
(
sisusb
,
SISSR
,
0x01
,
~
0x20
,
sr1
);
sisusb_setidxregandor
(
sisusb
,
SISCR
,
0x17
,
0x7f
,
cr17
);
sisusb_setidxregandor
(
sisusb
,
SISSR
,
0x1f
,
0x3f
,
pmreg
);
sisusb_setidxregandor
(
sisusb
,
SISCR
,
0x63
,
0xbf
,
cr63
);
}
up
(
&
sisusb
->
lock
);
return
ret
;
}
/* interface routine */
static
int
sisusbcon_scrolldelta
(
struct
vc_data
*
c
,
int
lines
)
{
struct
sisusb_usb_data
*
sisusb
;
int
margin
=
c
->
vc_size_row
*
4
;
int
ul
,
we
,
p
,
st
;
/* The return value does not seem to be used */
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
0
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
0
;
}
if
(
!
lines
)
/* Turn scrollback off */
c
->
vc_visible_origin
=
c
->
vc_origin
;
else
{
if
(
sisusb
->
con_rolled_over
>
(
c
->
vc_scr_end
-
sisusb
->
scrbuf
)
+
margin
)
{
ul
=
c
->
vc_scr_end
-
sisusb
->
scrbuf
;
we
=
sisusb
->
con_rolled_over
+
c
->
vc_size_row
;
}
else
{
ul
=
0
;
we
=
sisusb
->
scrbuf_size
;
}
p
=
(
c
->
vc_visible_origin
-
sisusb
->
scrbuf
-
ul
+
we
)
%
we
+
lines
*
c
->
vc_size_row
;
st
=
(
c
->
vc_origin
-
sisusb
->
scrbuf
-
ul
+
we
)
%
we
;
if
(
st
<
2
*
margin
)
margin
=
0
;
if
(
p
<
margin
)
p
=
0
;
if
(
p
>
st
-
margin
)
p
=
st
;
c
->
vc_visible_origin
=
sisusb
->
scrbuf
+
(
p
+
ul
)
%
we
;
}
sisusbcon_set_start_address
(
sisusb
,
c
);
up
(
&
sisusb
->
lock
);
return
1
;
}
/* Interface routine */
static
void
sisusbcon_cursor
(
struct
vc_data
*
c
,
int
mode
)
{
struct
sisusb_usb_data
*
sisusb
;
int
from
,
to
,
baseline
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
;
}
if
(
c
->
vc_origin
!=
c
->
vc_visible_origin
)
{
c
->
vc_visible_origin
=
c
->
vc_origin
;
sisusbcon_set_start_address
(
sisusb
,
c
);
}
if
(
mode
==
CM_ERASE
)
{
sisusb_setidxregor
(
sisusb
,
SISCR
,
0x0a
,
0x20
);
sisusb
->
sisusb_cursor_size_to
=
-
1
;
up
(
&
sisusb
->
lock
);
return
;
}
sisusb_set_cursor
(
sisusb
,
(
c
->
vc_pos
-
sisusb
->
scrbuf
)
/
2
);
baseline
=
c
->
vc_font
.
height
-
(
c
->
vc_font
.
height
<
10
?
1
:
2
);
switch
(
c
->
vc_cursor_type
&
0x0f
)
{
case
CUR_BLOCK
:
from
=
1
;
to
=
c
->
vc_font
.
height
;
break
;
case
CUR_TWO_THIRDS
:
from
=
c
->
vc_font
.
height
/
3
;
to
=
baseline
;
break
;
case
CUR_LOWER_HALF
:
from
=
c
->
vc_font
.
height
/
2
;
to
=
baseline
;
break
;
case
CUR_LOWER_THIRD
:
from
=
(
c
->
vc_font
.
height
*
2
)
/
3
;
to
=
baseline
;
break
;
case
CUR_NONE
:
from
=
31
;
to
=
30
;
break
;
default:
case
CUR_UNDERLINE
:
from
=
baseline
-
1
;
to
=
baseline
;
break
;
}
if
(
sisusb
->
sisusb_cursor_size_from
!=
from
||
sisusb
->
sisusb_cursor_size_to
!=
to
)
{
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x0a
,
from
);
sisusb_setidxregandor
(
sisusb
,
SISCR
,
0x0b
,
0xe0
,
to
);
sisusb
->
sisusb_cursor_size_from
=
from
;
sisusb
->
sisusb_cursor_size_to
=
to
;
}
up
(
&
sisusb
->
lock
);
}
static
int
sisusbcon_scroll_area
(
struct
vc_data
*
c
,
struct
sisusb_usb_data
*
sisusb
,
int
t
,
int
b
,
int
dir
,
int
lines
)
{
int
cols
=
sisusb
->
sisusb_num_columns
;
int
length
=
((
b
-
t
)
*
cols
)
*
2
;
u16
eattr
=
c
->
vc_video_erase_char
;
ssize_t
written
;
/* sisusb->lock is down */
/* Scroll an area which does not match the
* visible screen's dimensions. This needs
* to be done separately, as it does not
* use hardware panning.
*/
switch
(
dir
)
{
case
SM_UP
:
sisusbcon_memmovew
(
SISUSB_VADDR
(
0
,
t
),
SISUSB_VADDR
(
0
,
t
+
lines
),
(
b
-
t
-
lines
)
*
cols
*
2
);
sisusbcon_memsetw
(
SISUSB_VADDR
(
0
,
b
-
lines
),
eattr
,
lines
*
cols
*
2
);
break
;
case
SM_DOWN
:
sisusbcon_memmovew
(
SISUSB_VADDR
(
0
,
t
+
lines
),
SISUSB_VADDR
(
0
,
t
),
(
b
-
t
-
lines
)
*
cols
*
2
);
sisusbcon_memsetw
(
SISUSB_VADDR
(
0
,
t
),
eattr
,
lines
*
cols
*
2
);
break
;
}
sisusb_copy_memory
(
sisusb
,
(
char
*
)
SISUSB_VADDR
(
0
,
t
),
(
u32
)
SISUSB_HADDR
(
0
,
t
),
length
,
&
written
);
up
(
&
sisusb
->
lock
);
return
1
;
}
/* Interface routine */
static
int
sisusbcon_scroll
(
struct
vc_data
*
c
,
int
t
,
int
b
,
int
dir
,
int
lines
)
{
struct
sisusb_usb_data
*
sisusb
;
u16
eattr
=
c
->
vc_video_erase_char
;
ssize_t
written
;
int
copyall
=
0
;
unsigned
long
oldorigin
;
unsigned
int
delta
=
lines
*
c
->
vc_size_row
;
u32
originoffset
;
/* Returning != 0 means we have done the scrolling successfully.
* Returning 0 makes vt do the scrolling on its own.
* Note that con_scroll is only called if the console is
* visible. In that case, the origin should be our buffer,
* not the vt's private one.
*/
if
(
!
lines
)
return
1
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
0
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
))
{
up
(
&
sisusb
->
lock
);
return
0
;
}
/* Special case */
if
(
t
||
b
!=
c
->
vc_rows
)
return
sisusbcon_scroll_area
(
c
,
sisusb
,
t
,
b
,
dir
,
lines
);
if
(
c
->
vc_origin
!=
c
->
vc_visible_origin
)
{
c
->
vc_visible_origin
=
c
->
vc_origin
;
sisusbcon_set_start_address
(
sisusb
,
c
);
}
/* limit amount to maximum realistic size */
if
(
lines
>
c
->
vc_rows
)
lines
=
c
->
vc_rows
;
oldorigin
=
c
->
vc_origin
;
switch
(
dir
)
{
case
SM_UP
:
if
(
c
->
vc_scr_end
+
delta
>=
sisusb
->
scrbuf
+
sisusb
->
scrbuf_size
)
{
sisusbcon_memcpyw
((
u16
*
)
sisusb
->
scrbuf
,
(
u16
*
)(
oldorigin
+
delta
),
c
->
vc_screenbuf_size
-
delta
);
c
->
vc_origin
=
sisusb
->
scrbuf
;
sisusb
->
con_rolled_over
=
oldorigin
-
sisusb
->
scrbuf
;
copyall
=
1
;
}
else
c
->
vc_origin
+=
delta
;
sisusbcon_memsetw
(
(
u16
*
)(
c
->
vc_origin
+
c
->
vc_screenbuf_size
-
delta
),
eattr
,
delta
);
break
;
case
SM_DOWN
:
if
(
oldorigin
-
delta
<
sisusb
->
scrbuf
)
{
sisusbcon_memmovew
((
u16
*
)(
sisusb
->
scrbuf
+
sisusb
->
scrbuf_size
-
c
->
vc_screenbuf_size
+
delta
),
(
u16
*
)
oldorigin
,
c
->
vc_screenbuf_size
-
delta
);
c
->
vc_origin
=
sisusb
->
scrbuf
+
sisusb
->
scrbuf_size
-
c
->
vc_screenbuf_size
;
sisusb
->
con_rolled_over
=
0
;
copyall
=
1
;
}
else
c
->
vc_origin
-=
delta
;
c
->
vc_scr_end
=
c
->
vc_origin
+
c
->
vc_screenbuf_size
;
scr_memsetw
((
u16
*
)(
c
->
vc_origin
),
eattr
,
delta
);
break
;
}
originoffset
=
(
u32
)(
c
->
vc_origin
-
sisusb
->
scrbuf
);
if
(
copyall
)
sisusb_copy_memory
(
sisusb
,
(
char
*
)
c
->
vc_origin
,
(
u32
)(
sisusb
->
vrambase
+
originoffset
),
c
->
vc_screenbuf_size
,
&
written
);
else
if
(
dir
==
SM_UP
)
sisusb_copy_memory
(
sisusb
,
(
char
*
)
c
->
vc_origin
+
c
->
vc_screenbuf_size
-
delta
,
(
u32
)
sisusb
->
vrambase
+
originoffset
+
c
->
vc_screenbuf_size
-
delta
,
delta
,
&
written
);
else
sisusb_copy_memory
(
sisusb
,
(
char
*
)
c
->
vc_origin
,
(
u32
)(
sisusb
->
vrambase
+
originoffset
),
delta
,
&
written
);
c
->
vc_scr_end
=
c
->
vc_origin
+
c
->
vc_screenbuf_size
;
c
->
vc_visible_origin
=
c
->
vc_origin
;
sisusbcon_set_start_address
(
sisusb
,
c
);
c
->
vc_pos
=
c
->
vc_pos
-
oldorigin
+
c
->
vc_origin
;
up
(
&
sisusb
->
lock
);
return
1
;
}
/* Interface routine */
static
int
sisusbcon_set_origin
(
struct
vc_data
*
c
)
{
struct
sisusb_usb_data
*
sisusb
;
/* Returning != 0 means we were successful.
* Returning 0 will vt make to use its own
* screenbuffer as the origin.
*/
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
0
;
/* sisusb->lock is down */
if
(
sisusb_is_inactive
(
c
,
sisusb
)
||
sisusb
->
con_blanked
)
{
up
(
&
sisusb
->
lock
);
return
0
;
}
c
->
vc_origin
=
c
->
vc_visible_origin
=
sisusb
->
scrbuf
;
sisusbcon_set_start_address
(
sisusb
,
c
);
sisusb
->
con_rolled_over
=
0
;
up
(
&
sisusb
->
lock
);
return
1
;
}
/* Interface routine */
static
int
sisusbcon_resize
(
struct
vc_data
*
c
,
unsigned
int
newcols
,
unsigned
int
newrows
)
{
struct
sisusb_usb_data
*
sisusb
;
int
fh
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
-
ENODEV
;
fh
=
sisusb
->
current_font_height
;
up
(
&
sisusb
->
lock
);
/* We are quite unflexible as regards resizing. The vt code
* handles sizes where the line length isn't equal the pitch
* quite badly. As regards the rows, our panning tricks only
* work well if the number of rows equals the visible number
* of rows.
*/
if
(
newcols
!=
80
||
c
->
vc_scan_lines
/
fh
!=
newrows
)
return
-
EINVAL
;
return
0
;
}
int
sisusbcon_do_font_op
(
struct
sisusb_usb_data
*
sisusb
,
int
set
,
int
slot
,
u8
*
arg
,
int
cmapsz
,
int
ch512
,
int
dorecalc
,
struct
vc_data
*
c
,
int
fh
,
int
uplock
)
{
int
font_select
=
0x00
,
i
,
err
=
0
;
u32
offset
=
0
;
u8
dummy
;
/* sisusb->lock is down */
/*
* The default font is kept in slot 0.
* A user font is loaded in slot 2 (256 ch)
* or 2+3 (512 ch).
*/
if
((
slot
!=
0
&&
slot
!=
2
)
||
!
fh
)
{
if
(
uplock
)
up
(
&
sisusb
->
lock
);
return
-
EINVAL
;
}
if
(
set
)
sisusb
->
font_slot
=
slot
;
/* Default font is always 256 */
if
(
slot
==
0
)
ch512
=
0
;
else
offset
=
4
*
cmapsz
;
font_select
=
(
slot
==
0
)
?
0x00
:
(
ch512
?
0x0e
:
0x0a
);
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x00
,
0x01
);
/* Reset */
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x02
,
0x04
);
/* Write to plane 2 */
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x04
,
0x07
);
/* Memory mode a0-bf */
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x00
,
0x03
);
/* Reset */
if
(
err
)
goto
font_op_error
;
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x04
,
0x03
);
/* Select plane read 2 */
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x05
,
0x00
);
/* Disable odd/even */
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x06
,
0x00
);
/* Address range a0-bf */
if
(
err
)
goto
font_op_error
;
if
(
arg
)
{
if
(
set
)
for
(
i
=
0
;
i
<
cmapsz
;
i
++
)
{
err
|=
sisusb_writeb
(
sisusb
,
sisusb
->
vrambase
+
offset
+
i
,
arg
[
i
]);
if
(
err
)
break
;
}
else
for
(
i
=
0
;
i
<
cmapsz
;
i
++
)
{
err
|=
sisusb_readb
(
sisusb
,
sisusb
->
vrambase
+
offset
+
i
,
&
arg
[
i
]);
if
(
err
)
break
;
}
/*
* In 512-character mode, the character map is not contiguous if
* we want to remain EGA compatible -- which we do
*/
if
(
ch512
)
{
if
(
set
)
for
(
i
=
0
;
i
<
cmapsz
;
i
++
)
{
err
|=
sisusb_writeb
(
sisusb
,
sisusb
->
vrambase
+
offset
+
(
2
*
cmapsz
)
+
i
,
arg
[
cmapsz
+
i
]);
if
(
err
)
break
;
}
else
for
(
i
=
0
;
i
<
cmapsz
;
i
++
)
{
err
|=
sisusb_readb
(
sisusb
,
sisusb
->
vrambase
+
offset
+
(
2
*
cmapsz
)
+
i
,
&
arg
[
cmapsz
+
i
]);
if
(
err
)
break
;
}
}
}
if
(
err
)
goto
font_op_error
;
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x00
,
0x01
);
/* Reset */
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x02
,
0x03
);
/* Write to planes 0+1 */
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x04
,
0x03
);
/* Memory mode a0-bf */
if
(
set
)
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x03
,
font_select
);
err
|=
sisusb_setidxreg
(
sisusb
,
SISSR
,
0x00
,
0x03
);
/* Reset end */
if
(
err
)
goto
font_op_error
;
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x04
,
0x00
);
/* Select plane read 0 */
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x05
,
0x10
);
/* Enable odd/even */
err
|=
sisusb_setidxreg
(
sisusb
,
SISGR
,
0x06
,
0x06
);
/* Address range b8-bf */
if
(
err
)
goto
font_op_error
;
if
((
set
)
&&
(
ch512
!=
sisusb
->
current_font_512
))
{
/* Font is shared among all our consoles.
* And so is the hi_font_mask.
*/
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
{
struct
vc_data
*
c
=
vc_cons
[
i
].
d
;
if
(
c
&&
c
->
vc_sw
==
&
sisusb_con
)
c
->
vc_hi_font_mask
=
ch512
?
0x0800
:
0
;
}
sisusb
->
current_font_512
=
ch512
;
/* color plane enable register:
256-char: enable intensity bit
512-char: disable intensity bit */
sisusb_getreg
(
sisusb
,
SISINPSTAT
,
&
dummy
);
sisusb_setreg
(
sisusb
,
SISAR
,
0x12
);
sisusb_setreg
(
sisusb
,
SISAR
,
ch512
?
0x07
:
0x0f
);
sisusb_getreg
(
sisusb
,
SISINPSTAT
,
&
dummy
);
sisusb_setreg
(
sisusb
,
SISAR
,
0x20
);
sisusb_getreg
(
sisusb
,
SISINPSTAT
,
&
dummy
);
}
if
(
dorecalc
)
{
/*
* Adjust the screen to fit a font of a certain height
*/
unsigned
char
ovr
,
vde
,
fsr
;
int
rows
=
0
,
maxscan
=
0
;
if
(
c
)
{
/* Number of video rows */
rows
=
c
->
vc_scan_lines
/
fh
;
/* Scan lines to actually display-1 */
maxscan
=
rows
*
fh
-
1
;
/*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",
rows, maxscan, fh, c->vc_scan_lines);*/
sisusb_getidxreg
(
sisusb
,
SISCR
,
0x07
,
&
ovr
);
vde
=
maxscan
&
0xff
;
ovr
=
(
ovr
&
0xbd
)
|
((
maxscan
&
0x100
)
>>
7
)
|
((
maxscan
&
0x200
)
>>
3
);
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x07
,
ovr
);
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x12
,
vde
);
}
sisusb_getidxreg
(
sisusb
,
SISCR
,
0x09
,
&
fsr
);
fsr
=
(
fsr
&
0xe0
)
|
(
fh
-
1
);
sisusb_setidxreg
(
sisusb
,
SISCR
,
0x09
,
fsr
);
sisusb
->
current_font_height
=
fh
;
sisusb
->
sisusb_cursor_size_from
=
-
1
;
sisusb
->
sisusb_cursor_size_to
=
-
1
;
}
if
(
uplock
)
up
(
&
sisusb
->
lock
);
if
(
dorecalc
&&
c
)
{
int
i
,
rows
=
c
->
vc_scan_lines
/
fh
;
/* Now adjust our consoles' size */
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
{
struct
vc_data
*
vc
=
vc_cons
[
i
].
d
;
if
(
vc
&&
vc
->
vc_sw
==
&
sisusb_con
)
{
if
(
CON_IS_VISIBLE
(
vc
))
{
vc
->
vc_sw
->
con_cursor
(
vc
,
CM_DRAW
);
}
vc
->
vc_font
.
height
=
fh
;
vc_resize
(
vc
,
0
,
rows
);
}
}
}
return
0
;
font_op_error:
if
(
uplock
)
up
(
&
sisusb
->
lock
);
return
-
EIO
;
}
/* Interface routine */
static
int
sisusbcon_font_set
(
struct
vc_data
*
c
,
struct
console_font
*
font
,
unsigned
flags
)
{
struct
sisusb_usb_data
*
sisusb
;
unsigned
charcount
=
font
->
charcount
;
if
(
font
->
width
!=
8
||
(
charcount
!=
256
&&
charcount
!=
512
))
return
-
EINVAL
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
-
ENODEV
;
/* sisusb->lock is down */
/* Save the user-provided font into a buffer. This
* is used for restoring text mode after quitting
* from X and for the con_getfont routine.
*/
if
(
sisusb
->
font_backup
)
{
if
(
sisusb
->
font_backup_size
<
charcount
)
{
vfree
(
sisusb
->
font_backup
);
sisusb
->
font_backup
=
NULL
;
}
}
if
(
!
sisusb
->
font_backup
)
sisusb
->
font_backup
=
vmalloc
(
charcount
*
32
);
if
(
sisusb
->
font_backup
)
{
memcpy
(
sisusb
->
font_backup
,
font
->
data
,
charcount
*
32
);
sisusb
->
font_backup_size
=
charcount
;
sisusb
->
font_backup_height
=
font
->
height
;
sisusb
->
font_backup_512
=
(
charcount
==
512
)
?
1
:
0
;
}
/* do_font_op ups sisusb->lock */
return
sisusbcon_do_font_op
(
sisusb
,
1
,
2
,
font
->
data
,
8192
,
(
charcount
==
512
),
(
!
(
flags
&
KD_FONT_FLAG_DONT_RECALC
))
?
1
:
0
,
c
,
font
->
height
,
1
);
}
/* Interface routine */
static
int
sisusbcon_font_get
(
struct
vc_data
*
c
,
struct
console_font
*
font
)
{
struct
sisusb_usb_data
*
sisusb
;
if
(
!
(
sisusb
=
sisusb_get_sisusb_lock_and_check
(
c
->
vc_num
)))
return
-
ENODEV
;
/* sisusb->lock is down */
font
->
width
=
8
;
font
->
height
=
c
->
vc_font
.
height
;
font
->
charcount
=
256
;
if
(
!
font
->
data
)
{
up
(
&
sisusb
->
lock
);
return
0
;
}
if
(
!
sisusb
->
font_backup
)
{
up
(
&
sisusb
->
lock
);
return
-
ENODEV
;
}
/* Copy 256 chars only, like vgacon */
memcpy
(
font
->
data
,
sisusb
->
font_backup
,
256
*
32
);
up
(
&
sisusb
->
lock
);
return
0
;
}
/*
* The console `switch' structure for the sisusb console
*/
static
const
struct
consw
sisusb_con
=
{
.
owner
=
THIS_MODULE
,
.
con_startup
=
sisusbcon_startup
,
.
con_init
=
sisusbcon_init
,
.
con_deinit
=
sisusbcon_deinit
,
.
con_clear
=
sisusbcon_clear
,
.
con_putc
=
sisusbcon_putc
,
.
con_putcs
=
sisusbcon_putcs
,
.
con_cursor
=
sisusbcon_cursor
,
.
con_scroll
=
sisusbcon_scroll
,
.
con_bmove
=
sisusbcon_bmove
,
.
con_switch
=
sisusbcon_switch
,
.
con_blank
=
sisusbcon_blank
,
.
con_font_set
=
sisusbcon_font_set
,
.
con_font_get
=
sisusbcon_font_get
,
.
con_set_palette
=
sisusbcon_set_palette
,
.
con_scrolldelta
=
sisusbcon_scrolldelta
,
.
con_build_attr
=
sisusbcon_build_attr
,
.
con_invert_region
=
sisusbcon_invert_region
,
.
con_set_origin
=
sisusbcon_set_origin
,
.
con_save_screen
=
sisusbcon_save_screen
,
.
con_resize
=
sisusbcon_resize
,
};
/* Our very own dummy console driver */
static
const
char
*
sisusbdummycon_startup
(
void
)
{
return
"SISUSBVGADUMMY"
;
}
static
void
sisusbdummycon_init
(
struct
vc_data
*
vc
,
int
init
)
{
vc
->
vc_can_do_color
=
1
;
if
(
init
)
{
vc
->
vc_cols
=
80
;
vc
->
vc_rows
=
25
;
}
else
vc_resize
(
vc
,
80
,
25
);
}
static
int
sisusbdummycon_dummy
(
void
)
{
return
0
;
}
#define SISUSBCONDUMMY (void *)sisusbdummycon_dummy
const
struct
consw
sisusb_dummy_con
=
{
.
owner
=
THIS_MODULE
,
.
con_startup
=
sisusbdummycon_startup
,
.
con_init
=
sisusbdummycon_init
,
.
con_deinit
=
SISUSBCONDUMMY
,
.
con_clear
=
SISUSBCONDUMMY
,
.
con_putc
=
SISUSBCONDUMMY
,
.
con_putcs
=
SISUSBCONDUMMY
,
.
con_cursor
=
SISUSBCONDUMMY
,
.
con_scroll
=
SISUSBCONDUMMY
,
.
con_bmove
=
SISUSBCONDUMMY
,
.
con_switch
=
SISUSBCONDUMMY
,
.
con_blank
=
SISUSBCONDUMMY
,
.
con_font_set
=
SISUSBCONDUMMY
,
.
con_font_get
=
SISUSBCONDUMMY
,
.
con_font_default
=
SISUSBCONDUMMY
,
.
con_font_copy
=
SISUSBCONDUMMY
,
.
con_set_palette
=
SISUSBCONDUMMY
,
.
con_scrolldelta
=
SISUSBCONDUMMY
,
};
int
sisusb_console_init
(
struct
sisusb_usb_data
*
sisusb
,
int
first
,
int
last
)
{
int
i
,
ret
,
minor
=
sisusb
->
minor
;
down
(
&
disconnect_sem
);
down
(
&
sisusb
->
lock
);
/* Erm.. that should not happen */
if
(
sisusb
->
haveconsole
||
!
sisusb
->
SiS_Pr
)
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
return
1
;
}
sisusb
->
con_first
=
first
;
sisusb
->
con_last
=
last
;
if
(
first
>
last
||
first
>
MAX_NR_CONSOLES
||
last
>
MAX_NR_CONSOLES
)
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
return
1
;
}
/* If gfxcore not initialized or no consoles given, quit graciously */
if
(
!
sisusb
->
gfxinit
||
first
<
1
||
last
<
1
)
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
return
0
;
}
sisusb
->
sisusb_cursor_loc
=
-
1
;
sisusb
->
sisusb_cursor_size_from
=
-
1
;
sisusb
->
sisusb_cursor_size_to
=
-
1
;
/* Set up text mode (and upload default font) */
if
(
sisusb_reset_text_mode
(
sisusb
,
1
))
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
printk
(
KERN_ERR
"sisusbvga[%d]: Failed to set up text mode
\n
"
,
minor
);
return
1
;
}
/* Initialize some gfx registers */
sisusb_initialize
(
sisusb
);
for
(
i
=
first
-
1
;
i
<=
last
-
1
;
i
++
)
{
/* Save sisusb for our interface routines */
mysisusbs
[
i
]
=
sisusb
;
}
/* Initial console setup */
sisusb
->
sisusb_num_columns
=
80
;
/* Use a 32K buffer (matches b8000-bffff area) */
sisusb
->
scrbuf_size
=
32
*
1024
;
/* Allocate screen buffer */
if
(
!
(
sisusb
->
scrbuf
=
(
unsigned
long
)
vmalloc
(
sisusb
->
scrbuf_size
)))
{
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
printk
(
KERN_ERR
"sisusbvga[%d]: Failed to allocate screen buffer
\n
"
,
minor
);
return
1
;
}
up
(
&
sisusb
->
lock
);
up
(
&
disconnect_sem
);
/* Now grab the desired console(s) */
ret
=
take_over_console
(
&
sisusb_con
,
first
-
1
,
last
-
1
,
0
);
if
(
!
ret
)
sisusb
->
haveconsole
=
1
;
else
{
for
(
i
=
first
-
1
;
i
<=
last
-
1
;
i
++
)
mysisusbs
[
i
]
=
NULL
;
}
return
ret
;
}
void
sisusb_console_exit
(
struct
sisusb_usb_data
*
sisusb
)
{
int
i
;
/* This is called if the device is disconnected
* and while disconnect and lock semaphores
* are up. This should be save because we
* can't lose our sisusb any other way but by
* disconnection (and hence, the disconnect
* sema is for protecting all other access
* functions from disconnection, not the
* other way round).
*/
/* Now what do we do in case of disconnection:
* One alternative would be to simply call
* give_up_console(). Nah, not a good idea.
* give_up_console() is obviously buggy as it
* only discards the consw pointer from the
* driver_map, but doesn't adapt vc->vc_sw
* of the affected consoles. Hence, the next
* call to any of the console functions will
* eventually take a trip to oops county.
* Also, give_up_console for some reason
* doesn't decrement our module refcount.
* Instead, we switch our consoles to a private
* dummy console. This, of course, keeps our
* refcount up as well, but it works perfectly.
*/
if
(
sisusb
->
haveconsole
)
{
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
if
(
sisusb
->
havethisconsole
[
i
])
take_over_console
(
&
sisusb_dummy_con
,
i
,
i
,
0
);
/* At this point, con_deinit for all our
* consoles is executed by take_over_console().
*/
sisusb
->
haveconsole
=
0
;
}
vfree
((
void
*
)
sisusb
->
scrbuf
);
sisusb
->
scrbuf
=
0
;
vfree
(
sisusb
->
font_backup
);
sisusb
->
font_backup
=
NULL
;
}
void
__init
sisusb_init_concode
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
MAX_NR_CONSOLES
;
i
++
)
mysisusbs
[
i
]
=
NULL
;
}
#endif
/* INCL_CON */
drivers/usb/misc/sisusbvga/sisusb_init.c
0 → 100644
View file @
cc6120c6
/*
* sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
*
* Display mode initializing code
*
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, this code is licensed under the
* terms of the GPL v2.
*
* Otherwise, the following license terms apply:
*
* * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions
* * are met:
* * 1) Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* * 2) Redistributions in binary form must reproduce the above copyright
* * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission.
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/kref.h>
#include "sisusb.h"
#ifdef INCL_SISUSB_CON
#include "sisusb_init.h"
/*********************************************/
/* POINTER INITIALIZATION */
/*********************************************/
static
void
SiSUSB_InitPtr
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_Pr
->
SiS_ModeResInfo
=
SiSUSB_ModeResInfo
;
SiS_Pr
->
SiS_StandTable
=
SiSUSB_StandTable
;
SiS_Pr
->
SiS_SModeIDTable
=
SiSUSB_SModeIDTable
;
SiS_Pr
->
SiS_EModeIDTable
=
SiSUSB_EModeIDTable
;
SiS_Pr
->
SiS_RefIndex
=
SiSUSB_RefIndex
;
SiS_Pr
->
SiS_CRT1Table
=
SiSUSB_CRT1Table
;
SiS_Pr
->
SiS_VCLKData
=
SiSUSB_VCLKData
;
}
/*********************************************/
/* HELPER: Get ModeID */
/*********************************************/
unsigned
short
SiSUSB_GetModeID
(
int
HDisplay
,
int
VDisplay
,
int
Depth
)
{
unsigned
short
ModeIndex
=
0
;
switch
(
HDisplay
)
{
case
320
:
if
(
VDisplay
==
200
)
ModeIndex
=
ModeIndex_320x200
[
Depth
];
else
if
(
VDisplay
==
240
)
ModeIndex
=
ModeIndex_320x240
[
Depth
];
break
;
case
400
:
if
(
VDisplay
==
300
)
ModeIndex
=
ModeIndex_400x300
[
Depth
];
break
;
case
512
:
if
(
VDisplay
==
384
)
ModeIndex
=
ModeIndex_512x384
[
Depth
];
break
;
case
640
:
if
(
VDisplay
==
480
)
ModeIndex
=
ModeIndex_640x480
[
Depth
];
else
if
(
VDisplay
==
400
)
ModeIndex
=
ModeIndex_640x400
[
Depth
];
break
;
case
720
:
if
(
VDisplay
==
480
)
ModeIndex
=
ModeIndex_720x480
[
Depth
];
else
if
(
VDisplay
==
576
)
ModeIndex
=
ModeIndex_720x576
[
Depth
];
break
;
case
768
:
if
(
VDisplay
==
576
)
ModeIndex
=
ModeIndex_768x576
[
Depth
];
break
;
case
800
:
if
(
VDisplay
==
600
)
ModeIndex
=
ModeIndex_800x600
[
Depth
];
else
if
(
VDisplay
==
480
)
ModeIndex
=
ModeIndex_800x480
[
Depth
];
break
;
case
848
:
if
(
VDisplay
==
480
)
ModeIndex
=
ModeIndex_848x480
[
Depth
];
break
;
case
856
:
if
(
VDisplay
==
480
)
ModeIndex
=
ModeIndex_856x480
[
Depth
];
break
;
case
960
:
if
(
VDisplay
==
540
)
ModeIndex
=
ModeIndex_960x540
[
Depth
];
else
if
(
VDisplay
==
600
)
ModeIndex
=
ModeIndex_960x600
[
Depth
];
break
;
case
1024
:
if
(
VDisplay
==
576
)
ModeIndex
=
ModeIndex_1024x576
[
Depth
];
else
if
(
VDisplay
==
768
)
ModeIndex
=
ModeIndex_1024x768
[
Depth
];
break
;
case
1152
:
if
(
VDisplay
==
864
)
ModeIndex
=
ModeIndex_1152x864
[
Depth
];
break
;
case
1280
:
switch
(
VDisplay
)
{
case
720
:
ModeIndex
=
ModeIndex_1280x720
[
Depth
];
break
;
case
768
:
ModeIndex
=
ModeIndex_1280x768
[
Depth
];
break
;
case
1024
:
ModeIndex
=
ModeIndex_1280x1024
[
Depth
];
break
;
}
}
return
ModeIndex
;
}
/*********************************************/
/* HELPER: SetReg, GetReg */
/*********************************************/
static
void
SiS_SetReg
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
index
,
unsigned
short
data
)
{
sisusb_setidxreg
(
SiS_Pr
->
sisusb
,
port
,
index
,
data
);
}
static
void
SiS_SetRegByte
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
data
)
{
sisusb_setreg
(
SiS_Pr
->
sisusb
,
port
,
data
);
}
static
unsigned
char
SiS_GetReg
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
index
)
{
u8
data
;
sisusb_getidxreg
(
SiS_Pr
->
sisusb
,
port
,
index
,
&
data
);
return
data
;
}
static
unsigned
char
SiS_GetRegByte
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
)
{
u8
data
;
sisusb_getreg
(
SiS_Pr
->
sisusb
,
port
,
&
data
);
return
data
;
}
static
void
SiS_SetRegANDOR
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
index
,
unsigned
short
DataAND
,
unsigned
short
DataOR
)
{
sisusb_setidxregandor
(
SiS_Pr
->
sisusb
,
port
,
index
,
DataAND
,
DataOR
);
}
static
void
SiS_SetRegAND
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
index
,
unsigned
short
DataAND
)
{
sisusb_setidxregand
(
SiS_Pr
->
sisusb
,
port
,
index
,
DataAND
);
}
static
void
SiS_SetRegOR
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
port
,
unsigned
short
index
,
unsigned
short
DataOR
)
{
sisusb_setidxregor
(
SiS_Pr
->
sisusb
,
port
,
index
,
DataOR
);
}
/*********************************************/
/* HELPER: DisplayOn, DisplayOff */
/*********************************************/
static
void
SiS_DisplayOn
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x01
,
0xDF
);
}
/*********************************************/
/* HELPER: Init Port Addresses */
/*********************************************/
void
SiSUSBRegInit
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
BaseAddr
)
{
SiS_Pr
->
SiS_P3c4
=
BaseAddr
+
0x14
;
SiS_Pr
->
SiS_P3d4
=
BaseAddr
+
0x24
;
SiS_Pr
->
SiS_P3c0
=
BaseAddr
+
0x10
;
SiS_Pr
->
SiS_P3ce
=
BaseAddr
+
0x1e
;
SiS_Pr
->
SiS_P3c2
=
BaseAddr
+
0x12
;
SiS_Pr
->
SiS_P3ca
=
BaseAddr
+
0x1a
;
SiS_Pr
->
SiS_P3c6
=
BaseAddr
+
0x16
;
SiS_Pr
->
SiS_P3c7
=
BaseAddr
+
0x17
;
SiS_Pr
->
SiS_P3c8
=
BaseAddr
+
0x18
;
SiS_Pr
->
SiS_P3c9
=
BaseAddr
+
0x19
;
SiS_Pr
->
SiS_P3cb
=
BaseAddr
+
0x1b
;
SiS_Pr
->
SiS_P3cc
=
BaseAddr
+
0x1c
;
SiS_Pr
->
SiS_P3cd
=
BaseAddr
+
0x1d
;
SiS_Pr
->
SiS_P3da
=
BaseAddr
+
0x2a
;
SiS_Pr
->
SiS_Part1Port
=
BaseAddr
+
SIS_CRT2_PORT_04
;
}
/*********************************************/
/* HELPER: GetSysFlags */
/*********************************************/
static
void
SiS_GetSysFlags
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_Pr
->
SiS_MyCR63
=
0x63
;
}
/*********************************************/
/* HELPER: Init PCI & Engines */
/*********************************************/
static
void
SiSInitPCIetc
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x20
,
0xa1
);
/* - Enable 2D (0x40)
* - Enable 3D (0x02)
* - Enable 3D vertex command fetch (0x10)
* - Enable 3D command parser (0x08)
* - Enable 3D G/L transformation engine (0x80)
*/
SiS_SetRegOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x1E
,
0xDA
);
}
/*********************************************/
/* HELPER: SET SEGMENT REGISTERS */
/*********************************************/
static
void
SiS_SetSegRegLower
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
value
)
{
unsigned
short
temp
;
value
&=
0x00ff
;
temp
=
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cb
)
&
0xf0
;
temp
|=
(
value
>>
4
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cb
,
temp
);
temp
=
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cd
)
&
0xf0
;
temp
|=
(
value
&
0x0f
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cd
,
temp
);
}
static
void
SiS_SetSegRegUpper
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
value
)
{
unsigned
short
temp
;
value
&=
0x00ff
;
temp
=
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cb
)
&
0x0f
;
temp
|=
(
value
&
0xf0
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cb
,
temp
);
temp
=
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cd
)
&
0x0f
;
temp
|=
(
value
<<
4
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3cd
,
temp
);
}
static
void
SiS_SetSegmentReg
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
value
)
{
SiS_SetSegRegLower
(
SiS_Pr
,
value
);
SiS_SetSegRegUpper
(
SiS_Pr
,
value
);
}
static
void
SiS_ResetSegmentReg
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_SetSegmentReg
(
SiS_Pr
,
0
);
}
static
void
SiS_SetSegmentRegOver
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
value
)
{
unsigned
short
temp
=
value
>>
8
;
temp
&=
0x07
;
temp
|=
(
temp
<<
4
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x1d
,
temp
);
SiS_SetSegmentReg
(
SiS_Pr
,
value
);
}
static
void
SiS_ResetSegmentRegOver
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_SetSegmentRegOver
(
SiS_Pr
,
0
);
}
static
void
SiS_ResetSegmentRegisters
(
struct
SiS_Private
*
SiS_Pr
)
{
SiS_ResetSegmentReg
(
SiS_Pr
);
SiS_ResetSegmentRegOver
(
SiS_Pr
);
}
/*********************************************/
/* HELPER: SearchModeID */
/*********************************************/
static
int
SiS_SearchModeID
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
*
ModeNo
,
unsigned
short
*
ModeIdIndex
)
{
if
((
*
ModeNo
)
<=
0x13
)
{
if
((
*
ModeNo
)
!=
0x03
)
return
0
;
(
*
ModeIdIndex
)
=
0
;
}
else
{
for
(
*
ModeIdIndex
=
0
;
;(
*
ModeIdIndex
)
++
)
{
if
(
SiS_Pr
->
SiS_EModeIDTable
[
*
ModeIdIndex
].
Ext_ModeID
==
(
*
ModeNo
))
break
;
if
(
SiS_Pr
->
SiS_EModeIDTable
[
*
ModeIdIndex
].
Ext_ModeID
==
0xFF
)
return
0
;
}
}
return
1
;
}
/*********************************************/
/* HELPER: ENABLE CRT1 */
/*********************************************/
static
void
SiS_HandleCRT1
(
struct
SiS_Private
*
SiS_Pr
)
{
/* Enable CRT1 gating */
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
SiS_Pr
->
SiS_MyCR63
,
0xbf
);
}
/*********************************************/
/* HELPER: GetColorDepth */
/*********************************************/
static
unsigned
short
SiS_GetColorDepth
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
)
{
static
const
unsigned
short
ColorDepth
[
6
]
=
{
1
,
2
,
4
,
4
,
6
,
8
};
unsigned
short
modeflag
;
short
index
;
if
(
ModeNo
<=
0x13
)
{
modeflag
=
SiS_Pr
->
SiS_SModeIDTable
[
ModeIdIndex
].
St_ModeFlag
;
}
else
{
modeflag
=
SiS_Pr
->
SiS_EModeIDTable
[
ModeIdIndex
].
Ext_ModeFlag
;
}
index
=
(
modeflag
&
ModeTypeMask
)
-
ModeEGA
;
if
(
index
<
0
)
index
=
0
;
return
ColorDepth
[
index
];
}
/*********************************************/
/* HELPER: GetOffset */
/*********************************************/
static
unsigned
short
SiS_GetOffset
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
,
unsigned
short
rrti
)
{
unsigned
short
xres
,
temp
,
colordepth
,
infoflag
;
infoflag
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_InfoFlag
;
xres
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
XRes
;
colordepth
=
SiS_GetColorDepth
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
);
temp
=
xres
/
16
;
if
(
infoflag
&
InterlaceMode
)
temp
<<=
1
;
temp
*=
colordepth
;
if
(
xres
%
16
)
temp
+=
(
colordepth
>>
1
);
return
temp
;
}
/*********************************************/
/* SEQ */
/*********************************************/
static
void
SiS_SetSeqRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
StandTableIndex
)
{
unsigned
char
SRdata
;
int
i
;
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x00
,
0x03
);
SRdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
SR
[
0
]
|
0x20
;
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x01
,
SRdata
);
for
(
i
=
2
;
i
<=
4
;
i
++
)
{
SRdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
SR
[
i
-
1
];
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
i
,
SRdata
);
}
}
/*********************************************/
/* MISC */
/*********************************************/
static
void
SiS_SetMiscRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
StandTableIndex
)
{
unsigned
char
Miscdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
MISC
;
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c2
,
Miscdata
);
}
/*********************************************/
/* CRTC */
/*********************************************/
static
void
SiS_SetCRTCRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
StandTableIndex
)
{
unsigned
char
CRTCdata
;
unsigned
short
i
;
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x11
,
0x7f
);
for
(
i
=
0
;
i
<=
0x18
;
i
++
)
{
CRTCdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
CRTC
[
i
];
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
i
,
CRTCdata
);
}
}
/*********************************************/
/* ATT */
/*********************************************/
static
void
SiS_SetATTRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
StandTableIndex
)
{
unsigned
char
ARdata
;
unsigned
short
i
;
for
(
i
=
0
;
i
<=
0x13
;
i
++
)
{
ARdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
ATTR
[
i
];
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3da
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c0
,
i
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c0
,
ARdata
);
}
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3da
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c0
,
0x14
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c0
,
0x00
);
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3da
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c0
,
0x20
);
SiS_GetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3da
);
}
/*********************************************/
/* GRC */
/*********************************************/
static
void
SiS_SetGRCRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
StandTableIndex
)
{
unsigned
char
GRdata
;
unsigned
short
i
;
for
(
i
=
0
;
i
<=
0x08
;
i
++
)
{
GRdata
=
SiS_Pr
->
SiS_StandTable
[
StandTableIndex
].
GRC
[
i
];
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3ce
,
i
,
GRdata
);
}
if
(
SiS_Pr
->
SiS_ModeType
>
ModeVGA
)
{
/* 256 color disable */
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3ce
,
0x05
,
0xBF
);
}
}
/*********************************************/
/* CLEAR EXTENDED REGISTERS */
/*********************************************/
static
void
SiS_ClearExt1Regs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
)
{
int
i
;
for
(
i
=
0x0A
;
i
<=
0x0E
;
i
++
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
i
,
0x00
);
}
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x37
,
0xFE
);
}
/*********************************************/
/* Get rate index */
/*********************************************/
static
unsigned
short
SiS_GetRatePtr
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
)
{
unsigned
short
rrti
,
i
,
index
,
temp
;
if
(
ModeNo
<=
0x13
)
return
0xFFFF
;
index
=
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x33
)
&
0x0F
;
if
(
index
>
0
)
index
--
;
rrti
=
SiS_Pr
->
SiS_EModeIDTable
[
ModeIdIndex
].
REFindex
;
ModeNo
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
ModeID
;
i
=
0
;
do
{
if
(
SiS_Pr
->
SiS_RefIndex
[
rrti
+
i
].
ModeID
!=
ModeNo
)
break
;
temp
=
SiS_Pr
->
SiS_RefIndex
[
rrti
+
i
].
Ext_InfoFlag
&
ModeTypeMask
;
if
(
temp
<
SiS_Pr
->
SiS_ModeType
)
break
;
i
++
;
index
--
;
}
while
(
index
!=
0xFFFF
);
i
--
;
return
(
rrti
+
i
);
}
/*********************************************/
/* SYNC */
/*********************************************/
static
void
SiS_SetCRT1Sync
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
rrti
)
{
unsigned
short
sync
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_InfoFlag
>>
8
;
sync
&=
0xC0
;
sync
|=
0x2f
;
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c2
,
sync
);
}
/*********************************************/
/* CRTC/2 */
/*********************************************/
static
void
SiS_SetCRT1CRTC
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
,
unsigned
short
rrti
)
{
unsigned
char
index
;
unsigned
short
temp
,
i
,
j
,
modeflag
;
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x11
,
0x7f
);
modeflag
=
SiS_Pr
->
SiS_EModeIDTable
[
ModeIdIndex
].
Ext_ModeFlag
;
index
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_CRT1CRTC
;
for
(
i
=
0
,
j
=
0
;
i
<=
7
;
i
++
,
j
++
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
j
,
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
i
]);
}
for
(
j
=
0x10
;
i
<=
10
;
i
++
,
j
++
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
j
,
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
i
]);
}
for
(
j
=
0x15
;
i
<=
12
;
i
++
,
j
++
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
j
,
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
i
]);
}
for
(
j
=
0x0A
;
i
<=
15
;
i
++
,
j
++
)
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
j
,
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
i
]);
}
temp
=
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
16
]
&
0xE0
;
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0E
,
temp
);
temp
=
((
SiS_Pr
->
SiS_CRT1Table
[
index
].
CR
[
16
])
&
0x01
)
<<
5
;
if
(
modeflag
&
DoubleScanMode
)
temp
|=
0x80
;
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x09
,
0x5F
,
temp
);
if
(
SiS_Pr
->
SiS_ModeType
>
ModeVGA
)
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x14
,
0x4F
);
}
/*********************************************/
/* OFFSET & PITCH */
/*********************************************/
/* (partly overruled by SetPitch() in XF86) */
/*********************************************/
static
void
SiS_SetCRT1Offset
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
,
unsigned
short
rrti
)
{
unsigned
short
du
=
SiS_GetOffset
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
,
rrti
);
unsigned
short
infoflag
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_InfoFlag
;
unsigned
short
temp
;
temp
=
(
du
>>
8
)
&
0x0f
;
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0E
,
0xF0
,
temp
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x13
,
(
du
&
0xFF
));
if
(
infoflag
&
InterlaceMode
)
du
>>=
1
;
du
<<=
5
;
temp
=
(
du
>>
8
)
&
0xff
;
if
(
du
&
0xff
)
temp
++
;
temp
++
;
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x10
,
temp
);
}
/*********************************************/
/* VCLK */
/*********************************************/
static
void
SiS_SetCRT1VCLK
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
rrti
)
{
unsigned
short
index
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_CRTVCLK
;
unsigned
short
clka
=
SiS_Pr
->
SiS_VCLKData
[
index
].
SR2B
;
unsigned
short
clkb
=
SiS_Pr
->
SiS_VCLKData
[
index
].
SR2C
;
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x31
,
0xCF
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x2B
,
clka
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x2C
,
clkb
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x2D
,
0x01
);
}
/*********************************************/
/* FIFO */
/*********************************************/
static
void
SiS_SetCRT1FIFO_310
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
mi
)
{
unsigned
short
modeflag
=
SiS_Pr
->
SiS_EModeIDTable
[
mi
].
Ext_ModeFlag
;
/* disable auto-threshold */
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x3D
,
0xFE
);
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x08
,
0xAE
);
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x09
,
0xF0
);
if
(
ModeNo
<=
0x13
)
return
;
if
((
!
(
modeflag
&
DoubleScanMode
))
||
(
!
(
modeflag
&
HalfDCLK
)))
{
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x08
,
0x34
);
SiS_SetRegOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x3D
,
0x01
);
}
}
/*********************************************/
/* MODE REGISTERS */
/*********************************************/
static
void
SiS_SetVCLKState
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
rrti
)
{
unsigned
short
data
=
0
,
VCLK
=
0
,
index
=
0
;
if
(
ModeNo
>
0x13
)
{
index
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_CRTVCLK
;
VCLK
=
SiS_Pr
->
SiS_VCLKData
[
index
].
CLOCK
;
}
if
(
VCLK
>=
166
)
data
|=
0x0c
;
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x32
,
0xf3
,
data
);
if
(
VCLK
>=
166
)
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x1f
,
0xe7
);
/* DAC speed */
data
=
0x03
;
if
(
VCLK
>=
260
)
data
=
0x00
;
else
if
(
VCLK
>=
160
)
data
=
0x01
;
else
if
(
VCLK
>=
135
)
data
=
0x02
;
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x07
,
0xF8
,
data
);
}
static
void
SiS_SetCRT1ModeRegs
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
,
unsigned
short
rrti
)
{
unsigned
short
data
,
infoflag
=
0
,
modeflag
;
if
(
ModeNo
<=
0x13
)
modeflag
=
SiS_Pr
->
SiS_SModeIDTable
[
ModeIdIndex
].
St_ModeFlag
;
else
{
modeflag
=
SiS_Pr
->
SiS_EModeIDTable
[
ModeIdIndex
].
Ext_ModeFlag
;
infoflag
=
SiS_Pr
->
SiS_RefIndex
[
rrti
].
Ext_InfoFlag
;
}
/* Disable DPMS */
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x1F
,
0x3F
);
data
=
0
;
if
(
ModeNo
>
0x13
)
{
if
(
SiS_Pr
->
SiS_ModeType
>
ModeEGA
)
{
data
|=
0x02
;
data
|=
((
SiS_Pr
->
SiS_ModeType
-
ModeVGA
)
<<
2
);
}
if
(
infoflag
&
InterlaceMode
)
data
|=
0x20
;
}
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x06
,
0xC0
,
data
);
data
=
0
;
if
(
infoflag
&
InterlaceMode
)
{
/* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
unsigned
short
hrs
=
(
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x04
)
|
((
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0b
)
&
0xc0
)
<<
2
))
-
3
;
unsigned
short
hto
=
(
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x00
)
|
((
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0b
)
&
0x03
)
<<
8
))
+
5
;
data
=
hrs
-
(
hto
>>
1
)
+
3
;
}
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x19
,
(
data
&
0xFF
));
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x1a
,
0xFC
,
(
data
>>
8
));
if
(
modeflag
&
HalfDCLK
)
SiS_SetRegOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x01
,
0x08
);
data
=
0
;
if
(
modeflag
&
LineCompareOff
)
data
=
0x08
;
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0F
,
0xB7
,
data
);
if
((
SiS_Pr
->
SiS_ModeType
==
ModeEGA
)
&&
(
ModeNo
>
0x13
))
SiS_SetRegOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x0F
,
0x40
);
SiS_SetRegAND
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x31
,
0xfb
);
data
=
0x60
;
if
(
SiS_Pr
->
SiS_ModeType
!=
ModeText
)
{
data
^=
0x60
;
if
(
SiS_Pr
->
SiS_ModeType
!=
ModeEGA
)
data
^=
0xA0
;
}
SiS_SetRegANDOR
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x21
,
0x1F
,
data
);
SiS_SetVCLKState
(
SiS_Pr
,
ModeNo
,
rrti
);
if
(
SiS_GetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x31
)
&
0x40
)
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x52
,
0x2c
);
else
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x52
,
0x6c
);
}
/*********************************************/
/* LOAD DAC */
/*********************************************/
static
void
SiS_WriteDAC
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
DACData
,
unsigned
short
shiftflag
,
unsigned
short
dl
,
unsigned
short
ah
,
unsigned
short
al
,
unsigned
short
dh
)
{
unsigned
short
d1
,
d2
,
d3
;
switch
(
dl
)
{
case
0
:
d1
=
dh
;
d2
=
ah
;
d3
=
al
;
break
;
case
1
:
d1
=
ah
;
d2
=
al
;
d3
=
dh
;
break
;
default:
d1
=
al
;
d2
=
dh
;
d3
=
ah
;
}
SiS_SetRegByte
(
SiS_Pr
,
DACData
,
(
d1
<<
shiftflag
));
SiS_SetRegByte
(
SiS_Pr
,
DACData
,
(
d2
<<
shiftflag
));
SiS_SetRegByte
(
SiS_Pr
,
DACData
,
(
d3
<<
shiftflag
));
}
static
void
SiS_LoadDAC
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
mi
)
{
unsigned
short
data
,
data2
,
time
,
i
,
j
,
k
,
m
,
n
,
o
;
unsigned
short
si
,
di
,
bx
,
sf
;
unsigned
long
DACAddr
,
DACData
;
const
unsigned
char
*
table
=
NULL
;
if
(
ModeNo
<
0x13
)
data
=
SiS_Pr
->
SiS_SModeIDTable
[
mi
].
St_ModeFlag
;
else
data
=
SiS_Pr
->
SiS_EModeIDTable
[
mi
].
Ext_ModeFlag
;
data
&=
DACInfoFlag
;
j
=
time
=
64
;
if
(
data
==
0x00
)
table
=
SiS_MDA_DAC
;
else
if
(
data
==
0x08
)
table
=
SiS_CGA_DAC
;
else
if
(
data
==
0x10
)
table
=
SiS_EGA_DAC
;
else
{
j
=
16
;
time
=
256
;
table
=
SiS_VGA_DAC
;
}
DACAddr
=
SiS_Pr
->
SiS_P3c8
;
DACData
=
SiS_Pr
->
SiS_P3c9
;
sf
=
0
;
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c6
,
0xFF
);
SiS_SetRegByte
(
SiS_Pr
,
DACAddr
,
0x00
);
for
(
i
=
0
;
i
<
j
;
i
++
)
{
data
=
table
[
i
];
for
(
k
=
0
;
k
<
3
;
k
++
)
{
data2
=
0
;
if
(
data
&
0x01
)
data2
+=
0x2A
;
if
(
data
&
0x02
)
data2
+=
0x15
;
SiS_SetRegByte
(
SiS_Pr
,
DACData
,
(
data2
<<
sf
));
data
>>=
2
;
}
}
if
(
time
==
256
)
{
for
(
i
=
16
;
i
<
32
;
i
++
)
{
data
=
table
[
i
]
<<
sf
;
for
(
k
=
0
;
k
<
3
;
k
++
)
SiS_SetRegByte
(
SiS_Pr
,
DACData
,
data
);
}
si
=
32
;
for
(
m
=
0
;
m
<
9
;
m
++
)
{
di
=
si
;
bx
=
si
+
4
;
for
(
n
=
0
;
n
<
3
;
n
++
)
{
for
(
o
=
0
;
o
<
5
;
o
++
)
{
SiS_WriteDAC
(
SiS_Pr
,
DACData
,
sf
,
n
,
table
[
di
],
table
[
bx
],
table
[
si
]);
si
++
;
}
si
-=
2
;
for
(
o
=
0
;
o
<
3
;
o
++
)
{
SiS_WriteDAC
(
SiS_Pr
,
DACData
,
sf
,
n
,
table
[
di
],
table
[
si
],
table
[
bx
]);
si
--
;
}
}
si
+=
5
;
}
}
}
/*********************************************/
/* SET CRT1 REGISTER GROUP */
/*********************************************/
static
void
SiS_SetCRT1Group
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
,
unsigned
short
ModeIdIndex
)
{
unsigned
short
StandTableIndex
,
rrti
;
SiS_Pr
->
SiS_CRT1Mode
=
ModeNo
;
if
(
ModeNo
<=
0x13
)
StandTableIndex
=
0
;
else
StandTableIndex
=
1
;
SiS_ResetSegmentRegisters
(
SiS_Pr
);
SiS_SetSeqRegs
(
SiS_Pr
,
StandTableIndex
);
SiS_SetMiscRegs
(
SiS_Pr
,
StandTableIndex
);
SiS_SetCRTCRegs
(
SiS_Pr
,
StandTableIndex
);
SiS_SetATTRegs
(
SiS_Pr
,
StandTableIndex
);
SiS_SetGRCRegs
(
SiS_Pr
,
StandTableIndex
);
SiS_ClearExt1Regs
(
SiS_Pr
,
ModeNo
);
rrti
=
SiS_GetRatePtr
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
);
if
(
rrti
!=
0xFFFF
)
{
SiS_SetCRT1Sync
(
SiS_Pr
,
rrti
);
SiS_SetCRT1CRTC
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
,
rrti
);
SiS_SetCRT1Offset
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
,
rrti
);
SiS_SetCRT1VCLK
(
SiS_Pr
,
ModeNo
,
rrti
);
}
SiS_SetCRT1FIFO_310
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
);
SiS_SetCRT1ModeRegs
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
,
rrti
);
SiS_LoadDAC
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
);
SiS_DisplayOn
(
SiS_Pr
);
}
/*********************************************/
/* SiSSetMode() */
/*********************************************/
int
SiSUSBSetMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
)
{
unsigned
short
ModeIdIndex
;
unsigned
long
BaseAddr
=
SiS_Pr
->
IOAddress
;
SiSUSB_InitPtr
(
SiS_Pr
);
SiSUSBRegInit
(
SiS_Pr
,
BaseAddr
);
SiS_GetSysFlags
(
SiS_Pr
);
if
(
!
(
SiS_SearchModeID
(
SiS_Pr
,
&
ModeNo
,
&
ModeIdIndex
)))
return
0
;
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c4
,
0x05
,
0x86
);
SiSInitPCIetc
(
SiS_Pr
);
ModeNo
&=
0x7f
;
SiS_Pr
->
SiS_ModeType
=
SiS_Pr
->
SiS_EModeIDTable
[
ModeIdIndex
].
Ext_ModeFlag
&
ModeTypeMask
;
SiS_Pr
->
SiS_SetFlag
=
LowModeTests
;
/* Set mode on CRT1 */
SiS_SetCRT1Group
(
SiS_Pr
,
ModeNo
,
ModeIdIndex
);
SiS_HandleCRT1
(
SiS_Pr
);
SiS_DisplayOn
(
SiS_Pr
);
SiS_SetRegByte
(
SiS_Pr
,
SiS_Pr
->
SiS_P3c6
,
0xFF
);
/* Store mode number */
SiS_SetReg
(
SiS_Pr
,
SiS_Pr
->
SiS_P3d4
,
0x34
,
ModeNo
);
return
1
;
}
int
SiSUSBSetVESAMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
VModeNo
)
{
unsigned
short
ModeNo
=
0
;
int
i
;
SiSUSB_InitPtr
(
SiS_Pr
);
if
(
VModeNo
==
0x03
)
{
ModeNo
=
0x03
;
}
else
{
i
=
0
;
do
{
if
(
SiS_Pr
->
SiS_EModeIDTable
[
i
].
Ext_VESAID
==
VModeNo
)
{
ModeNo
=
SiS_Pr
->
SiS_EModeIDTable
[
i
].
Ext_ModeID
;
break
;
}
}
while
(
SiS_Pr
->
SiS_EModeIDTable
[
i
++
].
Ext_ModeID
!=
0xff
);
}
if
(
!
ModeNo
)
return
0
;
return
SiSUSBSetMode
(
SiS_Pr
,
ModeNo
);
}
#endif
/* INCL_SISUSB_CON */
drivers/usb/misc/sisusbvga/sisusb_init.h
0 → 100644
View file @
cc6120c6
/* $XFree86$ */
/* $XdotOrg$ */
/*
* Data and prototypes for init.c
*
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
*
* * 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 named License,
* * or 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
*
* Otherwise, the following license terms apply:
*
* * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions
* * are met:
* * 1) Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* * 2) Redistributions in binary form must reproduce the above copyright
* * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission.
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
#ifndef _SISUSB_INIT_H_
#define _SISUSB_INIT_H_
/* SiS_ModeType */
#define ModeText 0x00
#define ModeCGA 0x01
#define ModeEGA 0x02
#define ModeVGA 0x03
#define Mode15Bpp 0x04
#define Mode16Bpp 0x05
#define Mode24Bpp 0x06
#define Mode32Bpp 0x07
#define ModeTypeMask 0x07
#define IsTextMode 0x07
#define DACInfoFlag 0x0018
#define MemoryInfoFlag 0x01E0
#define MemorySizeShift 5
/* modeflag */
#define Charx8Dot 0x0200
#define LineCompareOff 0x0400
#define CRT2Mode 0x0800
#define HalfDCLK 0x1000
#define NoSupportSimuTV 0x2000
#define NoSupportLCDScale 0x4000
/* SiS bridge: No scaling possible (no matter what panel) */
#define DoubleScanMode 0x8000
/* Infoflag */
#define SupportTV 0x0008
#define SupportTV1024 0x0800
#define SupportCHTV 0x0800
#define Support64048060Hz 0x0800
/* Special for 640x480 LCD */
#define SupportHiVision 0x0010
#define SupportYPbPr750p 0x1000
#define SupportLCD 0x0020
#define SupportRAMDAC2 0x0040
/* All (<= 100Mhz) */
#define SupportRAMDAC2_135 0x0100
/* All except DH (<= 135Mhz) */
#define SupportRAMDAC2_162 0x0200
/* B, C (<= 162Mhz) */
#define SupportRAMDAC2_202 0x0400
/* C (<= 202Mhz) */
#define InterlaceMode 0x0080
#define SyncPP 0x0000
#define SyncPN 0x4000
#define SyncNP 0x8000
#define SyncNN 0xc000
/* SetFlag */
#define ProgrammingCRT2 0x0001
#define LowModeTests 0x0002
#define LCDVESATiming 0x0008
#define EnableLVDSDDA 0x0010
#define SetDispDevSwitchFlag 0x0020
#define CheckWinDos 0x0040
#define SetDOSMode 0x0080
/* Index in ModeResInfo table */
#define SIS_RI_320x200 0
#define SIS_RI_320x240 1
#define SIS_RI_320x400 2
#define SIS_RI_400x300 3
#define SIS_RI_512x384 4
#define SIS_RI_640x400 5
#define SIS_RI_640x480 6
#define SIS_RI_800x600 7
#define SIS_RI_1024x768 8
#define SIS_RI_1280x1024 9
#define SIS_RI_1600x1200 10
#define SIS_RI_1920x1440 11
#define SIS_RI_2048x1536 12
#define SIS_RI_720x480 13
#define SIS_RI_720x576 14
#define SIS_RI_1280x960 15
#define SIS_RI_800x480 16
#define SIS_RI_1024x576 17
#define SIS_RI_1280x720 18
#define SIS_RI_856x480 19
#define SIS_RI_1280x768 20
#define SIS_RI_1400x1050 21
#define SIS_RI_1152x864 22
/* Up to here SiS conforming */
#define SIS_RI_848x480 23
#define SIS_RI_1360x768 24
#define SIS_RI_1024x600 25
#define SIS_RI_1152x768 26
#define SIS_RI_768x576 27
#define SIS_RI_1360x1024 28
#define SIS_RI_1680x1050 29
#define SIS_RI_1280x800 30
#define SIS_RI_1920x1080 31
#define SIS_RI_960x540 32
#define SIS_RI_960x600 33
#define SIS_VIDEO_CAPTURE 0x00 - 0x30
#define SIS_VIDEO_PLAYBACK 0x02 - 0x30
#define SIS_CRT2_PORT_04 0x04 - 0x30
/* Mode numbers */
static
const
unsigned
short
ModeIndex_320x200
[]
=
{
0x59
,
0x41
,
0x00
,
0x4f
};
static
const
unsigned
short
ModeIndex_320x240
[]
=
{
0x50
,
0x56
,
0x00
,
0x53
};
static
const
unsigned
short
ModeIndex_400x300
[]
=
{
0x51
,
0x57
,
0x00
,
0x54
};
static
const
unsigned
short
ModeIndex_512x384
[]
=
{
0x52
,
0x58
,
0x00
,
0x5c
};
static
const
unsigned
short
ModeIndex_640x400
[]
=
{
0x2f
,
0x5d
,
0x00
,
0x5e
};
static
const
unsigned
short
ModeIndex_640x480
[]
=
{
0x2e
,
0x44
,
0x00
,
0x62
};
static
const
unsigned
short
ModeIndex_720x480
[]
=
{
0x31
,
0x33
,
0x00
,
0x35
};
static
const
unsigned
short
ModeIndex_720x576
[]
=
{
0x32
,
0x34
,
0x00
,
0x36
};
static
const
unsigned
short
ModeIndex_768x576
[]
=
{
0x5f
,
0x60
,
0x00
,
0x61
};
static
const
unsigned
short
ModeIndex_800x480
[]
=
{
0x70
,
0x7a
,
0x00
,
0x76
};
static
const
unsigned
short
ModeIndex_800x600
[]
=
{
0x30
,
0x47
,
0x00
,
0x63
};
static
const
unsigned
short
ModeIndex_848x480
[]
=
{
0x39
,
0x3b
,
0x00
,
0x3e
};
static
const
unsigned
short
ModeIndex_856x480
[]
=
{
0x3f
,
0x42
,
0x00
,
0x45
};
static
const
unsigned
short
ModeIndex_960x540
[]
=
{
0x1d
,
0x1e
,
0x00
,
0x1f
};
static
const
unsigned
short
ModeIndex_960x600
[]
=
{
0x20
,
0x21
,
0x00
,
0x22
};
static
const
unsigned
short
ModeIndex_1024x768
[]
=
{
0x38
,
0x4a
,
0x00
,
0x64
};
static
const
unsigned
short
ModeIndex_1024x576
[]
=
{
0x71
,
0x74
,
0x00
,
0x77
};
static
const
unsigned
short
ModeIndex_1152x864
[]
=
{
0x29
,
0x2a
,
0x00
,
0x2b
};
static
const
unsigned
short
ModeIndex_1280x720
[]
=
{
0x79
,
0x75
,
0x00
,
0x78
};
static
const
unsigned
short
ModeIndex_1280x768
[]
=
{
0x23
,
0x24
,
0x00
,
0x25
};
static
const
unsigned
short
ModeIndex_1280x1024
[]
=
{
0x3a
,
0x4d
,
0x00
,
0x65
};
static
const
unsigned
char
SiS_MDA_DAC
[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x15
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
,
0x3F
};
static
const
unsigned
char
SiS_CGA_DAC
[]
=
{
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x09
,
0x15
,
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x09
,
0x15
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
,
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x09
,
0x15
,
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x09
,
0x15
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
};
static
const
unsigned
char
SiS_EGA_DAC
[]
=
{
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x05
,
0x15
,
0x20
,
0x30
,
0x24
,
0x34
,
0x21
,
0x31
,
0x25
,
0x35
,
0x08
,
0x18
,
0x0C
,
0x1C
,
0x09
,
0x19
,
0x0D
,
0x1D
,
0x28
,
0x38
,
0x2C
,
0x3C
,
0x29
,
0x39
,
0x2D
,
0x3D
,
0x02
,
0x12
,
0x06
,
0x16
,
0x03
,
0x13
,
0x07
,
0x17
,
0x22
,
0x32
,
0x26
,
0x36
,
0x23
,
0x33
,
0x27
,
0x37
,
0x0A
,
0x1A
,
0x0E
,
0x1E
,
0x0B
,
0x1B
,
0x0F
,
0x1F
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
};
static
const
unsigned
char
SiS_VGA_DAC
[]
=
{
0x00
,
0x10
,
0x04
,
0x14
,
0x01
,
0x11
,
0x09
,
0x15
,
0x2A
,
0x3A
,
0x2E
,
0x3E
,
0x2B
,
0x3B
,
0x2F
,
0x3F
,
0x00
,
0x05
,
0x08
,
0x0B
,
0x0E
,
0x11
,
0x14
,
0x18
,
0x1C
,
0x20
,
0x24
,
0x28
,
0x2D
,
0x32
,
0x38
,
0x3F
,
0x00
,
0x10
,
0x1F
,
0x2F
,
0x3F
,
0x1F
,
0x27
,
0x2F
,
0x37
,
0x3F
,
0x2D
,
0x31
,
0x36
,
0x3A
,
0x3F
,
0x00
,
0x07
,
0x0E
,
0x15
,
0x1C
,
0x0E
,
0x11
,
0x15
,
0x18
,
0x1C
,
0x14
,
0x16
,
0x18
,
0x1A
,
0x1C
,
0x00
,
0x04
,
0x08
,
0x0C
,
0x10
,
0x08
,
0x0A
,
0x0C
,
0x0E
,
0x10
,
0x0B
,
0x0C
,
0x0D
,
0x0F
,
0x10
};
static
const
struct
SiS_St
SiSUSB_SModeIDTable
[]
=
{
{
0x03
,
0x0010
,
0x18
,
0x02
,
0x02
,
0x00
,
0x01
,
0x03
,
0x40
},
{
0xff
,
0x0000
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
}
};
static
const
struct
SiS_StResInfo_S
SiSUSB_StResInfo
[]
=
{
{
640
,
400
},
{
640
,
350
},
{
720
,
400
},
{
720
,
350
},
{
640
,
480
}
};
static
const
struct
SiS_ModeResInfo
SiSUSB_ModeResInfo
[]
=
{
{
320
,
200
,
8
,
8
},
/* 0x00 */
{
320
,
240
,
8
,
8
},
/* 0x01 */
{
320
,
400
,
8
,
8
},
/* 0x02 */
{
400
,
300
,
8
,
8
},
/* 0x03 */
{
512
,
384
,
8
,
8
},
/* 0x04 */
{
640
,
400
,
8
,
16
},
/* 0x05 */
{
640
,
480
,
8
,
16
},
/* 0x06 */
{
800
,
600
,
8
,
16
},
/* 0x07 */
{
1024
,
768
,
8
,
16
},
/* 0x08 */
{
1280
,
1024
,
8
,
16
},
/* 0x09 */
{
1600
,
1200
,
8
,
16
},
/* 0x0a */
{
1920
,
1440
,
8
,
16
},
/* 0x0b */
{
2048
,
1536
,
8
,
16
},
/* 0x0c */
{
720
,
480
,
8
,
16
},
/* 0x0d */
{
720
,
576
,
8
,
16
},
/* 0x0e */
{
1280
,
960
,
8
,
16
},
/* 0x0f */
{
800
,
480
,
8
,
16
},
/* 0x10 */
{
1024
,
576
,
8
,
16
},
/* 0x11 */
{
1280
,
720
,
8
,
16
},
/* 0x12 */
{
856
,
480
,
8
,
16
},
/* 0x13 */
{
1280
,
768
,
8
,
16
},
/* 0x14 */
{
1400
,
1050
,
8
,
16
},
/* 0x15 */
{
1152
,
864
,
8
,
16
},
/* 0x16 */
{
848
,
480
,
8
,
16
},
/* 0x17 */
{
1360
,
768
,
8
,
16
},
/* 0x18 */
{
1024
,
600
,
8
,
16
},
/* 0x19 */
{
1152
,
768
,
8
,
16
},
/* 0x1a */
{
768
,
576
,
8
,
16
},
/* 0x1b */
{
1360
,
1024
,
8
,
16
},
/* 0x1c */
{
1680
,
1050
,
8
,
16
},
/* 0x1d */
{
1280
,
800
,
8
,
16
},
/* 0x1e */
{
1920
,
1080
,
8
,
16
},
/* 0x1f */
{
960
,
540
,
8
,
16
},
/* 0x20 */
{
960
,
600
,
8
,
16
}
/* 0x21 */
};
static
const
struct
SiS_StandTable
SiSUSB_StandTable
[]
=
{
/* MD_3_400 - mode 0x03 - 400 */
{
0x50
,
0x18
,
0x10
,
0x1000
,
{
0x00
,
0x03
,
0x00
,
0x02
},
0x67
,
{
0x5f
,
0x4f
,
0x50
,
0x82
,
0x55
,
0x81
,
0xbf
,
0x1f
,
0x00
,
0x4f
,
0x0d
,
0x0e
,
0x00
,
0x00
,
0x00
,
0x00
,
0x9c
,
0x8e
,
0x8f
,
0x28
,
0x1f
,
0x96
,
0xb9
,
0xa3
,
0xff
},
{
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x14
,
0x07
,
0x38
,
0x39
,
0x3a
,
0x3b
,
0x3c
,
0x3d
,
0x3e
,
0x3f
,
0x0c
,
0x00
,
0x0f
,
0x08
},
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x10
,
0x0e
,
0x00
,
0xff
}
},
/* Generic for VGA and higher */
{
0x00
,
0x00
,
0x00
,
0x0000
,
{
0x01
,
0x0f
,
0x00
,
0x0e
},
0x23
,
{
0x5f
,
0x4f
,
0x50
,
0x82
,
0x54
,
0x80
,
0x0b
,
0x3e
,
0x00
,
0x40
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xea
,
0x8c
,
0xdf
,
0x28
,
0x40
,
0xe7
,
0x04
,
0xa3
,
0xff
},
{
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
0x08
,
0x09
,
0x0a
,
0x0b
,
0x0c
,
0x0d
,
0x0e
,
0x0f
,
0x01
,
0x00
,
0x00
,
0x00
},
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x40
,
0x05
,
0x0f
,
0xff
}
}
};
static
const
struct
SiS_Ext
SiSUSB_EModeIDTable
[]
=
{
{
0x2e
,
0x0a1b
,
0x0101
,
SIS_RI_640x480
,
0x00
,
0x00
,
0x05
,
0x05
,
0x08
,
2
},
/* 640x480x8 */
{
0x2f
,
0x0a1b
,
0x0100
,
SIS_RI_640x400
,
0x00
,
0x00
,
0x05
,
0x05
,
0x10
,
0
},
/* 640x400x8 */
{
0x30
,
0x2a1b
,
0x0103
,
SIS_RI_800x600
,
0x00
,
0x00
,
0x07
,
0x06
,
0x00
,
3
},
/* 800x600x8 */
{
0x31
,
0x4a1b
,
0x0000
,
SIS_RI_720x480
,
0x00
,
0x00
,
0x06
,
0x06
,
0x11
,
-
1
},
/* 720x480x8 */
{
0x32
,
0x4a1b
,
0x0000
,
SIS_RI_720x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x12
,
-
1
},
/* 720x576x8 */
{
0x33
,
0x4a1d
,
0x0000
,
SIS_RI_720x480
,
0x00
,
0x00
,
0x06
,
0x06
,
0x11
,
-
1
},
/* 720x480x16 */
{
0x34
,
0x6a1d
,
0x0000
,
SIS_RI_720x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x12
,
-
1
},
/* 720x576x16 */
{
0x35
,
0x4a1f
,
0x0000
,
SIS_RI_720x480
,
0x00
,
0x00
,
0x06
,
0x06
,
0x11
,
-
1
},
/* 720x480x32 */
{
0x36
,
0x6a1f
,
0x0000
,
SIS_RI_720x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x12
,
-
1
},
/* 720x576x32 */
{
0x38
,
0x0a1b
,
0x0105
,
SIS_RI_1024x768
,
0x00
,
0x00
,
0x08
,
0x07
,
0x13
,
4
},
/* 1024x768x8 */
{
0x3a
,
0x0e3b
,
0x0107
,
SIS_RI_1280x1024
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2f
,
8
},
/* 1280x1024x8 */
{
0x41
,
0x9a1d
,
0x010e
,
SIS_RI_320x200
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1a
,
0
},
/* 320x200x16 */
{
0x44
,
0x0a1d
,
0x0111
,
SIS_RI_640x480
,
0x00
,
0x00
,
0x05
,
0x05
,
0x08
,
2
},
/* 640x480x16 */
{
0x47
,
0x2a1d
,
0x0114
,
SIS_RI_800x600
,
0x00
,
0x00
,
0x07
,
0x06
,
0x00
,
3
},
/* 800x600x16 */
{
0x4a
,
0x0a3d
,
0x0117
,
SIS_RI_1024x768
,
0x00
,
0x00
,
0x08
,
0x07
,
0x13
,
4
},
/* 1024x768x16 */
{
0x4d
,
0x0e7d
,
0x011a
,
SIS_RI_1280x1024
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2f
,
8
},
/* 1280x1024x16 */
{
0x50
,
0x9a1b
,
0x0132
,
SIS_RI_320x240
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1b
,
2
},
/* 320x240x8 */
{
0x51
,
0xba1b
,
0x0133
,
SIS_RI_400x300
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1c
,
3
},
/* 400x300x8 */
{
0x52
,
0xba1b
,
0x0134
,
SIS_RI_512x384
,
0x00
,
0x00
,
0x00
,
0x00
,
0x1d
,
4
},
/* 512x384x8 */
{
0x56
,
0x9a1d
,
0x0135
,
SIS_RI_320x240
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1b
,
2
},
/* 320x240x16 */
{
0x57
,
0xba1d
,
0x0136
,
SIS_RI_400x300
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1c
,
3
},
/* 400x300x16 */
{
0x58
,
0xba1d
,
0x0137
,
SIS_RI_512x384
,
0x00
,
0x00
,
0x00
,
0x00
,
0x1d
,
4
},
/* 512x384x16 */
{
0x59
,
0x9a1b
,
0x0138
,
SIS_RI_320x200
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1a
,
0
},
/* 320x200x8 */
{
0x5c
,
0xba1f
,
0x0000
,
SIS_RI_512x384
,
0x00
,
0x00
,
0x00
,
0x00
,
0x1d
,
4
},
/* 512x384x32 */
{
0x5d
,
0x0a1d
,
0x0139
,
SIS_RI_640x400
,
0x00
,
0x00
,
0x05
,
0x07
,
0x10
,
0
},
/* 640x400x16 */
{
0x5e
,
0x0a1f
,
0x0000
,
SIS_RI_640x400
,
0x00
,
0x00
,
0x05
,
0x07
,
0x10
,
0
},
/* 640x400x32 */
{
0x62
,
0x0a3f
,
0x013a
,
SIS_RI_640x480
,
0x00
,
0x00
,
0x05
,
0x05
,
0x08
,
2
},
/* 640x480x32 */
{
0x63
,
0x2a3f
,
0x013b
,
SIS_RI_800x600
,
0x00
,
0x00
,
0x07
,
0x06
,
0x00
,
3
},
/* 800x600x32 */
{
0x64
,
0x0a7f
,
0x013c
,
SIS_RI_1024x768
,
0x00
,
0x00
,
0x08
,
0x07
,
0x13
,
4
},
/* 1024x768x32 */
{
0x65
,
0x0eff
,
0x013d
,
SIS_RI_1280x1024
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2f
,
8
},
/* 1280x1024x32 */
{
0x70
,
0x6a1b
,
0x0000
,
SIS_RI_800x480
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1e
,
-
1
},
/* 800x480x8 */
{
0x71
,
0x4a1b
,
0x0000
,
SIS_RI_1024x576
,
0x00
,
0x00
,
0x00
,
0x00
,
0x21
,
-
1
},
/* 1024x576x8 */
{
0x74
,
0x4a1d
,
0x0000
,
SIS_RI_1024x576
,
0x00
,
0x00
,
0x00
,
0x00
,
0x21
,
-
1
},
/* 1024x576x16 */
{
0x75
,
0x0a3d
,
0x0000
,
SIS_RI_1280x720
,
0x00
,
0x00
,
0x00
,
0x00
,
0x24
,
5
},
/* 1280x720x16 */
{
0x76
,
0x6a1f
,
0x0000
,
SIS_RI_800x480
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1e
,
-
1
},
/* 800x480x32 */
{
0x77
,
0x4a1f
,
0x0000
,
SIS_RI_1024x576
,
0x00
,
0x00
,
0x00
,
0x00
,
0x21
,
-
1
},
/* 1024x576x32 */
{
0x78
,
0x0a3f
,
0x0000
,
SIS_RI_1280x720
,
0x00
,
0x00
,
0x00
,
0x00
,
0x24
,
5
},
/* 1280x720x32 */
{
0x79
,
0x0a3b
,
0x0000
,
SIS_RI_1280x720
,
0x00
,
0x00
,
0x00
,
0x00
,
0x24
,
5
},
/* 1280x720x8 */
{
0x7a
,
0x6a1d
,
0x0000
,
SIS_RI_800x480
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1e
,
-
1
},
/* 800x480x16 */
{
0x23
,
0x0e3b
,
0x0000
,
SIS_RI_1280x768
,
0x00
,
0x00
,
0x00
,
0x00
,
0x27
,
6
},
/* 1280x768x8 */
{
0x24
,
0x0e7d
,
0x0000
,
SIS_RI_1280x768
,
0x00
,
0x00
,
0x00
,
0x00
,
0x27
,
6
},
/* 1280x768x16 */
{
0x25
,
0x0eff
,
0x0000
,
SIS_RI_1280x768
,
0x00
,
0x00
,
0x00
,
0x00
,
0x27
,
6
},
/* 1280x768x32 */
{
0x39
,
0x6a1b
,
0x0000
,
SIS_RI_848x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x28
,
-
1
},
/* 848x480 */
{
0x3b
,
0x6a3d
,
0x0000
,
SIS_RI_848x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x28
,
-
1
},
{
0x3e
,
0x6a7f
,
0x0000
,
SIS_RI_848x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x28
,
-
1
},
{
0x3f
,
0x6a1b
,
0x0000
,
SIS_RI_856x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2a
,
-
1
},
/* 856x480 */
{
0x42
,
0x6a3d
,
0x0000
,
SIS_RI_856x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2a
,
-
1
},
{
0x45
,
0x6a7f
,
0x0000
,
SIS_RI_856x480
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2a
,
-
1
},
{
0x4f
,
0x9a1f
,
0x0000
,
SIS_RI_320x200
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1a
,
0
},
/* 320x200x32 */
{
0x53
,
0x9a1f
,
0x0000
,
SIS_RI_320x240
,
0x00
,
0x00
,
0x04
,
0x04
,
0x1b
,
2
},
/* 320x240x32 */
{
0x54
,
0xba1f
,
0x0000
,
SIS_RI_400x300
,
0x00
,
0x00
,
0x07
,
0x07
,
0x1c
,
3
},
/* 400x300x32 */
{
0x5f
,
0x6a1b
,
0x0000
,
SIS_RI_768x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x2c
,
-
1
},
/* 768x576 */
{
0x60
,
0x6a1d
,
0x0000
,
SIS_RI_768x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x2c
,
-
1
},
{
0x61
,
0x6a3f
,
0x0000
,
SIS_RI_768x576
,
0x00
,
0x00
,
0x06
,
0x06
,
0x2c
,
-
1
},
{
0x1d
,
0x6a1b
,
0x0000
,
SIS_RI_960x540
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2d
,
-
1
},
/* 960x540 */
{
0x1e
,
0x6a3d
,
0x0000
,
SIS_RI_960x540
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2d
,
-
1
},
{
0x1f
,
0x6a7f
,
0x0000
,
SIS_RI_960x540
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2d
,
-
1
},
{
0x20
,
0x6a1b
,
0x0000
,
SIS_RI_960x600
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2e
,
-
1
},
/* 960x600 */
{
0x21
,
0x6a3d
,
0x0000
,
SIS_RI_960x600
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2e
,
-
1
},
{
0x22
,
0x6a7f
,
0x0000
,
SIS_RI_960x600
,
0x00
,
0x00
,
0x00
,
0x00
,
0x2e
,
-
1
},
{
0x29
,
0x4e1b
,
0x0000
,
SIS_RI_1152x864
,
0x00
,
0x00
,
0x00
,
0x00
,
0x33
,
-
1
},
/* 1152x864 */
{
0x2a
,
0x4e3d
,
0x0000
,
SIS_RI_1152x864
,
0x00
,
0x00
,
0x00
,
0x00
,
0x33
,
-
1
},
{
0x2b
,
0x4e7f
,
0x0000
,
SIS_RI_1152x864
,
0x00
,
0x00
,
0x00
,
0x00
,
0x33
,
-
1
},
{
0xff
,
0x0000
,
0x0000
,
0
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
-
1
}
};
static
const
struct
SiS_Ext2
SiSUSB_RefIndex
[]
=
{
{
0x085f
,
0x0d
,
0x03
,
0x05
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x0 */
{
0x0067
,
0x0e
,
0x04
,
0x05
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x1 */
{
0x0067
,
0x0f
,
0x08
,
0x48
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x2 */
{
0x0067
,
0x10
,
0x07
,
0x8b
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x3 */
{
0x0047
,
0x11
,
0x0a
,
0x00
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x4 */
{
0x0047
,
0x12
,
0x0d
,
0x00
,
0x05
,
0x30
,
800
,
600
,
0x40
,
0x00
,
0x00
},
/* 0x5 */
{
0x0047
,
0x13
,
0x13
,
0x00
,
0x05
,
0x30
,
800
,
600
,
0x20
,
0x00
,
0x00
},
/* 0x6 */
{
0x0107
,
0x14
,
0x1c
,
0x00
,
0x05
,
0x30
,
800
,
600
,
0x20
,
0x00
,
0x00
},
/* 0x7 */
{
0xc85f
,
0x05
,
0x00
,
0x04
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0x8 */
{
0xc067
,
0x06
,
0x02
,
0x04
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0x9 */
{
0xc067
,
0x07
,
0x02
,
0x47
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xa */
{
0xc067
,
0x08
,
0x03
,
0x8a
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xb */
{
0xc047
,
0x09
,
0x05
,
0x00
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xc */
{
0xc047
,
0x0a
,
0x09
,
0x00
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xd */
{
0xc047
,
0x0b
,
0x0e
,
0x00
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xe */
{
0xc047
,
0x0c
,
0x15
,
0x00
,
0x04
,
0x2e
,
640
,
480
,
0x40
,
0x00
,
0x00
},
/* 0xf */
{
0x487f
,
0x04
,
0x00
,
0x00
,
0x00
,
0x2f
,
640
,
400
,
0x30
,
0x55
,
0x6e
},
/* 0x10 */
{
0xc06f
,
0x3c
,
0x01
,
0x06
,
0x13
,
0x31
,
720
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x11 */
{
0x006f
,
0x3d
,
0x6f
,
0x06
,
0x14
,
0x32
,
720
,
576
,
0x30
,
0x00
,
0x00
},
/* 0x12 (6f was 03) */
{
0x0087
,
0x15
,
0x06
,
0x00
,
0x06
,
0x38
,
1024
,
768
,
0x30
,
0x00
,
0x00
},
/* 0x13 */
{
0xc877
,
0x16
,
0x0b
,
0x06
,
0x06
,
0x38
,
1024
,
768
,
0x20
,
0x00
,
0x00
},
/* 0x14 */
{
0xc067
,
0x17
,
0x0f
,
0x49
,
0x06
,
0x38
,
1024
,
768
,
0x20
,
0x00
,
0x00
},
/* 0x15 */
{
0x0067
,
0x18
,
0x11
,
0x00
,
0x06
,
0x38
,
1024
,
768
,
0x20
,
0x00
,
0x00
},
/* 0x16 */
{
0x0047
,
0x19
,
0x16
,
0x8c
,
0x06
,
0x38
,
1024
,
768
,
0x20
,
0x00
,
0x00
},
/* 0x17 */
{
0x0107
,
0x1a
,
0x1b
,
0x00
,
0x06
,
0x38
,
1024
,
768
,
0x10
,
0x00
,
0x00
},
/* 0x18 */
{
0x0107
,
0x1b
,
0x1f
,
0x00
,
0x06
,
0x38
,
1024
,
768
,
0x10
,
0x00
,
0x00
},
/* 0x19 */
{
0x407f
,
0x00
,
0x00
,
0x00
,
0x00
,
0x41
,
320
,
200
,
0x30
,
0x56
,
0x4e
},
/* 0x1a */
{
0xc07f
,
0x01
,
0x00
,
0x04
,
0x04
,
0x50
,
320
,
240
,
0x30
,
0x00
,
0x00
},
/* 0x1b */
{
0x007f
,
0x02
,
0x04
,
0x05
,
0x05
,
0x51
,
400
,
300
,
0x30
,
0x00
,
0x00
},
/* 0x1c */
{
0xc077
,
0x03
,
0x0b
,
0x06
,
0x06
,
0x52
,
512
,
384
,
0x30
,
0x00
,
0x00
},
/* 0x1d */
{
0x0077
,
0x32
,
0x40
,
0x08
,
0x18
,
0x70
,
800
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x1e */
{
0x0047
,
0x33
,
0x07
,
0x08
,
0x18
,
0x70
,
800
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x1f */
{
0x0047
,
0x34
,
0x0a
,
0x08
,
0x18
,
0x70
,
800
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x20 */
{
0x0077
,
0x35
,
0x0b
,
0x09
,
0x19
,
0x71
,
1024
,
576
,
0x30
,
0x00
,
0x00
},
/* 0x21 */
{
0x0047
,
0x36
,
0x11
,
0x09
,
0x19
,
0x71
,
1024
,
576
,
0x30
,
0x00
,
0x00
},
/* 0x22 */
{
0x0047
,
0x37
,
0x16
,
0x09
,
0x19
,
0x71
,
1024
,
576
,
0x30
,
0x00
,
0x00
},
/* 0x23 */
{
0x1137
,
0x38
,
0x19
,
0x0a
,
0x0c
,
0x75
,
1280
,
720
,
0x30
,
0x00
,
0x00
},
/* 0x24 */
{
0x1107
,
0x39
,
0x1e
,
0x0a
,
0x0c
,
0x75
,
1280
,
720
,
0x30
,
0x00
,
0x00
},
/* 0x25 */
{
0x1307
,
0x3a
,
0x20
,
0x0a
,
0x0c
,
0x75
,
1280
,
720
,
0x30
,
0x00
,
0x00
},
/* 0x26 */
{
0x0077
,
0x42
,
0x5b
,
0x08
,
0x11
,
0x23
,
1280
,
768
,
0x30
,
0x00
,
0x00
},
/* 0x27 */
{
0x0087
,
0x45
,
0x57
,
0x00
,
0x16
,
0x39
,
848
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x28 38Hzi */
{
0xc067
,
0x46
,
0x55
,
0x0b
,
0x16
,
0x39
,
848
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x29 848x480-60Hz */
{
0x0087
,
0x47
,
0x57
,
0x00
,
0x17
,
0x3f
,
856
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x2a 856x480-38Hzi */
{
0xc067
,
0x48
,
0x57
,
0x00
,
0x17
,
0x3f
,
856
,
480
,
0x30
,
0x00
,
0x00
},
/* 0x2b 856x480-60Hz */
{
0x006f
,
0x4d
,
0x71
,
0x06
,
0x15
,
0x5f
,
768
,
576
,
0x30
,
0x00
,
0x00
},
/* 0x2c 768x576-56Hz */
{
0x0067
,
0x52
,
0x6a
,
0x00
,
0x1c
,
0x1d
,
960
,
540
,
0x30
,
0x00
,
0x00
},
/* 0x2d 960x540 60Hz */
{
0x0077
,
0x53
,
0x6b
,
0x0b
,
0x1d
,
0x20
,
960
,
600
,
0x30
,
0x00
,
0x00
},
/* 0x2e 960x600 60Hz */
{
0x0087
,
0x1c
,
0x11
,
0x00
,
0x07
,
0x3a
,
1280
,
1024
,
0x30
,
0x00
,
0x00
},
/* 0x2f */
{
0x0137
,
0x1d
,
0x19
,
0x07
,
0x07
,
0x3a
,
1280
,
1024
,
0x00
,
0x00
,
0x00
},
/* 0x30 */
{
0x0107
,
0x1e
,
0x1e
,
0x00
,
0x07
,
0x3a
,
1280
,
1024
,
0x00
,
0x00
,
0x00
},
/* 0x31 */
{
0x0207
,
0x1f
,
0x20
,
0x00
,
0x07
,
0x3a
,
1280
,
1024
,
0x00
,
0x00
,
0x00
},
/* 0x32 */
{
0x0127
,
0x54
,
0x6d
,
0x00
,
0x1a
,
0x29
,
1152
,
864
,
0x30
,
0x00
,
0x00
},
/* 0x33 1152x864-60Hz */
{
0x0127
,
0x44
,
0x19
,
0x00
,
0x1a
,
0x29
,
1152
,
864
,
0x30
,
0x00
,
0x00
},
/* 0x34 1152x864-75Hz */
{
0x0127
,
0x4a
,
0x1e
,
0x00
,
0x1a
,
0x29
,
1152
,
864
,
0x30
,
0x00
,
0x00
},
/* 0x35 1152x864-85Hz */
{
0xffff
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0
,
0
,
0
,
0x00
,
0x00
}
};
static
const
struct
SiS_CRT1Table
SiSUSB_CRT1Table
[]
=
{
{{
0x2d
,
0x27
,
0x28
,
0x90
,
0x2c
,
0x80
,
0xbf
,
0x1f
,
0x9c
,
0x8e
,
0x8f
,
0x96
,
0xb9
,
0x30
,
0x00
,
0x00
,
0x00
}},
/* 0x0 */
{{
0x2d
,
0x27
,
0x28
,
0x90
,
0x2c
,
0x80
,
0x0b
,
0x3e
,
0xe9
,
0x8b
,
0xdf
,
0xe7
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
}},
/* 0x1 */
{{
0x3d
,
0x31
,
0x31
,
0x81
,
0x37
,
0x1f
,
0x72
,
0xf0
,
0x58
,
0x8c
,
0x57
,
0x57
,
0x73
,
0x20
,
0x00
,
0x05
,
0x01
}},
/* 0x2 */
{{
0x4f
,
0x3f
,
0x3f
,
0x93
,
0x45
,
0x0d
,
0x24
,
0xf5
,
0x02
,
0x88
,
0xff
,
0xff
,
0x25
,
0x10
,
0x00
,
0x01
,
0x01
}},
/* 0x3 */
{{
0x5f
,
0x4f
,
0x50
,
0x82
,
0x55
,
0x81
,
0xbf
,
0x1f
,
0x9c
,
0x8e
,
0x8f
,
0x96
,
0xb9
,
0x30
,
0x00
,
0x05
,
0x00
}},
/* 0x4 */
{{
0x5f
,
0x4f
,
0x4f
,
0x83
,
0x55
,
0x81
,
0x0b
,
0x3e
,
0xe9
,
0x8b
,
0xdf
,
0xe8
,
0x0c
,
0x00
,
0x00
,
0x05
,
0x00
}},
/* 0x5 */
{{
0x63
,
0x4f
,
0x4f
,
0x87
,
0x56
,
0x9b
,
0x06
,
0x3e
,
0xe8
,
0x8a
,
0xdf
,
0xe7
,
0x07
,
0x00
,
0x00
,
0x01
,
0x00
}},
/* 0x6 */
{{
0x64
,
0x4f
,
0x4f
,
0x88
,
0x55
,
0x9d
,
0xf2
,
0x1f
,
0xe0
,
0x83
,
0xdf
,
0xdf
,
0xf3
,
0x10
,
0x00
,
0x01
,
0x00
}},
/* 0x7 */
{{
0x63
,
0x4f
,
0x4f
,
0x87
,
0x5a
,
0x81
,
0xfb
,
0x1f
,
0xe0
,
0x83
,
0xdf
,
0xdf
,
0xfc
,
0x10
,
0x00
,
0x05
,
0x00
}},
/* 0x8 */
{{
0x65
,
0x4f
,
0x4f
,
0x89
,
0x58
,
0x80
,
0xfb
,
0x1f
,
0xe0
,
0x83
,
0xdf
,
0xdf
,
0xfc
,
0x10
,
0x00
,
0x05
,
0x61
}},
/* 0x9 */
{{
0x65
,
0x4f
,
0x4f
,
0x89
,
0x58
,
0x80
,
0x01
,
0x3e
,
0xe0
,
0x83
,
0xdf
,
0xdf
,
0x02
,
0x00
,
0x00
,
0x05
,
0x61
}},
/* 0xa */
{{
0x67
,
0x4f
,
0x4f
,
0x8b
,
0x58
,
0x81
,
0x0d
,
0x3e
,
0xe0
,
0x83
,
0xdf
,
0xdf
,
0x0e
,
0x00
,
0x00
,
0x05
,
0x61
}},
/* 0xb */
{{
0x65
,
0x4f
,
0x4f
,
0x89
,
0x57
,
0x9f
,
0xfb
,
0x1f
,
0xe6
,
0x8a
,
0xdf
,
0xdf
,
0xfc
,
0x10
,
0x00
,
0x01
,
0x00
}},
/* 0xc */
{{
0x7b
,
0x63
,
0x63
,
0x9f
,
0x6a
,
0x93
,
0x6f
,
0xf0
,
0x58
,
0x8a
,
0x57
,
0x57
,
0x70
,
0x20
,
0x00
,
0x05
,
0x01
}},
/* 0xd */
{{
0x7f
,
0x63
,
0x63
,
0x83
,
0x6c
,
0x1c
,
0x72
,
0xf0
,
0x58
,
0x8c
,
0x57
,
0x57
,
0x73
,
0x20
,
0x00
,
0x06
,
0x01
}},
/* 0xe */
{{
0x7d
,
0x63
,
0x63
,
0x81
,
0x6e
,
0x1d
,
0x98
,
0xf0
,
0x7c
,
0x82
,
0x57
,
0x57
,
0x99
,
0x00
,
0x00
,
0x06
,
0x01
}},
/* 0xf */
{{
0x7f
,
0x63
,
0x63
,
0x83
,
0x69
,
0x13
,
0x6f
,
0xf0
,
0x58
,
0x8b
,
0x57
,
0x57
,
0x70
,
0x20
,
0x00
,
0x06
,
0x01
}},
/* 0x10 */
{{
0x7e
,
0x63
,
0x63
,
0x82
,
0x6b
,
0x13
,
0x75
,
0xf0
,
0x58
,
0x8b
,
0x57
,
0x57
,
0x76
,
0x20
,
0x00
,
0x06
,
0x01
}},
/* 0x11 */
{{
0x81
,
0x63
,
0x63
,
0x85
,
0x6d
,
0x18
,
0x7a
,
0xf0
,
0x58
,
0x8b
,
0x57
,
0x57
,
0x7b
,
0x20
,
0x00
,
0x06
,
0x61
}},
/* 0x12 */
{{
0x83
,
0x63
,
0x63
,
0x87
,
0x6e
,
0x19
,
0x81
,
0xf0
,
0x58
,
0x8b
,
0x57
,
0x57
,
0x82
,
0x20
,
0x00
,
0x06
,
0x61
}},
/* 0x13 */
{{
0x85
,
0x63
,
0x63
,
0x89
,
0x6f
,
0x1a
,
0x91
,
0xf0
,
0x58
,
0x8b
,
0x57
,
0x57
,
0x92
,
0x20
,
0x00
,
0x06
,
0x61
}},
/* 0x14 */
{{
0x99
,
0x7f
,
0x7f
,
0x9d
,
0x84
,
0x1a
,
0x96
,
0x1f
,
0x7f
,
0x83
,
0x7f
,
0x7f
,
0x97
,
0x10
,
0x00
,
0x02
,
0x00
}},
/* 0x15 */
{{
0xa3
,
0x7f
,
0x7f
,
0x87
,
0x86
,
0x97
,
0x24
,
0xf5
,
0x02
,
0x88
,
0xff
,
0xff
,
0x25
,
0x10
,
0x00
,
0x02
,
0x01
}},
/* 0x16 */
{{
0xa1
,
0x7f
,
0x7f
,
0x85
,
0x86
,
0x97
,
0x24
,
0xf5
,
0x02
,
0x88
,
0xff
,
0xff
,
0x25
,
0x10
,
0x00
,
0x02
,
0x01
}},
/* 0x17 */
{{
0x9f
,
0x7f
,
0x7f
,
0x83
,
0x85
,
0x91
,
0x1e
,
0xf5
,
0x00
,
0x83
,
0xff
,
0xff
,
0x1f
,
0x10
,
0x00
,
0x02
,
0x01
}},
/* 0x18 */
{{
0xa7
,
0x7f
,
0x7f
,
0x8b
,
0x89
,
0x95
,
0x26
,
0xf5
,
0x00
,
0x83
,
0xff
,
0xff
,
0x27
,
0x10
,
0x00
,
0x02
,
0x01
}},
/* 0x19 */
{{
0xa9
,
0x7f
,
0x7f
,
0x8d
,
0x8c
,
0x9a
,
0x2c
,
0xf5
,
0x00
,
0x83
,
0xff
,
0xff
,
0x2d
,
0x14
,
0x00
,
0x02
,
0x62
}},
/* 0x1a */
{{
0xab
,
0x7f
,
0x7f
,
0x8f
,
0x8d
,
0x9b
,
0x35
,
0xf5
,
0x00
,
0x83
,
0xff
,
0xff
,
0x36
,
0x14
,
0x00
,
0x02
,
0x62
}},
/* 0x1b */
{{
0xcf
,
0x9f
,
0x9f
,
0x93
,
0xb2
,
0x01
,
0x14
,
0xba
,
0x00
,
0x83
,
0xff
,
0xff
,
0x15
,
0x00
,
0x00
,
0x03
,
0x00
}},
/* 0x1c */
{{
0xce
,
0x9f
,
0x9f
,
0x92
,
0xa9
,
0x17
,
0x28
,
0x5a
,
0x00
,
0x83
,
0xff
,
0xff
,
0x29
,
0x09
,
0x00
,
0x07
,
0x01
}},
/* 0x1d */
{{
0xce
,
0x9f
,
0x9f
,
0x92
,
0xa5
,
0x17
,
0x28
,
0x5a
,
0x00
,
0x83
,
0xff
,
0xff
,
0x29
,
0x09
,
0x00
,
0x07
,
0x01
}},
/* 0x1e */
{{
0xd3
,
0x9f
,
0x9f
,
0x97
,
0xab
,
0x1f
,
0x2e
,
0x5a
,
0x00
,
0x83
,
0xff
,
0xff
,
0x2f
,
0x09
,
0x00
,
0x07
,
0x01
}},
/* 0x1f */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x20 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x21 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x22 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x23 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x24 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x25 */
{{
0x09
,
0xc7
,
0xc7
,
0x8d
,
0xd3
,
0x0b
,
0xe0
,
0x10
,
0xb0
,
0x83
,
0xaf
,
0xaf
,
0xe1
,
0x2f
,
0x01
,
0x04
,
0x00
}},
/* 0x26 */
{{
0x40
,
0xef
,
0xef
,
0x84
,
0x03
,
0x1d
,
0xda
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xdb
,
0x1f
,
0x41
,
0x01
,
0x00
}},
/* 0x27 */
{{
0x43
,
0xef
,
0xef
,
0x87
,
0x06
,
0x00
,
0xd4
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xd5
,
0x1f
,
0x41
,
0x05
,
0x63
}},
/* 0x28 */
{{
0x45
,
0xef
,
0xef
,
0x89
,
0x07
,
0x01
,
0xd9
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xda
,
0x1f
,
0x41
,
0x05
,
0x63
}},
/* 0x29 */
{{
0x40
,
0xef
,
0xef
,
0x84
,
0x03
,
0x1d
,
0xda
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xdb
,
0x1f
,
0x41
,
0x01
,
0x00
}},
/* 0x2a */
{{
0x40
,
0xef
,
0xef
,
0x84
,
0x03
,
0x1d
,
0xda
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xdb
,
0x1f
,
0x41
,
0x01
,
0x00
}},
/* 0x2b */
{{
0x40
,
0xef
,
0xef
,
0x84
,
0x03
,
0x1d
,
0xda
,
0x1f
,
0xa0
,
0x83
,
0x9f
,
0x9f
,
0xdb
,
0x1f
,
0x41
,
0x01
,
0x00
}},
/* 0x2c */
{{
0x59
,
0xff
,
0xff
,
0x9d
,
0x17
,
0x13
,
0x33
,
0xba
,
0x00
,
0x83
,
0xff
,
0xff
,
0x34
,
0x0f
,
0x41
,
0x05
,
0x44
}},
/* 0x2d */
{{
0x5b
,
0xff
,
0xff
,
0x9f
,
0x18
,
0x14
,
0x38
,
0xba
,
0x00
,
0x83
,
0xff
,
0xff
,
0x39
,
0x0f
,
0x41
,
0x05
,
0x44
}},
/* 0x2e */
{{
0x5b
,
0xff
,
0xff
,
0x9f
,
0x18
,
0x14
,
0x3d
,
0xba
,
0x00
,
0x83
,
0xff
,
0xff
,
0x3e
,
0x0f
,
0x41
,
0x05
,
0x44
}},
/* 0x2f */
{{
0x5d
,
0xff
,
0xff
,
0x81
,
0x19
,
0x95
,
0x41
,
0xba
,
0x00
,
0x84
,
0xff
,
0xff
,
0x42
,
0x0f
,
0x41
,
0x05
,
0x44
}},
/* 0x30 */
{{
0x55
,
0xff
,
0xff
,
0x99
,
0x0d
,
0x0c
,
0x3e
,
0xba
,
0x00
,
0x84
,
0xff
,
0xff
,
0x3f
,
0x0f
,
0x41
,
0x05
,
0x00
}},
/* 0x31 */
{{
0x7f
,
0x63
,
0x63
,
0x83
,
0x6c
,
0x1c
,
0x72
,
0xba
,
0x27
,
0x8b
,
0xdf
,
0xdf
,
0x73
,
0x00
,
0x00
,
0x06
,
0x01
}},
/* 0x32 */
{{
0x7f
,
0x63
,
0x63
,
0x83
,
0x69
,
0x13
,
0x6f
,
0xba
,
0x26
,
0x89
,
0xdf
,
0xdf
,
0x6f
,
0x00
,
0x00
,
0x06
,
0x01
}},
/* 0x33 */
{{
0x7f
,
0x63
,
0x63
,
0x82
,
0x6b
,
0x13
,
0x75
,
0xba
,
0x29
,
0x8c
,
0xdf
,
0xdf
,
0x75
,
0x00
,
0x00
,
0x06
,
0x01
}},
/* 0x34 */
{{
0xa3
,
0x7f
,
0x7f
,
0x87
,
0x86
,
0x97
,
0x24
,
0xf1
,
0xaf
,
0x85
,
0x3f
,
0x3f
,
0x25
,
0x30
,
0x00
,
0x02
,
0x01
}},
/* 0x35 */
{{
0x9f
,
0x7f
,
0x7f
,
0x83
,
0x85
,
0x91
,
0x1e
,
0xf1
,
0xad
,
0x81
,
0x3f
,
0x3f
,
0x1f
,
0x30
,
0x00
,
0x02
,
0x01
}},
/* 0x36 */
{{
0xa7
,
0x7f
,
0x7f
,
0x88
,
0x89
,
0x95
,
0x26
,
0xf1
,
0xb1
,
0x85
,
0x3f
,
0x3f
,
0x27
,
0x30
,
0x00
,
0x02
,
0x01
}},
/* 0x37 */
{{
0xce
,
0x9f
,
0x9f
,
0x92
,
0xa9
,
0x17
,
0x28
,
0xc4
,
0x7a
,
0x8e
,
0xcf
,
0xcf
,
0x29
,
0x21
,
0x00
,
0x07
,
0x01
}},
/* 0x38 */
{{
0xce
,
0x9f
,
0x9f
,
0x92
,
0xa5
,
0x17
,
0x28
,
0xd4
,
0x7a
,
0x8e
,
0xcf
,
0xcf
,
0x29
,
0x21
,
0x00
,
0x07
,
0x01
}},
/* 0x39 */
{{
0xd3
,
0x9f
,
0x9f
,
0x97
,
0xab
,
0x1f
,
0x2e
,
0xd4
,
0x7d
,
0x81
,
0xcf
,
0xcf
,
0x2f
,
0x21
,
0x00
,
0x07
,
0x01
}},
/* 0x3a */
{{
0xdc
,
0x9f
,
0x9f
,
0x80
,
0xaf
,
0x9d
,
0xe6
,
0xff
,
0xc0
,
0x83
,
0xbf
,
0xbf
,
0xe7
,
0x10
,
0x00
,
0x07
,
0x01
}},
/* 0x3b */
{{
0x6b
,
0x59
,
0x59
,
0x8f
,
0x5e
,
0x8c
,
0x0b
,
0x3e
,
0xe9
,
0x8b
,
0xdf
,
0xe7
,
0x04
,
0x00
,
0x00
,
0x05
,
0x00
}},
/* 0x3c */
{{
0x6d
,
0x59
,
0x59
,
0x91
,
0x60
,
0x89
,
0x53
,
0xf0
,
0x41
,
0x84
,
0x3f
,
0x3f
,
0x54
,
0x00
,
0x00
,
0x05
,
0x41
}},
/* 0x3d */
{{
0x86
,
0x6a
,
0x6a
,
0x8a
,
0x74
,
0x06
,
0x8c
,
0x15
,
0x4f
,
0x83
,
0xef
,
0xef
,
0x8d
,
0x30
,
0x00
,
0x02
,
0x00
}},
/* 0x3e */
{{
0x81
,
0x6a
,
0x6a
,
0x85
,
0x70
,
0x00
,
0x0f
,
0x3e
,
0xeb
,
0x8e
,
0xdf
,
0xdf
,
0x10
,
0x00
,
0x00
,
0x02
,
0x00
}},
/* 0x3f */
{{
0xa3
,
0x7f
,
0x7f
,
0x87
,
0x86
,
0x97
,
0x1e
,
0xf1
,
0xae
,
0x85
,
0x57
,
0x57
,
0x1f
,
0x30
,
0x00
,
0x02
,
0x01
}},
/* 0x40 */
{{
0xa3
,
0x7f
,
0x7f
,
0x87
,
0x86
,
0x97
,
0x24
,
0xf5
,
0x02
,
0x88
,
0xff
,
0xff
,
0x25
,
0x10
,
0x00
,
0x02
,
0x01
}},
/* 0x41 */
{{
0xce
,
0x9f
,
0x9f
,
0x92
,
0xa9
,
0x17
,
0x20
,
0xf5
,
0x03
,
0x88
,
0xff
,
0xff
,
0x21
,
0x10
,
0x00
,
0x07
,
0x01
}},
/* 0x42 */
{{
0xe6
,
0xae
,
0xae
,
0x8a
,
0xbd
,
0x90
,
0x3d
,
0x10
,
0x1a
,
0x8d
,
0x19
,
0x19
,
0x3e
,
0x2f
,
0x00
,
0x03
,
0x00
}},
/* 0x43 */
{{
0xc3
,
0x8f
,
0x8f
,
0x87
,
0x9b
,
0x0b
,
0x82
,
0xef
,
0x60
,
0x83
,
0x5f
,
0x5f
,
0x83
,
0x10
,
0x00
,
0x07
,
0x01
}},
/* 0x44 */
{{
0x86
,
0x69
,
0x69
,
0x8A
,
0x74
,
0x06
,
0x8C
,
0x15
,
0x4F
,
0x83
,
0xEF
,
0xEF
,
0x8D
,
0x30
,
0x00
,
0x02
,
0x00
}},
/* 0x45 */
{{
0x83
,
0x69
,
0x69
,
0x87
,
0x6f
,
0x1d
,
0x03
,
0x3E
,
0xE5
,
0x8d
,
0xDF
,
0xe4
,
0x04
,
0x00
,
0x00
,
0x06
,
0x00
}},
/* 0x46 */
{{
0x86
,
0x6A
,
0x6A
,
0x8A
,
0x74
,
0x06
,
0x8C
,
0x15
,
0x4F
,
0x83
,
0xEF
,
0xEF
,
0x8D
,
0x30
,
0x00
,
0x02
,
0x00
}},
/* 0x47 */
{{
0x81
,
0x6A
,
0x6A
,
0x85
,
0x70
,
0x00
,
0x0F
,
0x3E
,
0xEB
,
0x8E
,
0xDF
,
0xDF
,
0x10
,
0x00
,
0x00
,
0x02
,
0x00
}},
/* 0x48 */
{{
0xdd
,
0xa9
,
0xa9
,
0x81
,
0xb4
,
0x97
,
0x26
,
0xfd
,
0x01
,
0x8d
,
0xff
,
0x00
,
0x27
,
0x10
,
0x00
,
0x03
,
0x01
}},
/* 0x49 */
{{
0xd9
,
0x8f
,
0x8f
,
0x9d
,
0xba
,
0x0a
,
0x8a
,
0xff
,
0x60
,
0x8b
,
0x5f
,
0x5f
,
0x8b
,
0x10
,
0x00
,
0x03
,
0x01
}},
/* 0x4a */
{{
0xea
,
0xae
,
0xae
,
0x8e
,
0xba
,
0x82
,
0x40
,
0x10
,
0x1b
,
0x87
,
0x19
,
0x1a
,
0x41
,
0x0f
,
0x00
,
0x03
,
0x00
}},
/* 0x4b */
{{
0xd3
,
0x9f
,
0x9f
,
0x97
,
0xab
,
0x1f
,
0xf1
,
0xff
,
0xc0
,
0x83
,
0xbf
,
0xbf
,
0xf2
,
0x10
,
0x00
,
0x07
,
0x01
}},
/* 0x4c */
{{
0x75
,
0x5f
,
0x5f
,
0x99
,
0x66
,
0x90
,
0x53
,
0xf0
,
0x41
,
0x84
,
0x3f
,
0x3f
,
0x54
,
0x00
,
0x00
,
0x05
,
0x41
}},
{{
0x2d
,
0x27
,
0x28
,
0x90
,
0x2c
,
0x80
,
0x0b
,
0x3e
,
0xe9
,
0x8b
,
0xdf
,
0xe7
,
0x04
,
0x00
,
0x00
,
0x00
,
0x00
}},
/* 0x4e */
{{
0xcd
,
0x9f
,
0x9f
,
0x91
,
0xab
,
0x1c
,
0x3a
,
0xff
,
0x20
,
0x83
,
0x1f
,
0x1f
,
0x3b
,
0x10
,
0x00
,
0x07
,
0x21
}},
/* 0x4f */
{{
0x15
,
0xd1
,
0xd1
,
0x99
,
0xe2
,
0x19
,
0x3d
,
0x10
,
0x1a
,
0x8d
,
0x19
,
0x19
,
0x3e
,
0x2f
,
0x01
,
0x0c
,
0x20
}},
/* 0x50 */
{{
0x0e
,
0xef
,
0xef
,
0x92
,
0xfe
,
0x03
,
0x30
,
0xf0
,
0x1e
,
0x83
,
0x1b
,
0x1c
,
0x31
,
0x00
,
0x01
,
0x00
,
0x61
}},
/* 0x51 */
{{
0x85
,
0x77
,
0x77
,
0x89
,
0x7d
,
0x01
,
0x31
,
0xf0
,
0x1e
,
0x84
,
0x1b
,
0x1c
,
0x32
,
0x00
,
0x00
,
0x02
,
0x41
}},
/* 0x52 */
{{
0x87
,
0x77
,
0x77
,
0x8b
,
0x81
,
0x0b
,
0x68
,
0xf0
,
0x5a
,
0x80
,
0x57
,
0x57
,
0x69
,
0x00
,
0x00
,
0x02
,
0x01
}},
/* 0x53 */
{{
0xcd
,
0x8f
,
0x8f
,
0x91
,
0x9b
,
0x1b
,
0x7a
,
0xff
,
0x64
,
0x8c
,
0x5f
,
0x62
,
0x7b
,
0x10
,
0x00
,
0x07
,
0x41
}}
/* 0x54 */
};
static
struct
SiS_VCLKData
SiSUSB_VCLKData
[]
=
{
{
0x1b
,
0xe1
,
25
},
/* 0x00 */
{
0x4e
,
0xe4
,
28
},
/* 0x01 */
{
0x57
,
0xe4
,
31
},
/* 0x02 */
{
0xc3
,
0xc8
,
36
},
/* 0x03 */
{
0x42
,
0xe2
,
40
},
/* 0x04 */
{
0xfe
,
0xcd
,
43
},
/* 0x05 */
{
0x5d
,
0xc4
,
44
},
/* 0x06 */
{
0x52
,
0xe2
,
49
},
/* 0x07 */
{
0x53
,
0xe2
,
50
},
/* 0x08 */
{
0x74
,
0x67
,
52
},
/* 0x09 */
{
0x6d
,
0x66
,
56
},
/* 0x0a */
{
0x5a
,
0x64
,
65
},
/* 0x0b */
{
0x46
,
0x44
,
67
},
/* 0x0c */
{
0xb1
,
0x46
,
68
},
/* 0x0d */
{
0xd3
,
0x4a
,
72
},
/* 0x0e */
{
0x29
,
0x61
,
75
},
/* 0x0f */
{
0x6e
,
0x46
,
76
},
/* 0x10 */
{
0x2b
,
0x61
,
78
},
/* 0x11 */
{
0x31
,
0x42
,
79
},
/* 0x12 */
{
0xab
,
0x44
,
83
},
/* 0x13 */
{
0x46
,
0x25
,
84
},
/* 0x14 */
{
0x78
,
0x29
,
86
},
/* 0x15 */
{
0x62
,
0x44
,
94
},
/* 0x16 */
{
0x2b
,
0x41
,
104
},
/* 0x17 */
{
0x3a
,
0x23
,
105
},
/* 0x18 */
{
0x70
,
0x44
,
108
},
/* 0x19 */
{
0x3c
,
0x23
,
109
},
/* 0x1a */
{
0x5e
,
0x43
,
113
},
/* 0x1b */
{
0xbc
,
0x44
,
116
},
/* 0x1c */
{
0xe0
,
0x46
,
132
},
/* 0x1d */
{
0x54
,
0x42
,
135
},
/* 0x1e */
{
0xea
,
0x2a
,
139
},
/* 0x1f */
{
0x41
,
0x22
,
157
},
/* 0x20 */
{
0x70
,
0x24
,
162
},
/* 0x21 */
{
0x30
,
0x21
,
175
},
/* 0x22 */
{
0x4e
,
0x22
,
189
},
/* 0x23 */
{
0xde
,
0x26
,
194
},
/* 0x24 */
{
0x62
,
0x06
,
202
},
/* 0x25 */
{
0x3f
,
0x03
,
229
},
/* 0x26 */
{
0xb8
,
0x06
,
234
},
/* 0x27 */
{
0x34
,
0x02
,
253
},
/* 0x28 */
{
0x58
,
0x04
,
255
},
/* 0x29 */
{
0x24
,
0x01
,
265
},
/* 0x2a */
{
0x9b
,
0x02
,
267
},
/* 0x2b */
{
0x70
,
0x05
,
270
},
/* 0x2c */
{
0x25
,
0x01
,
272
},
/* 0x2d */
{
0x9c
,
0x02
,
277
},
/* 0x2e */
{
0x27
,
0x01
,
286
},
/* 0x2f */
{
0x3c
,
0x02
,
291
},
/* 0x30 */
{
0xef
,
0x0a
,
292
},
/* 0x31 */
{
0xf6
,
0x0a
,
310
},
/* 0x32 */
{
0x95
,
0x01
,
315
},
/* 0x33 */
{
0xf0
,
0x09
,
324
},
/* 0x34 */
{
0xfe
,
0x0a
,
331
},
/* 0x35 */
{
0xf3
,
0x09
,
332
},
/* 0x36 */
{
0xea
,
0x08
,
340
},
/* 0x37 */
{
0xe8
,
0x07
,
376
},
/* 0x38 */
{
0xde
,
0x06
,
389
},
/* 0x39 */
{
0x52
,
0x2a
,
54
},
/* 0x3a 301 TV */
{
0x52
,
0x6a
,
27
},
/* 0x3b 301 TV */
{
0x62
,
0x24
,
70
},
/* 0x3c 301 TV */
{
0x62
,
0x64
,
70
},
/* 0x3d 301 TV */
{
0xa8
,
0x4c
,
30
},
/* 0x3e 301 TV */
{
0x20
,
0x26
,
33
},
/* 0x3f 301 TV */
{
0x31
,
0xc2
,
39
},
/* 0x40 */
{
0x60
,
0x36
,
30
},
/* 0x41 Chrontel */
{
0x40
,
0x4a
,
28
},
/* 0x42 Chrontel */
{
0x9f
,
0x46
,
44
},
/* 0x43 Chrontel */
{
0x97
,
0x2c
,
26
},
/* 0x44 */
{
0x44
,
0xe4
,
25
},
/* 0x45 Chrontel */
{
0x7e
,
0x32
,
47
},
/* 0x46 Chrontel */
{
0x8a
,
0x24
,
31
},
/* 0x47 Chrontel */
{
0x97
,
0x2c
,
26
},
/* 0x48 Chrontel */
{
0xce
,
0x3c
,
39
},
/* 0x49 */
{
0x52
,
0x4a
,
36
},
/* 0x4a Chrontel */
{
0x34
,
0x61
,
95
},
/* 0x4b */
{
0x78
,
0x27
,
108
},
/* 0x4c - was 102 */
{
0x66
,
0x43
,
123
},
/* 0x4d Modes 0x26-0x28 (1400x1050) */
{
0x41
,
0x4e
,
21
},
/* 0x4e */
{
0xa1
,
0x4a
,
29
},
/* 0x4f Chrontel */
{
0x19
,
0x42
,
42
},
/* 0x50 */
{
0x54
,
0x46
,
58
},
/* 0x51 Chrontel */
{
0x25
,
0x42
,
61
},
/* 0x52 */
{
0x44
,
0x44
,
66
},
/* 0x53 Chrontel */
{
0x3a
,
0x62
,
70
},
/* 0x54 Chrontel */
{
0x62
,
0xc6
,
34
},
/* 0x55 848x480-60 */
{
0x6a
,
0xc6
,
37
},
/* 0x56 848x480-75 - TEMP */
{
0xbf
,
0xc8
,
35
},
/* 0x57 856x480-38i,60 */
{
0x30
,
0x23
,
88
},
/* 0x58 1360x768-62 (is 60Hz!) */
{
0x52
,
0x07
,
149
},
/* 0x59 1280x960-85 */
{
0x56
,
0x07
,
156
},
/* 0x5a 1400x1050-75 */
{
0x70
,
0x29
,
81
},
/* 0x5b 1280x768 LCD */
{
0x45
,
0x25
,
83
},
/* 0x5c 1280x800 */
{
0x70
,
0x0a
,
147
},
/* 0x5d 1680x1050 */
{
0x70
,
0x24
,
162
},
/* 0x5e 1600x1200 */
{
0x5a
,
0x64
,
65
},
/* 0x5f 1280x720 - temp */
{
0x63
,
0x46
,
68
},
/* 0x60 1280x768_2 */
{
0x31
,
0x42
,
79
},
/* 0x61 1280x768_3 - temp */
{
0
,
0
,
0
},
/* 0x62 - custom (will be filled out at run-time) */
{
0x5a
,
0x64
,
65
},
/* 0x63 1280x720 (LCD LVDS) */
{
0x70
,
0x28
,
90
},
/* 0x64 1152x864@60 */
{
0x41
,
0xc4
,
32
},
/* 0x65 848x480@60 */
{
0x5c
,
0xc6
,
32
},
/* 0x66 856x480@60 */
{
0x76
,
0xe7
,
27
},
/* 0x67 720x480@60 */
{
0x5f
,
0xc6
,
33
},
/* 0x68 720/768x576@60 */
{
0x52
,
0x27
,
75
},
/* 0x69 1920x1080i 60Hz interlaced */
{
0x7c
,
0x6b
,
38
},
/* 0x6a 960x540@60 */
{
0xe3
,
0x56
,
41
},
/* 0x6b 960x600@60 */
{
0x45
,
0x25
,
83
},
/* 0x6c 1280x800 */
{
0x70
,
0x28
,
90
},
/* 0x6d 1152x864@60 */
{
0x15
,
0xe1
,
20
},
/* 0x6e 640x400@60 (fake, not actually used) */
{
0x5f
,
0xc6
,
33
},
/* 0x6f 720x576@60 */
{
0x37
,
0x5a
,
10
},
/* 0x70 320x200@60 (fake, not actually used) */
{
0x2b
,
0xc2
,
35
}
/* 0x71 768@576@60 */
};
void
SiSUSBRegInit
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
long
BaseAddr
);
unsigned
short
SiSUSB_GetModeID
(
int
HDisplay
,
int
VDisplay
,
int
Depth
);
int
SiSUSBSetMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
ModeNo
);
int
SiSUSBSetVESAMode
(
struct
SiS_Private
*
SiS_Pr
,
unsigned
short
VModeNo
);
extern
int
sisusb_setreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
data
);
extern
int
sisusb_getreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
*
data
);
extern
int
sisusb_setidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
data
);
extern
int
sisusb_getidxreg
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
*
data
);
extern
int
sisusb_setidxregandor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
,
u8
myor
);
extern
int
sisusb_setidxregor
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
index
,
u8
myor
);
extern
int
sisusb_setidxregand
(
struct
sisusb_usb_data
*
sisusb
,
int
port
,
u8
idx
,
u8
myand
);
#endif
drivers/usb/misc/sisusbvga/sisusb_struct.h
0 → 100644
View file @
cc6120c6
/*
* General structure definitions for universal mode switching modules
*
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
*
* If distributed as part of the Linux kernel, the following license terms
* apply:
*
* * 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 named License,
* * or 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
*
* Otherwise, the following license terms apply:
*
* * Redistribution and use in source and binary forms, with or without
* * modification, are permitted provided that the following conditions
* * are met:
* * 1) Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* * 2) Redistributions in binary form must reproduce the above copyright
* * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* * 3) The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission.
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
*/
#ifndef _SISUSB_STRUCT_H_
#define _SISUSB_STRUCT_H_
struct
SiS_St
{
unsigned
char
St_ModeID
;
unsigned
short
St_ModeFlag
;
unsigned
char
St_StTableIndex
;
unsigned
char
St_CRT2CRTC
;
unsigned
char
St_ResInfo
;
unsigned
char
VB_StTVFlickerIndex
;
unsigned
char
VB_StTVEdgeIndex
;
unsigned
char
VB_StTVYFilterIndex
;
unsigned
char
St_PDC
;
};
struct
SiS_StandTable
{
unsigned
char
CRT_COLS
;
unsigned
char
ROWS
;
unsigned
char
CHAR_HEIGHT
;
unsigned
short
CRT_LEN
;
unsigned
char
SR
[
4
];
unsigned
char
MISC
;
unsigned
char
CRTC
[
0x19
];
unsigned
char
ATTR
[
0x14
];
unsigned
char
GRC
[
9
];
};
struct
SiS_StResInfo_S
{
unsigned
short
HTotal
;
unsigned
short
VTotal
;
};
struct
SiS_Ext
{
unsigned
char
Ext_ModeID
;
unsigned
short
Ext_ModeFlag
;
unsigned
short
Ext_VESAID
;
unsigned
char
Ext_RESINFO
;
unsigned
char
VB_ExtTVFlickerIndex
;
unsigned
char
VB_ExtTVEdgeIndex
;
unsigned
char
VB_ExtTVYFilterIndex
;
unsigned
char
VB_ExtTVYFilterIndexROM661
;
unsigned
char
REFindex
;
char
ROMMODEIDX661
;
};
struct
SiS_Ext2
{
unsigned
short
Ext_InfoFlag
;
unsigned
char
Ext_CRT1CRTC
;
unsigned
char
Ext_CRTVCLK
;
unsigned
char
Ext_CRT2CRTC
;
unsigned
char
Ext_CRT2CRTC_NS
;
unsigned
char
ModeID
;
unsigned
short
XRes
;
unsigned
short
YRes
;
unsigned
char
Ext_PDC
;
unsigned
char
Ext_FakeCRT2CRTC
;
unsigned
char
Ext_FakeCRT2Clk
;
};
struct
SiS_CRT1Table
{
unsigned
char
CR
[
17
];
};
struct
SiS_VCLKData
{
unsigned
char
SR2B
,
SR2C
;
unsigned
short
CLOCK
;
};
struct
SiS_ModeResInfo
{
unsigned
short
HTotal
;
unsigned
short
VTotal
;
unsigned
char
XChar
;
unsigned
char
YChar
;
};
struct
SiS_Private
{
void
*
sisusb
;
unsigned
long
IOAddress
;
unsigned
long
SiS_P3c4
;
unsigned
long
SiS_P3d4
;
unsigned
long
SiS_P3c0
;
unsigned
long
SiS_P3ce
;
unsigned
long
SiS_P3c2
;
unsigned
long
SiS_P3ca
;
unsigned
long
SiS_P3c6
;
unsigned
long
SiS_P3c7
;
unsigned
long
SiS_P3c8
;
unsigned
long
SiS_P3c9
;
unsigned
long
SiS_P3cb
;
unsigned
long
SiS_P3cc
;
unsigned
long
SiS_P3cd
;
unsigned
long
SiS_P3da
;
unsigned
long
SiS_Part1Port
;
unsigned
char
SiS_MyCR63
;
unsigned
short
SiS_CRT1Mode
;
unsigned
short
SiS_ModeType
;
unsigned
short
SiS_SetFlag
;
const
struct
SiS_StandTable
*
SiS_StandTable
;
const
struct
SiS_St
*
SiS_SModeIDTable
;
const
struct
SiS_Ext
*
SiS_EModeIDTable
;
const
struct
SiS_Ext2
*
SiS_RefIndex
;
const
struct
SiS_CRT1Table
*
SiS_CRT1Table
;
struct
SiS_VCLKData
*
SiS_VCLKData
;
const
struct
SiS_ModeResInfo
*
SiS_ModeResInfo
;
};
#endif
drivers/usb/misc/uss720.c
View file @
cc6120c6
...
...
@@ -3,8 +3,8 @@
/*
* uss720.c -- USS720 USB Parport Cable.
*
* Copyright (C) 1999
* Thomas Sailer (
sailer@ife.ee
.ethz.ch)
* Copyright (C) 1999
, 2005
* Thomas Sailer (
t.sailer@alumni
.ethz.ch)
*
* 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
...
...
@@ -23,103 +23,240 @@
* Based on parport_pc.c
*
* History:
* 0.1 04.08.99 Created
* 0.2 07.08.99 Some fixes mainly suggested by Tim Waugh
* 0.1 04.08.
19
99 Created
* 0.2 07.08.
19
99 Some fixes mainly suggested by Tim Waugh
* Interrupt handling currently disabled because
* usb_request_irq crashes somewhere within ohci.c
* for no apparent reason (that is for me, anyway)
* ECP currently untested
* 0.3 10.08.99 fixing merge errors
* 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable
* 0.5 20.09.99 usb_control_msg wrapper used
* Nov01.00 usb_device_table support by Adam J. Richter
* 08.04.01 Identify version on module load. gb
* 0.3 10.08.1999 fixing merge errors
* 0.4 13.08.1999 Added Vendor/Product ID of Brad Hard's cable
* 0.5 20.09.1999 usb_control_msg wrapper used
* Nov01.2000 usb_device_table support by Adam J. Richter
* 08.04.2001 Identify version on module load. gb
* 0.6 02.09.2005 Fix "scheduling in interrupt" problem by making save/restore
* context asynchronous
*
*/
/*****************************************************************************/
#define DEBUG
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/parport.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/kref.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v0.
5
"
#define DRIVER_AUTHOR "Thomas M. Sailer,
sailer@ife.ee
.ethz.ch"
#define DRIVER_VERSION "v0.
6
"
#define DRIVER_AUTHOR "Thomas M. Sailer,
t.sailer@alumni
.ethz.ch"
#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
/* --------------------------------------------------------------------- */
struct
parport_uss720_private
{
struct
usb_device
*
usbdev
;
void
*
irqhandle
;
unsigned
int
irqpipe
;
unsigned
char
reg
[
7
];
/* USB registers */
struct
parport
*
pp
;
struct
kref
ref_count
;
__u8
reg
[
7
];
/* USB registers */
struct
list_head
asynclist
;
spinlock_t
asynclock
;
};
struct
uss720_async_request
{
struct
parport_uss720_private
*
priv
;
struct
kref
ref_count
;
struct
list_head
asynclist
;
struct
completion
compl
;
struct
urb
*
urb
;
struct
usb_ctrlrequest
dr
;
__u8
reg
[
7
];
};
/* --------------------------------------------------------------------- */
static
int
get_1284_register
(
struct
parport
*
pp
,
unsigned
char
reg
,
unsigned
char
*
val
)
static
void
destroy_priv
(
struct
kref
*
kref
)
{
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
struct
usb_device
*
usbdev
=
priv
->
usbdev
;
static
const
unsigned
char
regindex
[
9
]
=
{
4
,
0
,
1
,
5
,
5
,
0
,
2
,
3
,
6
};
int
ret
;
struct
parport_uss720_private
*
priv
=
container_of
(
kref
,
struct
parport_uss720_private
,
ref_count
);
if
(
!
usbdev
)
return
-
1
;
ret
=
usb_control_msg
(
usbdev
,
usb_rcvctrlpipe
(
usbdev
,
0
),
3
,
0xc0
,
((
unsigned
int
)
reg
)
<<
8
,
0
,
priv
->
reg
,
7
,
1000
);
if
(
ret
!=
7
)
{
printk
(
KERN_DEBUG
"uss720: get_1284_register(%d) failed, status 0x%x expected 7
\n
"
,
(
unsigned
int
)
reg
,
ret
);
ret
=
-
1
;
}
else
{
usb_put_dev
(
priv
->
usbdev
);
kfree
(
priv
);
dbg
(
"destroying priv datastructure"
);
}
static
void
destroy_async
(
struct
kref
*
kref
)
{
struct
uss720_async_request
*
rq
=
container_of
(
kref
,
struct
uss720_async_request
,
ref_count
);
struct
parport_uss720_private
*
priv
=
rq
->
priv
;
unsigned
long
flags
;
if
(
likely
(
rq
->
urb
))
usb_free_urb
(
rq
->
urb
);
spin_lock_irqsave
(
&
priv
->
asynclock
,
flags
);
list_del_init
(
&
rq
->
asynclist
);
spin_unlock_irqrestore
(
&
priv
->
asynclock
,
flags
);
kfree
(
rq
);
kref_put
(
&
priv
->
ref_count
,
destroy_priv
);
}
/* --------------------------------------------------------------------- */
static
void
async_complete
(
struct
urb
*
urb
,
struct
pt_regs
*
ptregs
)
{
struct
uss720_async_request
*
rq
;
struct
parport
*
pp
;
struct
parport_uss720_private
*
priv
;
rq
=
urb
->
context
;
priv
=
rq
->
priv
;
pp
=
priv
->
pp
;
if
(
urb
->
status
)
{
err
(
"async_complete: urb error %d"
,
urb
->
status
);
}
else
if
(
rq
->
dr
.
bRequest
==
3
)
{
memcpy
(
priv
->
reg
,
rq
->
reg
,
sizeof
(
priv
->
reg
));
#if 0
printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n
",
(unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1
],
(unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4
],
(unsigned int)priv->reg[5],
(unsigned int)priv->reg[6]);
dbg("async_complete regs %02x %02x %02x %02x %02x %02x %02x
",
(unsigned int)priv->reg[0], (unsigned int)priv->reg[1], (unsigned int)priv->reg[2
],
(unsigned int)priv->reg[3], (unsigned int)priv->reg[4], (unsigned int)priv->reg[5
],
(unsigned int)priv->reg[6]);
#endif
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if
(
priv
->
reg
[
2
]
&
priv
->
reg
[
1
]
&
0x10
)
if
(
rq
->
reg
[
2
]
&
rq
->
reg
[
1
]
&
0x10
&&
pp
)
parport_generic_irq
(
0
,
pp
,
NULL
);
ret
=
0
;
}
if
(
val
)
*
val
=
priv
->
reg
[(
reg
>=
9
)
?
0
:
regindex
[
reg
]];
return
ret
;
complete
(
&
rq
->
compl
);
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
}
static
int
set_1284_register
(
struct
parport
*
pp
,
unsigned
char
reg
,
unsigned
char
val
)
static
struct
uss720_async_request
*
submit_async_request
(
struct
parport_uss720_private
*
priv
,
__u8
request
,
__u8
requesttype
,
__u16
value
,
__u16
index
,
unsigned
int
mem_flags
)
{
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
struct
usb_device
*
usbdev
=
priv
->
usbdev
;
struct
usb_device
*
usbdev
;
struct
uss720_async_request
*
rq
;
unsigned
long
flags
;
int
ret
;
if
(
!
priv
)
return
NULL
;
usbdev
=
priv
->
usbdev
;
if
(
!
usbdev
)
return
-
1
;
ret
=
usb_control_msg
(
usbdev
,
usb_sndctrlpipe
(
usbdev
,
0
),
4
,
0x40
,
(((
unsigned
int
)
reg
)
<<
8
)
|
val
,
0
,
NULL
,
0
,
1000
);
if
(
ret
)
{
printk
(
KERN_DEBUG
"uss720: set_1284_register(%u,0x%02x) failed, status 0x%x
\n
"
,
(
unsigned
int
)
reg
,
(
unsigned
int
)
val
,
ret
);
}
else
{
#if 0
printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n",
(unsigned int)reg, (unsigned int)val);
#endif
return
NULL
;
rq
=
kmalloc
(
sizeof
(
struct
uss720_async_request
),
mem_flags
);
if
(
!
rq
)
{
err
(
"submit_async_request out of memory"
);
return
NULL
;
}
kref_init
(
&
rq
->
ref_count
);
INIT_LIST_HEAD
(
&
rq
->
asynclist
);
init_completion
(
&
rq
->
compl
);
kref_get
(
&
priv
->
ref_count
);
rq
->
priv
=
priv
;
rq
->
urb
=
usb_alloc_urb
(
0
,
mem_flags
);
if
(
!
rq
->
urb
)
{
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
err
(
"submit_async_request out of memory"
);
return
NULL
;
}
rq
->
dr
.
bRequestType
=
requesttype
;
rq
->
dr
.
bRequest
=
request
;
rq
->
dr
.
wValue
=
cpu_to_le16
(
value
);
rq
->
dr
.
wIndex
=
cpu_to_le16
(
index
);
rq
->
dr
.
wLength
=
cpu_to_le16
((
request
==
3
)
?
sizeof
(
rq
->
reg
)
:
0
);
usb_fill_control_urb
(
rq
->
urb
,
usbdev
,
(
requesttype
&
0x80
)
?
usb_rcvctrlpipe
(
usbdev
,
0
)
:
usb_sndctrlpipe
(
usbdev
,
0
),
(
unsigned
char
*
)
&
rq
->
dr
,
(
request
==
3
)
?
rq
->
reg
:
NULL
,
(
request
==
3
)
?
sizeof
(
rq
->
reg
)
:
0
,
async_complete
,
rq
);
/* rq->urb->transfer_flags |= URB_ASYNC_UNLINK; */
spin_lock_irqsave
(
&
priv
->
asynclock
,
flags
);
list_add_tail
(
&
rq
->
asynclist
,
&
priv
->
asynclist
);
spin_unlock_irqrestore
(
&
priv
->
asynclock
,
flags
);
ret
=
usb_submit_urb
(
rq
->
urb
,
mem_flags
);
if
(
!
ret
)
{
kref_get
(
&
rq
->
ref_count
);
return
rq
;
}
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
err
(
"submit_async_request submit_urb failed with %d"
,
ret
);
return
NULL
;
}
static
unsigned
int
kill_all_async_requests_priv
(
struct
parport_uss720_private
*
priv
)
{
struct
uss720_async_request
*
rq
;
unsigned
long
flags
;
unsigned
int
ret
=
0
;
spin_lock_irqsave
(
&
priv
->
asynclock
,
flags
);
list_for_each_entry
(
rq
,
&
priv
->
asynclist
,
asynclist
)
{
usb_unlink_urb
(
rq
->
urb
);
ret
++
;
}
spin_unlock_irqrestore
(
&
priv
->
asynclock
,
flags
);
return
ret
;
}
/* --------------------------------------------------------------------- */
static
int
get_1284_register
(
struct
parport
*
pp
,
unsigned
char
reg
,
unsigned
char
*
val
,
unsigned
int
mem_flags
)
{
struct
parport_uss720_private
*
priv
;
struct
uss720_async_request
*
rq
;
static
const
unsigned
char
regindex
[
9
]
=
{
4
,
0
,
1
,
5
,
5
,
0
,
2
,
3
,
6
};
int
ret
;
if
(
!
pp
)
return
-
EIO
;
priv
=
pp
->
private_data
;
rq
=
submit_async_request
(
priv
,
3
,
0xc0
,
((
unsigned
int
)
reg
)
<<
8
,
0
,
mem_flags
);
if
(
!
rq
)
{
err
(
"get_1284_register(%u) failed"
,
(
unsigned
int
)
reg
);
return
-
EIO
;
}
if
(
!
val
)
{
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
return
0
;
}
if
(
wait_for_completion_timeout
(
&
rq
->
compl
,
HZ
))
{
ret
=
rq
->
urb
->
status
;
*
val
=
priv
->
reg
[(
reg
>=
9
)
?
0
:
regindex
[
reg
]];
if
(
ret
)
warn
(
"get_1284_register: usb error %d"
,
ret
);
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
return
ret
;
}
warn
(
"get_1284_register timeout"
);
kill_all_async_requests_priv
(
priv
);
return
-
EIO
;
}
static
int
set_1284_register
(
struct
parport
*
pp
,
unsigned
char
reg
,
unsigned
char
val
,
unsigned
int
mem_flags
)
{
struct
parport_uss720_private
*
priv
;
struct
uss720_async_request
*
rq
;
if
(
!
pp
)
return
-
EIO
;
priv
=
pp
->
private_data
;
rq
=
submit_async_request
(
priv
,
4
,
0x40
,
(((
unsigned
int
)
reg
)
<<
8
)
|
val
,
0
,
mem_flags
);
if
(
!
rq
)
{
err
(
"set_1284_register(%u,%u) failed"
,
(
unsigned
int
)
reg
,
(
unsigned
int
)
val
);
return
-
EIO
;
}
kref_put
(
&
rq
->
ref_count
,
destroy_async
);
return
0
;
}
/* --------------------------------------------------------------------- */
/* ECR modes */
#define ECR_SPP 00
#define ECR_PS2 01
...
...
@@ -132,8 +269,9 @@ static int change_mode(struct parport *pp, int m)
{
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
int
mode
;
__u8
reg
;
if
(
get_1284_register
(
pp
,
6
,
NUL
L
))
if
(
get_1284_register
(
pp
,
6
,
&
reg
,
GFP_KERNE
L
))
return
-
EIO
;
/* Bits <7:5> contain the mode. */
mode
=
(
priv
->
reg
[
2
]
>>
5
)
&
0x7
;
...
...
@@ -153,7 +291,7 @@ static int change_mode(struct parport *pp, int m)
case
ECR_ECP
:
/* ECP Parallel Port mode */
/* Poll slowly. */
for
(;;)
{
if
(
get_1284_register
(
pp
,
6
,
NUL
L
))
if
(
get_1284_register
(
pp
,
6
,
&
reg
,
GFP_KERNE
L
))
return
-
EIO
;
if
(
priv
->
reg
[
2
]
&
0x01
)
break
;
...
...
@@ -167,7 +305,9 @@ static int change_mode(struct parport *pp, int m)
}
}
/* Set the mode. */
if
(
set_1284_register
(
pp
,
6
,
m
<<
5
))
if
(
set_1284_register
(
pp
,
6
,
m
<<
5
,
GFP_KERNEL
))
return
-
EIO
;
if
(
get_1284_register
(
pp
,
6
,
&
reg
,
GFP_KERNEL
))
return
-
EIO
;
return
0
;
}
...
...
@@ -179,7 +319,7 @@ static int clear_epp_timeout(struct parport *pp)
{
unsigned
char
stat
;
if
(
get_1284_register
(
pp
,
1
,
&
stat
))
if
(
get_1284_register
(
pp
,
1
,
&
stat
,
GFP_KERNEL
))
return
1
;
return
stat
&
1
;
}
...
...
@@ -205,14 +345,14 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
static
void
parport_uss720_write_data
(
struct
parport
*
pp
,
unsigned
char
d
)
{
set_1284_register
(
pp
,
0
,
d
);
set_1284_register
(
pp
,
0
,
d
,
GFP_KERNEL
);
}
static
unsigned
char
parport_uss720_read_data
(
struct
parport
*
pp
)
{
unsigned
char
ret
;
if
(
get_1284_register
(
pp
,
0
,
&
ret
))
if
(
get_1284_register
(
pp
,
0
,
&
ret
,
GFP_KERNEL
))
return
0
;
return
ret
;
}
...
...
@@ -222,7 +362,7 @@ static void parport_uss720_write_control(struct parport *pp, unsigned char d)
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
d
=
(
d
&
0xf
)
|
(
priv
->
reg
[
1
]
&
0xf0
);
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
;
priv
->
reg
[
1
]
=
d
;
}
...
...
@@ -241,7 +381,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
mask
&=
0x0f
;
val
&=
0x0f
;
d
=
(
priv
->
reg
[
1
]
&
(
~
mask
))
^
val
;
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
0
;
priv
->
reg
[
1
]
=
d
;
return
d
&
0xf
;
...
...
@@ -251,7 +391,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
{
unsigned
char
ret
;
if
(
get_1284_register
(
pp
,
1
,
&
ret
))
if
(
get_1284_register
(
pp
,
1
,
&
ret
,
GFP_KERNEL
))
return
0
;
return
ret
&
0xf8
;
}
...
...
@@ -262,7 +402,7 @@ static void parport_uss720_disable_irq(struct parport *pp)
unsigned
char
d
;
d
=
priv
->
reg
[
1
]
&
~
0x10
;
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
;
priv
->
reg
[
1
]
=
d
;
}
...
...
@@ -273,7 +413,7 @@ static void parport_uss720_enable_irq(struct parport *pp)
unsigned
char
d
;
d
=
priv
->
reg
[
1
]
|
0x10
;
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
;
priv
->
reg
[
1
]
=
d
;
}
...
...
@@ -284,7 +424,7 @@ static void parport_uss720_data_forward (struct parport *pp)
unsigned
char
d
;
d
=
priv
->
reg
[
1
]
&
~
0x20
;
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
;
priv
->
reg
[
1
]
=
d
;
}
...
...
@@ -295,7 +435,7 @@ static void parport_uss720_data_reverse (struct parport *pp)
unsigned
char
d
;
d
=
priv
->
reg
[
1
]
|
0x20
;
if
(
set_1284_register
(
pp
,
2
,
d
))
if
(
set_1284_register
(
pp
,
2
,
d
,
GFP_KERNEL
))
return
;
priv
->
reg
[
1
]
=
d
;
}
...
...
@@ -310,17 +450,23 @@ static void parport_uss720_save_state(struct parport *pp, struct parport_state *
{
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
if
(
get_1284_register
(
pp
,
2
,
NULL
))
#if 0
if (get_1284_register(pp, 2, NULL, GFP_ATOMIC))
return;
#endif
s
->
u
.
pc
.
ctr
=
priv
->
reg
[
1
];
s
->
u
.
pc
.
ecr
=
priv
->
reg
[
2
];
}
static
void
parport_uss720_restore_state
(
struct
parport
*
pp
,
struct
parport_state
*
s
)
{
set_1284_register
(
pp
,
2
,
s
->
u
.
pc
.
ctr
);
set_1284_register
(
pp
,
6
,
s
->
u
.
pc
.
ecr
);
get_1284_register
(
pp
,
2
,
NULL
);
struct
parport_uss720_private
*
priv
=
pp
->
private_data
;
set_1284_register
(
pp
,
2
,
s
->
u
.
pc
.
ctr
,
GFP_ATOMIC
);
set_1284_register
(
pp
,
6
,
s
->
u
.
pc
.
ecr
,
GFP_ATOMIC
);
get_1284_register
(
pp
,
2
,
NULL
,
GFP_ATOMIC
);
priv
->
reg
[
1
]
=
s
->
u
.
pc
.
ctr
;
priv
->
reg
[
2
]
=
s
->
u
.
pc
.
ecr
;
}
static
size_t
parport_uss720_epp_read_data
(
struct
parport
*
pp
,
void
*
buf
,
size_t
length
,
int
flags
)
...
...
@@ -331,7 +477,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
if
(
change_mode
(
pp
,
ECR_EPP
))
return
0
;
for
(;
got
<
length
;
got
++
)
{
if
(
get_1284_register
(
pp
,
4
,
(
char
*
)
buf
))
if
(
get_1284_register
(
pp
,
4
,
(
char
*
)
buf
,
GFP_KERNEL
))
break
;
buf
++
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
...
...
@@ -352,10 +498,10 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
if (change_mode(pp, ECR_EPP))
return 0;
for (; written < length; written++) {
if (set_1284_register(pp, 4, (char *)buf))
if (set_1284_register(pp, 4, (char *)buf
, GFP_KERNEL
))
break;
((char*)buf)++;
if (get_1284_register(pp, 1, NULL))
if (get_1284_register(pp, 1, NULL
, GFP_KERNEL
))
break;
if (priv->reg[0] & 0x01) {
clear_epp_timeout(pp);
...
...
@@ -390,7 +536,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
if
(
change_mode
(
pp
,
ECR_EPP
))
return
0
;
for
(;
got
<
length
;
got
++
)
{
if
(
get_1284_register
(
pp
,
3
,
(
char
*
)
buf
))
if
(
get_1284_register
(
pp
,
3
,
(
char
*
)
buf
,
GFP_KERNEL
))
break
;
buf
++
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
...
...
@@ -410,10 +556,10 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
if
(
change_mode
(
pp
,
ECR_EPP
))
return
0
;
for
(;
written
<
length
;
written
++
)
{
if
(
set_1284_register
(
pp
,
3
,
*
(
char
*
)
buf
))
if
(
set_1284_register
(
pp
,
3
,
*
(
char
*
)
buf
,
GFP_KERNEL
))
break
;
buf
++
;
if
(
get_1284_register
(
pp
,
1
,
NULL
))
if
(
get_1284_register
(
pp
,
1
,
NULL
,
GFP_KERNEL
))
break
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
clear_epp_timeout
(
pp
);
...
...
@@ -467,7 +613,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
if
(
change_mode
(
pp
,
ECR_ECP
))
return
0
;
for
(;
written
<
len
;
written
++
)
{
if
(
set_1284_register
(
pp
,
5
,
*
(
char
*
)
buffer
))
if
(
set_1284_register
(
pp
,
5
,
*
(
char
*
)
buffer
,
GFP_KERNEL
))
break
;
buffer
++
;
}
...
...
@@ -536,93 +682,91 @@ static struct parport_operations parport_uss720_ops =
static
int
uss720_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
usbdev
=
interface_to_usbdev
(
intf
);
struct
usb_device
*
usbdev
=
usb_get_dev
(
interface_to_usbdev
(
intf
)
);
struct
usb_host_interface
*
interface
;
struct
usb_host_endpoint
*
endpoint
;
struct
parport_uss720_private
*
priv
;
struct
parport
*
pp
;
unsigned
char
reg
;
int
i
;
printk
(
KERN_DEBUG
"uss720:
probe: vendor id 0x%x, device id 0x%x
\n
"
,
dbg
(
"
probe: vendor id 0x%x, device id 0x%x
\n
"
,
le16_to_cpu
(
usbdev
->
descriptor
.
idVendor
),
le16_to_cpu
(
usbdev
->
descriptor
.
idProduct
));
/* our known interfaces have 3 alternate settings */
if
(
intf
->
num_altsetting
!=
3
)
if
(
intf
->
num_altsetting
!=
3
)
{
usb_put_dev
(
usbdev
);
return
-
ENODEV
;
}
i
=
usb_set_interface
(
usbdev
,
intf
->
altsetting
->
desc
.
bInterfaceNumber
,
2
);
printk
(
KERN_DEBUG
"uss720: set inteface result %d
\n
"
,
i
);
dbg
(
"set inteface result %d
"
,
i
);
interface
=
intf
->
cur_altsetting
;
/*
* Allocate parport interface
*/
printk
(
KERN_INFO
"uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>
\n
"
);
if
(
!
(
priv
=
kmalloc
(
sizeof
(
struct
parport_uss720_private
),
GFP_KERNEL
)))
if
(
!
(
priv
=
kcalloc
(
sizeof
(
struct
parport_uss720_private
),
1
,
GFP_KERNEL
)))
{
usb_put_dev
(
usbdev
);
return
-
ENOMEM
;
}
priv
->
pp
=
NULL
;
priv
->
usbdev
=
usbdev
;
kref_init
(
&
priv
->
ref_count
);
spin_lock_init
(
&
priv
->
asynclock
);
INIT_LIST_HEAD
(
&
priv
->
asynclist
);
if
(
!
(
pp
=
parport_register_port
(
0
,
PARPORT_IRQ_NONE
,
PARPORT_DMA_NONE
,
&
parport_uss720_ops
)))
{
printk
(
KERN_WARNING
"usb-uss720: could not register parport
\n
"
);
warn
(
"could not register parport
"
);
goto
probe_abort
;
}
priv
->
pp
=
pp
;
pp
->
private_data
=
priv
;
priv
->
usbdev
=
usbdev
;
pp
->
modes
=
PARPORT_MODE_PCSPP
|
PARPORT_MODE_TRISTATE
|
PARPORT_MODE_EPP
|
PARPORT_MODE_ECP
|
PARPORT_MODE_COMPAT
;
/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
set_1284_register
(
pp
,
7
,
0x00
);
set_1284_register
(
pp
,
6
,
0x30
);
/* PS/2 mode */
set_1284_register
(
pp
,
2
,
0x0c
);
set_1284_register
(
pp
,
7
,
0x00
,
GFP_KERNEL
);
set_1284_register
(
pp
,
6
,
0x30
,
GFP_KERNEL
);
/* PS/2 mode */
set_1284_register
(
pp
,
2
,
0x0c
,
GFP_KERNEL
);
/* debugging */
get_1284_register
(
pp
,
0
,
NUL
L
);
printk
(
"uss720: reg: %02x %02x %02x %02x %02x %02x %02x
\n
"
,
get_1284_register
(
pp
,
0
,
&
reg
,
GFP_KERNE
L
);
dbg
(
"reg: %02x %02x %02x %02x %02x %02x %02x
"
,
priv
->
reg
[
0
],
priv
->
reg
[
1
],
priv
->
reg
[
2
],
priv
->
reg
[
3
],
priv
->
reg
[
4
],
priv
->
reg
[
5
],
priv
->
reg
[
6
]);
endpoint
=
&
interface
->
endpoint
[
2
];
printk
(
KERN_DEBUG
"uss720: epaddr %d interval %d
\n
"
,
endpoint
->
desc
.
bEndpointAddress
,
endpoint
->
desc
.
bInterval
);
#if 0
priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
i = usb_request_irq(usbdev, priv->irqpipe,
uss720_irq, endpoint->bInterval,
pp, &priv->irqhandle);
if (i) {
printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
goto probe_abort_port;
}
#endif
dbg
(
"epaddr %d interval %d"
,
endpoint
->
desc
.
bEndpointAddress
,
endpoint
->
desc
.
bInterval
);
parport_announce_port
(
pp
);
usb_set_intfdata
(
intf
,
pp
);
usb_set_intfdata
(
intf
,
pp
);
return
0
;
#if 0
probe_abort_port:
parport_put_port(pp);
#endif
probe_abort:
kfree
(
priv
);
kill_all_async_requests_priv
(
priv
);
kref_put
(
&
priv
->
ref_count
,
destroy_priv
);
return
-
ENODEV
;
}
static
void
uss720_disconnect
(
struct
usb_interface
*
intf
)
{
struct
parport
*
pp
=
usb_get_intfdata
(
intf
);
struct
parport
*
pp
=
usb_get_intfdata
(
intf
);
struct
parport_uss720_private
*
priv
;
struct
usb_device
*
usbdev
;
usb_set_intfdata
(
intf
,
NULL
);
dbg
(
"disconnect"
);
usb_set_intfdata
(
intf
,
NULL
);
if
(
pp
)
{
priv
=
pp
->
private_data
;
parport_remove_port
(
pp
);
#if 0
usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
#endif
usbdev
=
priv
->
usbdev
;
priv
->
usbdev
=
NULL
;
priv
->
pp
=
NULL
;
dbg
(
"parport_remove_port"
);
parport_remove_port
(
pp
);
parport_put_port
(
pp
);
kfree
(
priv
);
kill_all_async_requests_priv
(
priv
);
kref_put
(
&
priv
->
ref_count
,
destroy_priv
);
}
dbg
(
"disconnect done"
);
}
/* table of cables that work through this driver */
...
...
@@ -647,8 +791,8 @@ static struct usb_driver uss720_driver = {
/* --------------------------------------------------------------------- */
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
static
int
__init
uss720_init
(
void
)
...
...
@@ -659,6 +803,9 @@ static int __init uss720_init(void)
goto
out
;
info
(
DRIVER_VERSION
":"
DRIVER_DESC
);
info
(
"NOTE: this is a special purpose driver to allow nonstandard"
);
info
(
"protocols (eg. bitbang) over USS720 usb to parallel cables"
);
info
(
"If you just want to connect to a printer, use usblp instead"
);
out:
return
retval
;
}
...
...
drivers/usb/mon/mon_text.c
View file @
cc6120c6
...
...
@@ -79,7 +79,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
return
'-'
;
if
(
urb
->
transfer_flags
&
URB_NO_SETUP_DMA_MAP
)
return
'D'
;
return
mon_dmapeek
(
ep
->
setup
,
urb
->
setup_dma
,
SETUP_MAX
)
;
if
(
urb
->
setup_packet
==
NULL
)
return
'Z'
;
/* '0' would be not as pretty. */
...
...
drivers/usb/serial/cp2101.c
View file @
cc6120c6
...
...
@@ -32,7 +32,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.0
4
"
#define DRIVER_VERSION "v0.0
5
"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
...
...
@@ -54,8 +54,11 @@ static void cp2101_shutdown(struct usb_serial*);
static
int
debug
;
static
struct
usb_device_id
id_table
[]
=
{
{
USB_DEVICE
(
0x0FCF
,
0x1003
)
},
/* Dynastream ANT development board */
{
USB_DEVICE
(
0x10C4
,
0xEA60
)
},
/* Silicon Labs factory default */
{
USB_DEVICE
(
0x10C4
,
0x80CA
)
},
/* Degree Controls Inc */
{
USB_DEVICE
(
0x10C4
,
0x80F6
)
},
/* Suunto sports instrument */
{
USB_DEVICE
(
0x10A6
,
0xAA26
)
},
/* Knock-off DCU-11 cable */
{
USB_DEVICE
(
0x10AB
,
0x10C5
)
},
/* Siemens MC60 Cable */
{
}
/* Terminating Entry */
};
...
...
drivers/usb/serial/cypress_m8.c
View file @
cc6120c6
...
...
@@ -610,8 +610,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
timeout
=
max
((
HZ
*
2560
)
/
bps
,
HZ
/
10
);
else
timeout
=
2
*
HZ
;
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
timeout
);
schedule_timeout_interruptible
(
timeout
);
dbg
(
"%s - stopping urbs"
,
__FUNCTION__
);
usb_kill_urb
(
port
->
interrupt_in_urb
);
...
...
drivers/usb/serial/ftdi_sio.c
View file @
cc6120c6
...
...
@@ -914,7 +914,7 @@ static void ftdi_determine_type(struct usb_serial_port *port)
unsigned
interfaces
;
/* Assume it is not the original SIO device for now. */
priv
->
baud_base
=
48000000
/
16
;
priv
->
baud_base
=
48000000
/
2
;
priv
->
write_offset
=
0
;
version
=
le16_to_cpu
(
udev
->
descriptor
.
bcdDevice
);
...
...
drivers/usb/serial/pl2303.c
View file @
cc6120c6
...
...
@@ -95,6 +95,7 @@ static struct usb_device_id id_table [] = {
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_PRODUCT_ID
)
},
{
USB_DEVICE
(
SIEMENS_VENDOR_ID
,
SIEMENS_PRODUCT_ID_X65
)
},
{
USB_DEVICE
(
SYNTECH_VENDOR_ID
,
SYNTECH_PRODUCT_ID
)
},
{
USB_DEVICE
(
NOKIA_CA42_VENDOR_ID
,
NOKIA_CA42_PRODUCT_ID
)
},
{
}
/* Terminating entry */
};
...
...
@@ -652,8 +653,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
timeout
=
max
((
HZ
*
2560
)
/
bps
,
HZ
/
10
);
else
timeout
=
2
*
HZ
;
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
timeout
);
schedule_timeout_interruptible
(
timeout
);
/* shutdown our urbs */
dbg
(
"%s - shutting down urbs"
,
__FUNCTION__
);
...
...
drivers/usb/serial/pl2303.h
View file @
cc6120c6
...
...
@@ -58,3 +58,7 @@
#define SYNTECH_VENDOR_ID 0x0745
#define SYNTECH_PRODUCT_ID 0x0001
/* Nokia CA-42 Cable */
#define NOKIA_CA42_VENDOR_ID 0x078b
#define NOKIA_CA42_PRODUCT_ID 0x1234
drivers/usb/storage/scsiglue.c
View file @
cc6120c6
...
...
@@ -227,42 +227,42 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
/* This is always called with scsi_lock(host) held */
static
int
command_abort
(
struct
scsi_cmnd
*
srb
)
{
struct
us_data
*
us
=
host_to_us
(
srb
->
device
->
host
);
US_DEBUGP
(
"%s called
\n
"
,
__FUNCTION__
);
/* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
* bits are protected by the host lock. */
scsi_lock
(
us_to_host
(
us
));
/* Is this command still active? */
if
(
us
->
srb
!=
srb
)
{
scsi_unlock
(
us_to_host
(
us
));
US_DEBUGP
(
"-- nothing to abort
\n
"
);
return
FAILED
;
}
/* Set the TIMED_OUT bit. Also set the ABORTING bit, but only if
* a device reset isn't already in progress (to avoid interfering
* with the reset).
To prevent races with auto-reset, we must
*
stop any ongoing USB transfers while still holding the host
* lock. */
* with the reset).
Note that we must retain the host lock while
*
calling usb_stor_stop_transport(); otherwise it might interfere
*
with an auto-reset that begins as soon as we release the
lock. */
set_bit
(
US_FLIDX_TIMED_OUT
,
&
us
->
flags
);
if
(
!
test_bit
(
US_FLIDX_RESETTING
,
&
us
->
flags
))
{
set_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
usb_stor_stop_transport
(
us
);
}
scsi_unlock
(
us_to_host
(
us
));
/* Wait for the aborted command to finish */
wait_for_completion
(
&
us
->
notify
);
/* Reacquire the lock and allow USB transfers to resume */
clear_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
clear_bit
(
US_FLIDX_TIMED_OUT
,
&
us
->
flags
);
return
SUCCESS
;
}
/* This invokes the transport reset mechanism to reset the state of the
* device */
/* This is always called with scsi_lock(host) held */
static
int
device_reset
(
struct
scsi_cmnd
*
srb
)
{
struct
us_data
*
us
=
host_to_us
(
srb
->
device
->
host
);
...
...
@@ -279,7 +279,6 @@ static int device_reset(struct scsi_cmnd *srb)
}
/* Simulate a SCSI bus reset by resetting the device's USB port. */
/* This is always called with scsi_lock(host) held */
static
int
bus_reset
(
struct
scsi_cmnd
*
srb
)
{
struct
us_data
*
us
=
host_to_us
(
srb
->
device
->
host
);
...
...
@@ -291,7 +290,6 @@ static int bus_reset(struct scsi_cmnd *srb)
result
=
usb_stor_port_reset
(
us
);
up
(
&
(
us
->
dev_semaphore
));
/* lock the host for the return */
return
result
<
0
?
FAILED
:
SUCCESS
;
}
...
...
drivers/usb/storage/unusual_devs.h
View file @
cc6120c6
...
...
@@ -86,6 +86,16 @@ UNUSUAL_DEV( 0x040d, 0x6205, 0x0003, 0x0003,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_IGNORE_RESIDUE
),
/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
* and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
* for USB floppies that need the SINGLE_LUN enforcement.
*/
UNUSUAL_DEV
(
0x0409
,
0x0040
,
0x0000
,
0x9999
,
"NEC"
,
"NEC USB UF000x"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_SINGLE_LUN
),
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
...
...
@@ -96,6 +106,13 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
UNUSUAL_DEV
(
0x0424
,
0x0fdc
,
0x0210
,
0x0210
,
"SMSC"
,
"FDC GOLD-2.30"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_SINGLE_LUN
),
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV
(
0x0436
,
0x0005
,
0x0100
,
0x0100
,
"Microtech"
,
...
...
@@ -103,6 +120,24 @@ UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
US_SC_SCSI
,
US_PR_DPCM_USB
,
NULL
,
0
),
#endif
/*
* Pete Zaitcev <zaitcev@yahoo.com>, from Patrick C. F. Ernzer, bz#162559.
* The key does not actually break, but it returns zero sense which
* makes our SCSI stack to print confusing messages.
*/
UNUSUAL_DEV
(
0x0457
,
0x0150
,
0x0100
,
0x0100
,
"USBest Technology"
,
/* sold by Transcend */
"USB Mass Storage Device"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_NOT_LOCKABLE
),
/* Patch submitted by Daniel Drake <dsd@gentoo.org>
* Device reports nonsense bInterfaceProtocol 6 when connected over USB2 */
UNUSUAL_DEV
(
0x0451
,
0x5416
,
0x0100
,
0x0100
,
"Neuros Audio"
,
"USB 2.0 HD 2.5"
,
US_SC_DEVICE
,
US_PR_BULK
,
NULL
,
US_FL_NEED_OVERRIDE
),
/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV
(
0x0482
,
0x0100
,
0x0100
,
0x0100
,
"Kyocera"
,
...
...
drivers/usb/storage/usb.c
View file @
cc6120c6
...
...
@@ -392,11 +392,16 @@ static int usb_stor_control_thread(void * __us)
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* the TIMED_OUT flag, not srb->result == DID_ABORT, because
*
a timeout/abort request might be received after all the
*
USB processing was complet
e. */
if
(
test_bit
(
US_FLIDX_TIMED_OUT
,
&
us
->
flags
))
*
the timeout might have occurred after the command had
*
already completed with a different result cod
e. */
if
(
test_bit
(
US_FLIDX_TIMED_OUT
,
&
us
->
flags
))
{
complete
(
&
(
us
->
notify
));
/* Allow USB transfers to resume */
clear_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
clear_bit
(
US_FLIDX_TIMED_OUT
,
&
us
->
flags
);
}
/* finished working on this command */
us
->
srb
=
NULL
;
scsi_unlock
(
host
);
...
...
drivers/video/console/Kconfig
View file @
cc6120c6
...
...
@@ -137,7 +137,7 @@ config FONT_8x8
config FONT_8x16
bool "VGA 8x16 font" if FONTS
depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE=y
|| USB_SISUSBVGA_CON
default y if !SPARC32 && !SPARC64 && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
...
...
drivers/video/console/Makefile
View file @
cc6120c6
...
...
@@ -33,6 +33,10 @@ endif
obj-$(CONFIG_FB_STI)
+=
sticore.o font.o
ifeq
($(CONFIG_USB_SISUSBVGA_CON),y)
obj-$(CONFIG_USB_SISUSBVGA)
+=
font.o
endif
# Targets that kbuild needs to know about
targets
:=
promcon_tbl.c
...
...
include/linux/usbdevice_fs.h
View file @
cc6120c6
...
...
@@ -32,7 +32,6 @@
#define _LINUX_USBDEVICE_FS_H
#include <linux/types.h>
#include <linux/compat.h>
/* --------------------------------------------------------------------- */
...
...
@@ -125,6 +124,7 @@ struct usbdevfs_hub_portinfo {
};
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
struct
usbdevfs_urb32
{
unsigned
char
type
;
unsigned
char
endpoint
;
...
...
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